如何解决在Flutter中滚动CustomMultiChildLayout
我认为这是一个非常简单的布局,它为Flutter初学者带来了一些特别棘手的问题。但是,我正在取得良好的进展,并在此过程中学习了一些经验教训。我已经能够进行自定义布局,其中的小部件绝对定位,因此其中一个小部件在折叠下方对齐。
小部件集合是无状态AuthLayout
小部件。下图显示了AuthLayout
在首次显示时如何对齐其子级。用户应该能够向上滚动页面以显示“折痕以下”的蓝色部分。
就像其他有关此布局的内容一样,我认为这很简单,但到目前为止还没有运气。我已经尝试过CustomScrollView
和SingleChildScrollView
,但是没有将AuthLayout
放在具有硬编码高度的容器中,所以我一直没有办法解决问题。
以下是硬编码容器高度的代码,以允许折叠后的蓝色框滚动到视口中。我想要这种行为,但是要支持一个蓝色的框,其高度在构建时未知。
import 'package:flutter/material.dart';
class AuthPage extends StatelessWidget {
const AuthPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Material(
child: LayoutBuilder(builder: (ctx,constraints) {
return Stack(
children: [
Align(
alignment: Alignment.topCenter,child: Logo(),),SingleChildScrollView(
physics: ClampingScrollPhysics(),child: Container(
height: constraints.maxHeight + 300,// here is the hardcoded height
child: AuthLayout(screenHeight: constraints.maxHeight),],);
}),);
}
}
enum AuthWidgets { form,action,disclaimer }
class AuthLayoutDelegate extends MultiChildLayoutDelegate {
AuthLayoutDelegate({@required screenHeight}) : _screenHeight = screenHeight;
double _overlap = 50;
double _screenHeight;
@override
void performLayout(Size size) {
var formSize = layoutChild(AuthWidgets.form,BoxConstraints.loose(size));
var actionSize = layoutChild(AuthWidgets.action,BoxConstraints.loose(size));
var disclaimerSize =
layoutChild(AuthWidgets.disclaimer,BoxConstraints.loose(size));
if (formSize != null && actionSize != null && disclaimerSize != null) {
// Need the height of the form and action area,minus the overlap
var aboveTheFold = formSize.height + actionSize.height - _overlap;
var offsetY = _screenHeight - aboveTheFold;
offsetY += formSize.height - _overlap;
positionChild(AuthWidgets.action,Offset(0,offsetY));
offsetY += actionSize.height;
positionChild(AuthWidgets.disclaimer,offsetY));
positionChild(AuthWidgets.form,_screenHeight - aboveTheFold));
}
}
@override
bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) {
return false;
}
}
class AuthLayout extends StatelessWidget {
const AuthLayout({@required this.screenHeight,Key key}) : super(key: key);
final double screenHeight;
@override
Widget build(BuildContext context) {
return CustomMultiChildLayout(
delegate: AuthLayoutDelegate(screenHeight: screenHeight),children: [
LayoutId(id: AuthWidgets.action,child: ActionMenu()),LayoutId(id: AuthWidgets.disclaimer,child: Disclaimer()),LayoutId(id: AuthWidgets.form,child: SignInForm()),);
}
}
class Logo extends StatelessWidget {
const Logo({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 64,color: Colors.blue,child: Center(child: Text('Logo')),);
}
}
class SignInForm extends StatelessWidget {
const SignInForm({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 16),child: Container(
color: Colors.red.withOpacity(0.5),height: 350,child: Center(
child: Text('SignInForm'),);
}
}
class Disclaimer extends StatelessWidget {
const Disclaimer({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 300,color: Colors.blue.withOpacity(0.5),child: Center(child: Text('Disclaimer')),);
}
}
class ActionMenu extends StatelessWidget {
const ActionMenu({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 200,color: Colors.green.withOpacity(0.5),child: Center(child: Text('ActionMenu')),);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。