[解決済み] FlutterにおけるRelativeLayoutの等価性
質問
のようなものを実装する方法はありますか?
RelativeLayout
と同じようなものをAndroidで実装する方法はありますか?
特に、私は次のようなものを探しています。
centerInParent
,
layout_below:<layout_id>
,
layout_above:<layout_id>
そして
alignParentLeft
RelativeLayoutの詳細なリファレンスはこちら。 https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html
編集:以下は、レイアウトの例です。
RelativeLayout
つまり、上の画像では、上部にある「quot;豆腐の歌」のテキストは、次のように配置されています。
centerInParent
の中に
RelativeLayout
. 一方、他の2つは
alignParentLeft
であり
alignParentRight
各セルで、炎のアイコンのところに、その下のいいね!の数が炎のアイコンの中心あたりに揃っています。また、各セルの上下のタイトルは、それぞれ画像アバターの右側と上下に並んでいます。
どのように解決するのですか?
Flutterのレイアウトは、通常、ツリー状の
Column
,
Row
そして
Stack
ウィジェットがあります。これらのウィジェットはコンストラクタ引数を取り、親ウィジェットに対して子ウィジェットをどのようにレイアウトするかというルールを指定します。
Expanded
,
Flexible
,
Positioned
,
Align
または
Center
ウィジェットです。
を使って複雑なレイアウトを構築することも可能です。
CustomMultiChildLayout
. このように
Scaffold
は内部で実装されており、アプリでの使用例として
神社のデモ
. また
LayoutBuilder
または
CustomPaint
または、レイヤーを下げて
RenderObject
のように
セクタの例
. このように手動でレイアウトを行うことは、より多くの作業を必要とし、コーナーケースでエラーが発生する可能性が高くなります。
具体的な質問にお答えします。
-
を使用します。
leading
とtrailing
の引数をAppBar
という引数を使って、アプリバー要素を配置します。もしRow
を使いたい場合は、代わりにmainAxisAlignment
のMainAxisAlignment.spaceBetween
. -
を使用します。
Row
とcrossAxisAlignment
のCrossAxisAlignment.center
の下に火のアイコンと数字を配置します。 -
を使用する。
Column
とmainAxisAlignment
のMainAxisAlignment.spaceBetween
を使って、上下のタイトルを配置します。(このときListTile
を使用してリストタイルをレイアウトすることを検討すべきですが、これを行うと正確な位置の制御ができなくなります)。
提供されたデザインを実装するコードスニペットを示します。この例では
IntrinsicHeight
を使って曲のタイルの高さを決めていますが、固定の高さにハードコーディングすることでパフォーマンスを向上させることができます。
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
を使っていますが
CustomScrollView
をピン留めした
SliverAppBar
を持つ
elevation
を0.0に設定します。これにより、アプリ バーの背後にスクロールするコンテンツが表示されるようになります。しかし、これを
PageView
でうまく動作させるのは難しいです。なぜなら、固定サイズの領域がレイアウトされることを期待しているからです。
関連
-
[解決済み] RelativeLayoutにおける幅の割合(%)。
-
[解決済み] Flutterのデバッグバナーを削除するにはどうしたらいいですか?
-
[解決済み] Flutterで16進数の色文字列を使用するにはどうすればよいですか?
-
[解決済み] Flutterで丸みを帯びたボタン/border-radius付きボタンを作成する
-
[解決済み】ConstraintLayoutとRelativeLayoutの違いについて
-
[解決済み】flutterでパッケージ名を変更する方法は?
-
[解決済み] HttpPostによる画像送信
-
[解決済み] 複数のフィルタを持つBroadcastReceiverか、複数のBroadcastReceiverか?
-
[解決済み] Android - Snackbar vs Toast - 使い方と違い。
-
[解決済み] FragmentPagerAdapterのgetItemが呼び出されない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] RecyclerView.Stateを使って、RecyclerViewのスクロール位置を保存するには?
-
[解決済み] AndroidにおけるViewPager2の適切な実装
-
[解決済み] Android Webview - キャッシュを完全に削除する
-
[解決済み] 深くネストされたスタックから離れるとき、Fragmentのバックスタックをクリーンアップする方法はこれで良いのでしょうか?
-
[解決済み] Android Navigation Architecture Component - 現在表示されているフラグメントを取得する
-
[解決済み] バイト配列の画像ファイルをビットマップに変換するには?
-
[解決済み] Android端末がHDPI画面かMDPI画面かを確認する方法は?
-
[解決済み] react nativeアプリのバージョン番号を更新する方法
-
[解決済み] EditTextの右側のDrawableにonClickListenerを設定する [重複] [重複
-
[解決済み] Google Play ストア内部テストのロールアウトが開始できない