gpt4 book ai didi

android - Flutter中RelativeLayout的等价物

转载 作者:IT老高 更新时间:2023-10-28 13:15:47 27 4
gpt4 key购买 nike

有没有办法实现类似于 RelativeLayout 的东西?在 Android 上可以吗?

特别是我正在寻找类似于 centerInParent 的内容, layout_below:<layout_id> , layout_above:<layout_id> , 和 alignParentLeft

更多关于RelativeLayout的引用:https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html

编辑:这是一个依赖于 RelativeLayout 的布局示例

Screenshot

所以在上图中,顶部的“tofu's Songs”文本对齐为 centerInParentRelativeLayout 内.而另外两个是 alignParentLeftalignParentRight

在每个单元格上,火图标所在的位置,其底部的点赞数围绕火焰图标的中心对齐。此外,每个单元格的顶部和底部标题分别与图像头像的右侧和顶部和底部对齐。

最佳答案

Flutter 布局通常使用 Column 的树构建。 , RowStack小部件。这些小部件采用构造函数参数,指定子级相对于父级的布局规则,您还可以通过将它们包装在 Expanded 中来影响单个子级的布局。 , Flexible , Positioned , Align , 或 Center小部件。

也可以使用 CustomMultiChildLayout 构建复杂的布局。 .这就是 Scaffold在内部实现,如何在应用程序中使用它的示例出现在 Shrine demo .您也可以使用LayoutBuilderCustomPaint ,或向下一层扩展RenderObjectsector example所示.像这样手动进行布局需要更多的工作,并且会在极端情况下产生更多错误的可能性,所以如果可以的话,我会尝试使用高级布局原语。

回答您的具体问题:

  • AppBar 使用leadingtrailing 参数定位您的应用栏元素。如果您想改用 Row,请使用 MainAxisAlignment.spaceBetweenmainAxisAlignment
  • 使用 Row使用 CrossAxisAlignment.centercrossAxisAlignment 来定位下方的火图标和编号。
  • 使用 Column使用 MainAxisAlignment.spaceBetweenmainAxisAlignment 来定位您的顶部和底部标题。 (您应该考虑使用 ListTile 来布置列表图 block ,但这样做会失去对精确定位的控制。)

这是实现您提供的设计的代码 fragment 。在这个例子中,我使用了 IntrinsicHeight确定歌曲拼贴的高度,但您可以通过将其硬编码为固定高度来提高性能。

screenshot

import 'package:flutter/material.dart';

void main() {
runApp(new MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
brightness: Brightness.dark,
primaryColorBrightness: Brightness.dark,
),
home: new HomeScreen(),
debugShowCheckedModeBanner: false,
);
}
}

class Song extends StatelessWidget {
const Song({ this.title, this.author, this.likes });

final String title;
final String author;
final int likes;

@override
Widget build(BuildContext context) {
TextTheme textTheme = Theme
.of(context)
.textTheme;
return new Container(
margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0),
decoration: new BoxDecoration(
color: Colors.grey.shade200.withOpacity(0.3),
borderRadius: new BorderRadius.circular(5.0),
),
child: new IntrinsicHeight(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top: 4.0, bottom: 4.0, right: 10.0),
child: new CircleAvatar(
backgroundImage: new NetworkImage(
'http://thecatapi.com/api/images/get?format=src'
'&size=small&type=jpg#${title.hashCode}'
),
radius: 20.0,
),
),
new Expanded(
child: new Container(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Text(title, style: textTheme.subhead),
new Text(author, style: textTheme.caption),
],
),
),
),
new Container(
margin: new EdgeInsets.symmetric(horizontal: 5.0),
child: new InkWell(
child: new Icon(Icons.play_arrow, size: 40.0),
onTap: () {
// TODO(implement)
},
),
),
new Container(
margin: new EdgeInsets.symmetric(horizontal: 5.0),
child: new InkWell(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Icon(Icons.favorite, size: 25.0),
new Text('${likes ?? ''}'),
],
),
onTap: () {
// TODO(implement)
},
),
),
],
),
),
);
}
}

class Feed extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new ListView(
children: [
new Song(title: 'Trapadelic lobo', author: 'lillobobeats', likes: 4),
new Song(title: 'Different', author: 'younglowkey', likes: 23),
new Song(title: 'Future', author: 'younglowkey', likes: 2),
new Song(title: 'ASAP', author: 'tha_producer808', likes: 13),
new Song(title: '🌲🌲🌲', author: 'TraphousePeyton'),
new Song(title: 'Something sweet...', author: '6ryan'),
new Song(title: 'Sharpie', author: 'Fergie_6'),
],
);
}
}

class CustomTabBar extends AnimatedWidget implements PreferredSizeWidget {
CustomTabBar({ this.pageController, this.pageNames })
: super(listenable: pageController);

final PageController pageController;
final List<String> pageNames;

@override
final Size preferredSize = new Size(0.0, 40.0);

@override
Widget build(BuildContext context) {
TextTheme textTheme = Theme
.of(context)
.textTheme;
return new Container(
height: 40.0,
margin: const EdgeInsets.all(10.0),
padding: const EdgeInsets.symmetric(horizontal: 20.0),
decoration: new BoxDecoration(
color: Colors.grey.shade800.withOpacity(0.5),
borderRadius: new BorderRadius.circular(20.0),
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: new List.generate(pageNames.length, (int index) {
return new InkWell(
child: new Text(
pageNames[index],
style: textTheme.subhead.copyWith(
color: Colors.white.withOpacity(
index == pageController.page ? 1.0 : 0.2,
),
)
),
onTap: () {
pageController.animateToPage(
index,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 300),
);
}
);
})
.toList(),
),
);
}
}

class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => new _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {

PageController _pageController = new PageController(initialPage: 2);

@override
build(BuildContext context) {
final Map<String, Widget> pages = <String, Widget>{
'My Music': new Center(
child: new Text('My Music not implemented'),
),
'Shared': new Center(
child: new Text('Shared not implemented'),
),
'Feed': new Feed(),
};
TextTheme textTheme = Theme
.of(context)
.textTheme;
return new Stack(
children: [
new Container(
decoration: new BoxDecoration(
gradient: new LinearGradient(
begin: FractionalOffset.topCenter,
end: FractionalOffset.bottomCenter,
colors: [
const Color.fromARGB(255, 253, 72, 72),
const Color.fromARGB(255, 87, 97, 249),
],
stops: [0.0, 1.0],
)
),
child: new Align(
alignment: FractionalOffset.bottomCenter,
child: new Container(
padding: const EdgeInsets.all(10.0),
child: new Text(
'T I Z E',
style: textTheme.headline.copyWith(
color: Colors.grey.shade800.withOpacity(0.8),
fontWeight: FontWeight.bold,
),
),
)
)
),
new Scaffold(
backgroundColor: const Color(0x00000000),
appBar: new AppBar(
backgroundColor: const Color(0x00000000),
elevation: 0.0,
leading: new Center(
child: new ClipOval(
child: new Image.network(
'http://i.imgur.com/TtNPTe0.jpg',
),
),
),
actions: [
new IconButton(
icon: new Icon(Icons.add),
onPressed: () {
// TODO: implement
},
),
],
title: const Text('tofu\'s songs'),
bottom: new CustomTabBar(
pageController: _pageController,
pageNames: pages.keys.toList(),
),
),
body: new PageView(
controller: _pageController,
children: pages.values.toList(),
),
),
],
);
}
}

最后说明:在本例中,我使用了常规 AppBar,但您也可以使用带有固定 SliverAppBarCustomScrollView elevation 为 0.0。这将使内容在您的应用栏后面滚动时可见。让它与 PageView 很好地配合是很棘手的,因为它需要一个固定大小的区域来布置自己。

关于android - Flutter中RelativeLayout的等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44396075/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com