Как перемещаться по той же странице, что и на главной странице.

#flutter #layout #flutter-layout #master-detail

Вопрос:

Я создаю приложение на основе основных деталей и хочу показать его в splitview. Пытаюсь понять, как перенести данные на другую страницу в том же представлении, но не смог. Хотите просмотреть подробные данные на второй странице. Как передавать данные?

Он может быть либо отзывчивым, либо нет. Но я не хочу разрешать, а только использовать заданное состояние и заполнить пробел на странице сведений

изображение

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

Ответ №1:

Я предположил, что вы хотите изменить правую страницу, нажав на виджеты левой карты. У меня было разработано нечто подобное. Я использую IndexedStack для визуализации с правой стороны VerticalSplitView , затем использую поставщика и потребителя для управления отображаемой страницей.

Прежде всего, вам нужно импортировать зависимость от поставщика в pubspec.ymal Вы можете заменить этот код ниже для всего main.dart.

В main.dart вы можете попробовать заменить этот код. Идея в том, что мы собираемся создать IndexedStack , которые будут содержать виджет (страницу, как вы предпочитаете). Затем мы собираемся изменить индекс IndexedStack с помощью Provider и Consumer .

 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 приведенного ниже кода и повторить его.

импорт ‘пакет:flutter/купертино.дарт’;

 class PageData extends ChangeNotifier{
  PageData();

  int _currentPage = 0;

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

  int get currentPage {
    return this._currentPage;
  }
}
 

Счастливого кодирования 🙂

Ответ №2:

если я сейчас хочу разместить кнопку внутри нужного виджета: «добавить новую запись». Эта функция создания новой записи должна создать новую запись, скопировав все данные с текущей страницы на новую запись с новым идентификатором записи. В той же функции он затем должен перейти в новое сообщение, чтобы отредактировать копию комментария в копии текущего сообщения. Нравится:

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