Flutter 如何在同一页面中导航母版详细信息页面颤振

Flutter 如何在同一页面中导航母版详细信息页面颤振,flutter,layout,flutter-layout,master-detail,Flutter,Layout,Flutter Layout,Master Detail,我正在构建一个基于主细节的应用程序,我想在splitview中显示。试图了解如何将数据推送到同一视图中的另一页,但无法。希望在第二页中包含详细信息数据。如何推送数据 它可能是响应性的,也可能不是。但我不想解决,但只使用SET状态并在细节页面中填充空白 类MyHomePage扩展StatefulWidget{ MyHomePage({Key,this.title}):超级(Key:Key); 最后的字符串标题; @凌驾 _MyHomePageState createState()=>\u MyH

我正在构建一个基于主细节的应用程序,我想在splitview中显示。试图了解如何将数据推送到同一视图中的另一页,但无法。希望在第二页中包含详细信息数据。如何推送数据

它可能是响应性的,也可能不是。但我不想解决,但只使用SET状态并在细节页面中填充空白

类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
类_MyHomePageState扩展状态{
@凌驾
void initState(){
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:正文(
widget.title,
样式:TextStyle(颜色:Colors.black),
),
背景颜色:颜色。透明,
海拔:0,
),
主体:填充物(
填充:常数边集全部(8.0),
子:垂直拆分视图(
左:ListView.builder(itemCount:12,
itemBuilder:(上下文,索引){
回程卡(
孩子:InkWell(
飞溅颜色:颜色。蓝色。带有alpha(30),
onTap:(){
//push(context,MaterialPageRoute(builder:(context)=>newyapiekle());
},
子:容器(
孩子:填充(
填充:所有边缘设置(12.0),
孩子:排(
mainAxisAlignment:mainAxisAlignment.center,
//将列内容垂直居中,
crossAxisAlignment:crossAxisAlignment.center,
儿童:[
扩大(
孩子:ListTile(
前导:Image.network(“https://picsum.photos/200/300"),
标题:文本(“标题”),
字幕:文本(“字幕”),
),
//垫片(),
],
),
),
),
),
);
}
),
右:集装箱(
装饰:盒子装饰(
边框:边框。全部(颜色:颜色。黑色),
),
儿童:中心(
孩子:我的标志(
尺码:256,
)),
),
),
),
);
}
}
类VerticalSplitView扩展StatefulWidget{
最后一个小部件离开;
最终权利;
最终倍率;
常量垂直拆分视图(
{Key Key,@required this.left,@required this.right,this.ratio=0.5})
:assert(左!=null),
断言(右!=null),
断言(比率>=0),
断言(比率_VerticalSplitViewState();
}
类_VerticalSplitViewState扩展状态{
最终分割宽度=16.0;
//从0-1
双u比;
双最大宽度;
获取_width1=>_ratio*_maxWidth;
获取_width2=>(1-_比率)*\u maxWidth;
@凌驾
void initState(){
super.initState();
_ratio=widget.ratio;
}
@凌驾
小部件构建(构建上下文){
返回LayoutBuilder(生成器:(上下文,框约束){
断言(_比率=0);
如果(_maxWidth==null)_maxWidth=constraints.maxWidth-_dividerWidth;
if(_maxWidth!=constraints.maxWidth){
_maxWidth=constraints.maxWidth-\u dividerWidth;
}
返回大小框(
宽度:constraints.maxWidth,
孩子:排(
儿童:[
大小盒子(
宽度:_宽度1,
孩子:widget.left,
),
手势检测器(
行为:HitTestBehavior.transparent,
孩子:大小盒子(
宽度:_分隔宽度,
高度:constraints.maxHeight,
子:旋转变换(
子:图标(图标。拖动手柄),
转弯:始终停止转弯(0.25),
),
),
onPanUpdate:(DragUpdate详细信息){
设置状态(){
_比率+=details.delta.dx/_maxWidth;
如果(_比率>1)
_比率=1;
否则,如果(_比率<0.0)_比率=0.0;
});
},
),
大小盒子(
宽度:_宽度2,
孩子:对,
),
],
),
);
});
}
}

我假设您希望通过单击左边的卡片小部件来更改右边的页面。我已经开发了类似的东西。我正在使用
IndexedStack
VerticalSplitView
的右边进行渲染,然后使用提供者和使用者来控制页面的显示

首先,您需要在pubspec.ymal中导入依赖项 您可以将下面的代码替换为整个main.dart

在main.dart中,您可以尝试替换此代码。我们的想法是创建包含小部件的
IndexedStack
(您喜欢的页面)。然后,我们将使用
提供程序
消费者
更改
IndexedStack
的索引

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_indexed_stack/page_data.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) {
          var pageData = PageData();
          return pageData;
        }),
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  // Set required page same as list length in left of VerticalSplitView
  List<Widget> pages = [Text('Page1'), Text('Page2'), Text('Page3'),
    Text('Page4'), Text('Page5'), Text('Page6'), Text('Page7'),
    Text('Page8'), Text('Page9'), Text('Page10'), Text('Page11'),
    Text('Page12'), ];

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          widget.title,
          style: TextStyle(color: Colors.black),
        ),
        backgroundColor: Colors.transparent,
        elevation: 0,
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: VerticalSplitView(

          left: ListView.builder( itemCount: 12,
              itemBuilder: (context, index) {
                return Card(
                  child: InkWell(
                    splashColor: Colors.blue.withAlpha(30),
                    onTap: () {
                      // Set the current page for change page on the right side.
                      Provider.of<PageData>(context, listen: false).setCurrentTab(index);
                    },
                    child: Container(
                      child: Padding(
                        padding: EdgeInsets.all(12.0),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          //Center Column contents vertically,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: <Widget>[

                            Expanded(

                              child: ListTile(
                                  leading: Image.network("https://picsum.photos/200/300"),

                                  title: Text("Title"),
                                  subtitle: Text("Subtitle")),

                            ),
                            //Spacer(),

                          ],
                        ),
                      ),
                    ),
                  ),
                );

              }
          ),

          right: Consumer<PageData>(
            builder: (context, pageData, child) {
              return Container(
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.black),
                  ),
                  child: IndexedStack(
                    children: pages,
                    index: pageData.currentPage,
                  )
              );
            },
          ),
        ),
      ),
    );
  }
}

class VerticalSplitView extends StatefulWidget {
  final Widget left;
  final Widget right;
  final double ratio;

  const VerticalSplitView(
      {Key key, @required this.left, @required this.right, this.ratio = 0.5})
      : assert(left != null),
        assert(right != null),
        assert(ratio >= 0),
        assert(ratio <= 1),
        super(key: key);

  @override
  _VerticalSplitViewState createState() => _VerticalSplitViewState();
}

class _VerticalSplitViewState extends State<VerticalSplitView> {
  final _dividerWidth = 16.0;

  //from 0-1
  double _ratio;
  double _maxWidth;

  get _width1 => _ratio * _maxWidth;

  get _width2 => (1 - _ratio) * _maxWidth;

  @override
  void initState() {
    super.initState();
    _ratio = widget.ratio;
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, BoxConstraints constraints) {
      assert(_ratio <= 1);
      assert(_ratio >= 0);
      if (_maxWidth == null) _maxWidth = constraints.maxWidth - _dividerWidth;
      if (_maxWidth != constraints.maxWidth) {
        _maxWidth = constraints.maxWidth - _dividerWidth;
      }

      return SizedBox(
        width: constraints.maxWidth,
        child: Row(
          children: <Widget>[
            SizedBox(
              width: _width1,
              child: widget.left,
            ),
            GestureDetector(
              behavior: HitTestBehavior.translucent,
              child: SizedBox(
                width: _dividerWidth,
                height: constraints.maxHeight,
                child: RotationTransition(
                  child: Icon(Icons.drag_handle),
                  turns: AlwaysStoppedAnimation(0.25),
                ),
              ),
              onPanUpdate: (DragUpdateDetails details) {
                setState(() {
                  _ratio += details.delta.dx / _maxWidth;
                  if (_ratio > 1)
                    _ratio = 1;
                  else if (_ratio < 0.0) _ratio = 0.0;
                });
              },
            ),
            SizedBox(
              width: _width2,
              child: widget.right,
            ),
          ],
        ),
      );
    });
  }
}
 
快乐编码:)

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_indexed_stack/page_data.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) {
          var pageData = PageData();
          return pageData;
        }),
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  // Set required page same as list length in left of VerticalSplitView
  List<Widget> pages = [Text('Page1'), Text('Page2'), Text('Page3'),
    Text('Page4'), Text('Page5'), Text('Page6'), Text('Page7'),
    Text('Page8'), Text('Page9'), Text('Page10'), Text('Page11'),
    Text('Page12'), ];

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          widget.title,
          style: TextStyle(color: Colors.black),
        ),
        backgroundColor: Colors.transparent,
        elevation: 0,
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: VerticalSplitView(

          left: ListView.builder( itemCount: 12,
              itemBuilder: (context, index) {
                return Card(
                  child: InkWell(
                    splashColor: Colors.blue.withAlpha(30),
                    onTap: () {
                      // Set the current page for change page on the right side.
                      Provider.of<PageData>(context, listen: false).setCurrentTab(index);
                    },
                    child: Container(
                      child: Padding(
                        padding: EdgeInsets.all(12.0),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          //Center Column contents vertically,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: <Widget>[

                            Expanded(

                              child: ListTile(
                                  leading: Image.network("https://picsum.photos/200/300"),

                                  title: Text("Title"),
                                  subtitle: Text("Subtitle")),

                            ),
                            //Spacer(),

                          ],
                        ),
                      ),
                    ),
                  ),
                );

              }
          ),

          right: Consumer<PageData>(
            builder: (context, pageData, child) {
              return Container(
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.black),
                  ),
                  child: IndexedStack(
                    children: pages,
                    index: pageData.currentPage,
                  )
              );
            },
          ),
        ),
      ),
    );
  }
}

class VerticalSplitView extends StatefulWidget {
  final Widget left;
  final Widget right;
  final double ratio;

  const VerticalSplitView(
      {Key key, @required this.left, @required this.right, this.ratio = 0.5})
      : assert(left != null),
        assert(right != null),
        assert(ratio >= 0),
        assert(ratio <= 1),
        super(key: key);

  @override
  _VerticalSplitViewState createState() => _VerticalSplitViewState();
}

class _VerticalSplitViewState extends State<VerticalSplitView> {
  final _dividerWidth = 16.0;

  //from 0-1
  double _ratio;
  double _maxWidth;

  get _width1 => _ratio * _maxWidth;

  get _width2 => (1 - _ratio) * _maxWidth;

  @override
  void initState() {
    super.initState();
    _ratio = widget.ratio;
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, BoxConstraints constraints) {
      assert(_ratio <= 1);
      assert(_ratio >= 0);
      if (_maxWidth == null) _maxWidth = constraints.maxWidth - _dividerWidth;
      if (_maxWidth != constraints.maxWidth) {
        _maxWidth = constraints.maxWidth - _dividerWidth;
      }

      return SizedBox(
        width: constraints.maxWidth,
        child: Row(
          children: <Widget>[
            SizedBox(
              width: _width1,
              child: widget.left,
            ),
            GestureDetector(
              behavior: HitTestBehavior.translucent,
              child: SizedBox(
                width: _dividerWidth,
                height: constraints.maxHeight,
                child: RotationTransition(
                  child: Icon(Icons.drag_handle),
                  turns: AlwaysStoppedAnimation(0.25),
                ),
              ),
              onPanUpdate: (DragUpdateDetails details) {
                setState(() {
                  _ratio += details.delta.dx / _maxWidth;
                  if (_ratio > 1)
                    _ratio = 1;
                  else if (_ratio < 0.0) _ratio = 0.0;
                });
              },
            ),
            SizedBox(
              width: _width2,
              child: widget.right,
            ),
          ],
        ),
      );
    });
  }
}
 
class PageData extends ChangeNotifier{
  PageData();

  int _currentPage = 0;

  void setCurrentTab(int index){
    this._currentPage = index;
    notifyListeners();
  }

  int get currentPage {
    return this._currentPage;
  }
}