如何在同一页面主从页面 Flutter 中导航

How to Navigate in Same the Page Master Detail page Flutter

我正在构建一个基于主细节的应用程序,我想在拆分视图中显示。试图了解如何将数据推送到同一视图中的另一个页面,但无法做到。想要在第二页中覆盖详细信息数据。如何推送数据?

它可以响应也可以不响应。但我不想解决,只是使用设置状态并在详细信息页面中填充空白

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

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

class _MyHomePageState extends State<MyHomePage> {

  @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: () {
            //Navigator.push(context, MaterialPageRoute(builder: (context) => new yapiekle()) );
          },
          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: Container(
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black),
            ),
            child: Center(
                child: FlutterLogo(
                  size: 256,
                )),
          ),
        ),
      ),
    );
  }
}

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,
            ),
          ],
        ),
      );
    });
  }
}

我假设您想通过单击左侧的卡片小部件来更改右侧的页面。我已经开发了这样的东西。我正在使用 IndexedStackVerticalSplitView 的右侧进行渲染,然后使用提供者和消费者来控制要显示的页面。

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

在main.dart中你可以尝试替换这段代码。我们的想法是创建 IndexedStack 包含小部件(您喜欢的页面)。然后我们将使用 ProviderConsumer.

更改 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,
            ),
          ],
        ),
      );
    });
  }
}
 

您需要为 Provider 创建文件并替换下面的代码。

导入'package:flutter/cupertino.dart';

class PageData extends ChangeNotifier{
  PageData();

  int _currentPage = 0;

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

  int get currentPage {
    return this._currentPage;
  }
}

编码愉快:)

如果我现在想在右侧小部件中放置一个按钮:“添加新的 post”。这个新的 post 函数应该通过将所有数据从当前页面复制到新的 post 并使用新的 post-ID 创建一个新的 post。在相同的功能中,它应该导航到新的 post 以编辑当前 post 副本中的评论副本。喜欢:

ElevatedButton(
    onPressed: () {
                    addPost();
                  }
    )
    addPost() {
    String newId = uuid.v1();
        var newPost = Entry(
              id: newId,
              entry: entryProvider.comment,
            );
            firestoreService.setEntry(newPost);
    
        Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (context) => PostScreen(id: newId)));
        }