#flutter #dart
Вопрос:
Я использую комбинацию «BottomNavigationBar» и «Просмотр страниц» для навигации в моем приложении. Пользователь может либо перейти на следующую страницу, либо воспользоваться панелью навигации.
На одной из моих страниц я хотел бы использовать детектор жестов, который обрабатывает жесты панорамирования как по вертикали, так и по горизонтали.
Я не могу найти способ переопределить обнаружение жестов в просмотре страницы с помощью вложенного детектора жестов. Это означает, что обрабатываются только вертикальные жесты панорамирования, так как горизонтальные заняты просмотром страницы.
Как я могу отключить / переопределить обнаружение жестов просмотра страниц только для этой страницы или только для виджета, не полностью отключая физику прокрутки просмотров страниц?
Я создал упрощенную версию своего приложения, чтобы изолировать проблему, и прикрепил видео проблемы ниже.
Любая помощь будет очень признательна!
Вот код внутри моего main.dart:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: GestureIssueExample(),
);
}
}
class GestureIssueExample extends StatefulWidget {
GestureIssueExample({Key key}) : super(key: key);
@override
_GestureIssueExampleState createState() => _GestureIssueExampleState();
}
class _GestureIssueExampleState extends State<GestureIssueExample> {
int _navigationIndex;
double _xLocalValue;
double _yLocalValue;
PageController _pageController;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
bottomNavigationBar: _buildBottomNavigationBar(),
backgroundColor: Colors.white,
body: PageView(
controller: _pageController,
onPageChanged: _onNavigationPageChanged,
children: [
//Just a placeholder to represent a page to the left of the "swipe cards" widget
_buildSamplePage("Home"),
//Center child of 'PageView', contains a GestureDetector that handles Pan Gestures
//Thanks to the page view however, only vertical pan gestures are detected, while both horizontal and vertical gestures
//need to be handled...
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Local X: ${_xLocalValue.toString()}nLocal Y: ${_yLocalValue.toString()}"),
GestureDetector(
onPanStart: (details) => setState(
() {
this._xLocalValue = details.localPosition.dx;
this._yLocalValue = details.localPosition.dy;
},
),
onPanUpdate: (details) => setState(
() {
this._xLocalValue = details.localPosition.dx;
this._yLocalValue = details.localPosition.dy;
},
),
child: Container(
width: MediaQuery.of(context).size.width * 0.9,
height: 100.0,
color: Colors.red,
alignment: Alignment.center,
child: Text("Slidable Surface",
style: TextStyle(color: Colors.white)),
),
),
],
),
),
//Just a placeholder to represent a page to the right of the "swipe cards" widget
_buildSamplePage("Settings"),
],
),
);
}
@override
void initState() {
super.initState();
this._navigationIndex = 0;
this._pageController = PageController(
initialPage: _navigationIndex,
);
}
Widget _buildSamplePage(String text) {
// This simply returns a container that fills the page,
// with a text widget in its center.
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.grey[900],
alignment: Alignment.center,
child: Text(
text,
style: TextStyle(
color: Colors.white, fontSize: 30.0, fontWeight: FontWeight.bold),
),
);
}
Widget _buildBottomNavigationBar() {
//Returns the bottom navigation bar for the scaffold
return BottomNavigationBar(
backgroundColor: Colors.grey[900],
selectedItemColor: Colors.redAccent,
unselectedItemColor: Colors.white,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home_outlined), label: "Home"),
BottomNavigationBarItem(
icon: Icon(Icons.check_box_outline_blank), label: "Cards"),
BottomNavigationBarItem(
icon: Icon(Icons.settings_outlined), label: "Settings"),
],
currentIndex: _navigationIndex,
onTap: _onNavigationPageChanged,
);
}
void _onNavigationPageChanged(int newIndex) {
//Set the new navigation index for the nav bar
setState(() => this._navigationIndex = newIndex);
//Animate to the selected page
_pageController.animateToPage(
newIndex,
curve: Curves.easeInOut,
duration: Duration(microseconds: 100),
);
}
}
Ответ №1:
Можете ли вы попробовать что-то подобное:
Добавьте эту строку в свой PageView
:
PageView(
...
physics: _navigationIndex == 1 ? NeverScrollableScrollPhysics() : AlwaysScrollableScrollPhysics(),
...
)
Примечание: номер 1
указан потому, что страница с GestureDetector
индексом 1
находится в списке .
Комментарии:
1. Здравствуйте, Андрей, спасибо вам за ваш ответ! Я пробовал это решение, но, к сожалению, оно вызывает другую проблему. Просмотры страниц «currentIndex» обновляются, когда новая страница попадает в центр экрана. Это приводит к остановке перехода на центральную страницу (индекс 1), как только страница проходит центр экрана, в результате чего пользовательский интерфейс застревает между двумя страницами. Пожалуйста, дайте мне знать, если я смогу предоставить дополнительную информацию!
2. Я просто попробовал это на своем телефоне, и это сработало нормально. Пожалуйста, ознакомьтесь с записью: screencast.com/t/U9J0dXSYib , можете ли вы добавить еще одну запись экрана нового выпуска?
3. Эй, Андрей, в этом нет необходимости.. Я только что понял, что причина, по которой предложенное вами решение не работало, заключалась в том, что просмотр страниц в моем исходном приложении использовал другую переменную индекса, которая неправильно обновлялась, когда я устанавливал состояние. Я попробовал ваше решение как в моем тестовом приложении, так и в реальной версии, и оба они теперь работают нормально. Большое вам спасибо за вашу помощь!
4. Нет проблем! Я рад, что помог тебе. Хорошего вам дня. 🙂