我正在尝试实现以下渲染:
但是我不能在蓝色背景上重叠ClipOval(配置文件图标)。这是我的代码:
Widget build(BuildContext context) {
return OrientationBuilder(
builder: (context, orientation) {
return Scaffold(
key: _scaffoldKey,
//empty Appbar will detect that there is a endDrawer, so will add by default a menu icon
body: Column(
children: <Widget>[
AppBarProfile(
height: 150.0,
firstIcon: IconButton(
onPressed: () {
// to open the drawer
_scaffoldKey.currentState.openEndDrawer();
},
icon: Container(
child: Icon(Icons.settings),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
border: Border.all(color: Colors.white),
),
),
),
title: 'My Profile',
child: ClipOval(
child: Container(
color: Colors.white,
height: 100,
width: 100,
child: Container(
margin: const EdgeInsets.all(4),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: TheBaseColors.lightBlue, width: 2),
),
child: Icon(
Icons.person,
size: 80,
color: TheBaseColors.lightBlue,
),
),
),
),
),
Expanded(
child: Text('I am the body of the screen'),
),
],
),
以下是我的AppBAr的代码,它是在一个单独的文件中完成的,因此我可以多次调用它,并根据标题,应用栏的高度等更改所需的值:
class AppBarProfile extends StatelessWidget {
final Widget firstIcon, child;
final String title;
final double height, childHeight;
const AppBarProfile({
Key key,
this.firstIcon,
this.title,
this.height,
this.childHeight,
this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ClipPath(
clipper: _AppBarProfileClipper(childHeight),
child: Container(
padding: const EdgeInsets.only(top: 30.0),
color: TheBaseColors.lightBlue,
height: height,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
// mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Positioned(left: 0, top: 0, child: firstIcon),
Text(
title,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18.0,
color: Colors.white,
),
),
],
),
],
),
),
),
Positioned(
bottom: 60, //50
left: 0,
right: 0,
child: Align(
alignment: Alignment.bottomCenter,
child: child,
),
),
],
);
}
}
class _AppBarProfileClipper extends CustomClipper<Path> {
final double childHeight;
_AppBarProfileClipper(this.childHeight);
@override
Path getClip(Size size) {
var path = Path();
path.moveTo(0, size.height - 40.0);
path.quadraticBezierTo(
size.width / 2, size.height, size.width, size.height - 40.0);
path.lineTo(size.width, 0);
path.lineTo(0, 0);
return path;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}
代码的结果如下:
答案 0 :(得分:1)
这是您最终结果的一种实现,我尝试保留与您代码中相同的参数:
代码
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final Widget firstIcon;
final Widget child;
final String title;
final double height;
final double childHeight;
final Color color;
CustomAppBar({
Key key,
@required this.title,
this.height = 200.0,
@required this.childHeight,
this.color = Colors.black,
@required this.firstIcon,
@required this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox.fromSize(
size: preferredSize,
child: LayoutBuilder(
builder: (context, constraint) {
return Stack(
children: <Widget>[
ClipPath(
clipper: _AppBarProfileClipper(height),
child: Container(
width: double.maxFinite,
height: preferredSize.height - childHeight,
color: color,
alignment: Alignment.topCenter,
child: Row(
children: <Widget>[
if (firstIcon != null) firstIcon,
if (firstIcon != null) Expanded(child: Container()),
Text(
title,
style: Theme.of(context)
.textTheme
.headline6
.copyWith(color: Colors.white),
),
Expanded(child: Container()),
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {},
),
],
),
),
),
Positioned.fill(
child: Align(
alignment: Alignment.bottomCenter,
child: child,
),
),
],
);
},
),
);
}
@override
Size get preferredSize => Size.fromHeight(height);
}
Try the full example on DartPad
我正在使用PreferredSizeWidget
,因此您可以将其直接用作AppBar
中的Scaffold
。
Scaffold(
appBar: CustomAppBar(
title: 'User Profile',
childHeight: 40.0,
firstIcon: firstIconWidget,
child: childWidget,
),
);
答案 1 :(得分:0)
您是否尝试过使用Align小部件?
@override
Widget build(BuildContext context) {
const double profile_side = 200;
const double background_height = 300;
const double widget_height = background_height + profile_side/2;
return Scaffold(
body: Container(
color: Colors.white,
height: widget_height,
child: Stack(
children: [
Container(
color: Colors.blue,
height: background_height,
width: double.infinity,
),
Align(
alignment: Alignment(0.0, 1),
child: Container(
color: Colors.yellow,
height: profile_side,
width: profile_side,
),
),
Align(
alignment: Alignment(0,-0.8),
child: Text('My Profile',style: TextStyle(color: Colors.white,fontWeight: FontWeight.w700,fontSize: 24),),
),
Align(
alignment: Alignment(-0.9, -0.8),
child: Icon(Icons.menu),
),
Align(
alignment: Alignment(0.9, -0.8),
child: Icon(Icons.settings),
),
],
),
),
);
}