質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

iPad

iPadは、Appleがデザインしたタブレット型コンピュータです。iPadアプリケーションは通常Xcode IDEのObjective-Cで書かれますが、iPadアプリケーションを組むためのほかのツールを使うことも可能です。

UI

UIはUser Interfaceの略であり、人間がコンピュータとやりとりをするためのシステムです。

Q&A

2回答

4503閲覧

[Flutter][iPad][UI] 左側のサイドバーを固定し、右側画面のみで遷移を行いたい

inami_173

総合スコア22

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

iPad

iPadは、Appleがデザインしたタブレット型コンピュータです。iPadアプリケーションは通常Xcode IDEのObjective-Cで書かれますが、iPadアプリケーションを組むためのほかのツールを使うことも可能です。

UI

UIはUser Interfaceの略であり、人間がコンピュータとやりとりをするためのシステムです。

0グッド

0クリップ

投稿2020/06/25 03:49

編集2020/06/25 03:52

現状・問題点

現在FlutterでiPad専用のアプリケーションを開発しています。
UIはiPadの設定アプリのようなものを作成したいと思っているのですが、うまくいっていないので質問させていただきます。

iPadの設定アプリのUIはこちらです。

このように左側にサイドバーがあり、右側にその内容を表示するというところまでは出来ているのですが(画像)、右側でNavigator.of.pushを用いた遷移を行うと、サイドバーの上に遷移先の画面が覆いかぶさってしまってしまいます(画像)。

サイドバーを固定したままで遷移させたいのですが、やり方を知っている方がいたら教えていただきたいです????????‍♂️

コード

lib/main.dart

dart

1import 'package:flutter/material.dart'; 2import 'package:health_check/ui/master_detail_container.dart'; 3 4void main() => runApp(MyAppScreen()); 5 6class MyAppScreen extends StatefulWidget { 7 8 _MyAppScreenState createState() => _MyAppScreenState(); 9} 10 11class _MyAppScreenState extends State<MyAppScreen> { 12 13 Widget build(BuildContext context) { 14 return MaterialApp( 15 home: MasterDetailContainer(), 16 ); 17 } 18}

lib/ui/master_detail_container.dart

dart

1import 'package:flutter/material.dart'; 2import 'package:health_check/ui/item.dart'; 3import 'package:health_check/ui/item_details.dart'; 4import 'package:health_check/ui/item_listing.dart'; 5 6class MasterDetailContainer extends StatefulWidget { 7 8 _ItemMasterDetailContainerState createState() => 9 _ItemMasterDetailContainerState(); 10} 11 12class _ItemMasterDetailContainerState extends State<MasterDetailContainer> { 13 Item _selectedItem; 14 15 Widget _sideBar() { 16 return Flexible( 17 flex: 1, 18 child: Material( 19 elevation: 4.0, 20 child: ItemListing( 21 itemSelectedCallback: (item) { 22 setState(() { 23 _selectedItem = item; 24 }); 25 }, 26 selectedItem: _selectedItem, 27 ), 28 ), 29 ); 30 } 31 32 Widget _itemContent() { 33 return Flexible( 34 flex: 3, 35 child: ItemDetails( 36 item: _selectedItem, 37 ), 38 ); 39 40 } 41 42 43 Widget build(BuildContext context) { 44 return Scaffold( 45 body: Row( 46 children: <Widget>[ 47 _sideBar(), 48 _itemContent(), 49 ], 50 ), 51 ); 52 } 53}

lib/ui/item_listing.dart

dart

1import 'package:flutter/material.dart'; 2import 'package:health_check/ui/item.dart'; 3import 'package:health_check/ui/item_details.dart'; 4 5class ItemListing extends StatelessWidget { 6 ItemListing({ 7 this.itemSelectedCallback, 8 this.selectedItem, 9 }); 10 11 final ValueChanged<Item> itemSelectedCallback; 12 final Item selectedItem; 13 14 15 Widget build(BuildContext context) { 16 // return 17 return ListView( 18 children: items.map((item) { 19 return ListTile( 20 title: Text(item.title), 21 onTap: () => itemSelectedCallback(item), 22 selected: selectedItem == item, 23 ); 24 }).toList(), 25 ); 26 } 27}

lib/ui/item_details.dart

dart

1import 'package:flutter/material.dart'; 2import 'package:health_check/ui/item.dart'; 3import 'package:health_check/ui/item1_screen.dart'; 4import 'package:meta/meta.dart'; 5 6class ItemDetails extends StatelessWidget { 7 ItemDetails({ 8 this.item, 9 }); 10 11 final Item item; 12 13 14 Widget build(BuildContext context) { 15 final TextTheme textTheme = Theme.of(context).textTheme; 16 17 final Widget content = Column( 18 mainAxisAlignment: MainAxisAlignment.center, 19 children: [ 20 RaisedButton( 21 child: Text("Button"), 22 color: Colors.orange, 23 textColor: Colors.white, 24 onPressed: () { 25 Navigator.of(context, rootNavigator: true).push( 26 MaterialPageRoute(builder: (context) => Item1Screen())); 27 }, 28 ), 29 Text( 30 item?.title ?? 'No item selected!', 31 style: textTheme.headline, 32 ), 33 Text( 34 item?.subtitle ?? 'Please select one on the left.', 35 style: textTheme.subhead, 36 ), 37 ], 38 ); 39 40 return Scaffold( 41 appBar: AppBar( 42 title: Text('Appbar'), 43 ), 44 body: Center(child: content), 45 ); 46 } 47}

lib/ui/item1_screen.dart

dart

1import 'package:flutter/material.dart'; 2 3class Item1Screen extends StatelessWidget { 4 Item1Screen(); 5 6 7 8 Widget build(BuildContext context){ 9 return Scaffold( 10 appBar: AppBar( 11 title: Text('Item1 detail'), 12 ), 13 body: Center() 14 ); 15 } 16}

lib/ui/item.dart

dart

1import 'package:meta/meta.dart'; 2 3class Item { 4 Item({ 5 this.title, 6 this.subtitle, 7 }); 8 9 final String title; 10 final String subtitle; 11} 12 13final List<Item> items = <Item>[ 14 Item( 15 title: 'Item 1', 16 subtitle: 'This is the first item.', 17 ), 18 Item( 19 title: 'Item 2', 20 subtitle: 'This is the second item.', 21 ), 22 Item( 23 title: 'Item 3', 24 subtitle: 'This is the third item.', 25 ), 26];

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

限られた領域内で遷移を行いたい場合は、Navigator の範囲を限定してあげる必要があると思います。

その場合の実装方法は2つです。

  1. MaterialApp が提供する Navigator とは別に、新たな Navigator を用意して遷移させたい領域を囲む。
  2. MaterialApp が提供する Navigator の範囲を限定する。
1. MaterialApp が提供する Navigator とは別に、新たな Navigator を用意して遷移させたい領域を囲む。

新たな Navigator を用意する場合は、Navigator をそのまま使用するのでも良いですし、同じ要件を満たすことのできる CupertinoTabView を流用する方法もあります。

今回は、 コード量が少なく済む CupertinoTabView を使用する例を載せます。

Widget _itemContent() { return Flexible( flex: 3, child: CupertinoTabView( builder: (_context) => ItemDetails( item: _selectedItem, ), ), ); }
2. MaterialApp が提供する Navigator の範囲を限定する。

MaterialAppbuilder 引数を使用すれば、 Navigator よりも上層で Widget を構成できます。(そのため、Navigator の領域を可変させることも可能)

以下のようになります。

MaterialApp( home: MyHomePage(), builder: (context, child) { return Row( children: <Widget>[ /// _sideBar() に相当する Widget を配置する SideBar(), Expanded(child: child), ], ); }, );

但し、こちらの方法を用いる場合は、以下の点に十分注意してください。

  1. MaterialAppbuild する Widget 上では、setState を呼ぶとリビルド範囲が大きくなるので避けた方が良い。Provider などを使用すると良いと思います。
  2. MaterialApp#builder 内では MediaQuery は取得できないのでMediaQuery を使用してサイドバーの表示を可変させたい場合は使えません。質問内容では、今回は iPad 専用とのことだったのですが、今後そのような要件が出てきた場合には注意が必要です。

投稿2020/06/30 23:43

編集2020/06/30 23:45
HeavenOSK

総合スコア20

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

BottomNavigationBarを各画面で共有する方法ならば、英語ですが以下の記事によくまとめられています。読めるのであればぜひ読んでください。

https://medium.com/coding-with-flutter/flutter-case-study-multiple-navigators-with-bottomnavigationbar-90eb6caa6dbf

ただ、この質問の場合、オリジナルのサイドバーなので同じようにはいかない可能性があります。
個人的には以下のようなアイデアが思い浮かびます。

1.Navigatorによる画面遷移を使わず、ステートによって以下のitemContent()の内容を切り替える。

Dart

1body: Row( 2 children: <Widget>[ 3 sideBar(), 4 itemContent(), 5 ], 6),

2.画面遷移先にも同じようなサイドバーを設ける。
なんとなくこれはやりたくないですね...

ほかにもなにか思いついたら追記します。

投稿2020/06/25 07:24

編集2020/06/25 07:31
tepci

総合スコア419

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

inami_173

2020/06/25 08:24

回答ありがとうございます。 BottomNavigationBarは以前使ったことがあるのでなんとなくわかっているのですが、やっぱ今回のようなケースはオリジナルで作る必要があるんですね…。 1.そうですね。itemContent()の方で遷移するときにNavigator.of.push()のようなアニメーションを右半分だけに対して行う、みたいなことをする必要があるんですかね。。 正直ちょっとコストかかりそうですね???? 2.これも思いついたのですが、右側からサイドバーもまとめてスワイプして出てくるのはどうも気持ち悪くて自分の中で無しになりました。 > ほかにもなにか思いついたら追記します。 ありがとうございます。 よろしくおねがいします????????‍♂️
tepci

2020/06/30 02:09

私なら、画面右半分の部分をPageViewにして、アニメーションはカスタマイズします。 どんなアニメーションを使いたいかで変わってくると思いますが、PageViewを使えばデフォルトでアニメーションがついていますし、ある程度簡単にカスタマイズも可能だと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問