Flutter 非主滚动控制器的颤振web选项卡栏滚动问题
继续 上面提供的解决方案是好的。但我很难在我的项目中实施 预期成果:Flutter 非主滚动控制器的颤振web选项卡栏滚动问题,flutter,flutter-web,Flutter,Flutter Web,继续 上面提供的解决方案是好的。但我很难在我的项目中实施 预期成果: 我已经创建了两个选项卡 在每个选项卡中,我都使用滚动条包装SingleChildScrollView 我不能在两个选项卡中都使用主scrollcontroller,因为这会引发异常:“scrollcontroller连接到多个滚动视图。” 对于选项卡1,我使用主scrollcontroller,对于选项卡2,我创建了scrollcontroller并附加了它 两个选项卡中的小部件都应该可以使用键盘和鼠标滚动 实际结果:
- 我已经创建了两个选项卡
- 在每个选项卡中,我都使用滚动条包装SingleChildScrollView
- 我不能在两个选项卡中都使用主scrollcontroller,因为这会引发异常:“scrollcontroller连接到多个滚动视图。”
- 对于选项卡1,我使用主scrollcontroller,对于选项卡2,我创建了scrollcontroller并附加了它
- 两个选项卡中的小部件都应该可以使用键盘和鼠标滚动
- 对于带有主scrollcontroller的选项卡1,我可以通过键盘和拖动滚动条进行滚动
- 但对于带有非主scrollcontroller的选项卡2,我只能通过拖动滚动条来滚动。此选项卡不响应键盘上下翻页键
- 当键盘键在标签二中使用时,实际上标签一的内容会被滚动
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TabExample(),
);
}
}
class TabExample extends StatefulWidget {
const TabExample({Key key}) : super(key: key);
@override
_TabExampleState createState() => _TabExampleState();
}
class _TabExampleState extends State<TabExample> {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Text('Tab ONE')),
Tab(icon: Text('Tab TWO')),
],
),
title: Text('Tabs Demo'),
),
body: TabBarView(
children: [
WidgetC(),
WidgetD(),
],
),
),
);
}
}
class WidgetC extends StatefulWidget {
const WidgetC({Key key}) : super(key: key);
@override
_WidgetCState createState() => _WidgetCState();
}
class _WidgetCState extends State<WidgetC>
with AutomaticKeepAliveClientMixin<WidgetC> {
List<Widget> children;
@override
void initState() {
children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Container(
height: 100,
width: double.infinity,
color: Colors.blue,
child: Center(child: Text('$i')),
),
),
);
}
super.initState();
}
@override
Widget build(BuildContext context) {
super.build(context);
return Scrollbar(
key: PageStorageKey('WidgetC'),
isAlwaysShown: true,
showTrackOnHover: true,
child: SingleChildScrollView(
child: Column(
children: children,
),
),
);
}
@override
bool get wantKeepAlive => true;
}
class WidgetD extends StatefulWidget {
const WidgetD({Key key}) : super(key: key);
@override
_WidgetDState createState() => _WidgetDState();
}
class _WidgetDState extends State<WidgetD>
with AutomaticKeepAliveClientMixin<WidgetD> {
List<Widget> children;
ScrollController _scrollController;
@override
void initState() {
_scrollController = ScrollController();
children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Container(
height: 100,
width: double.infinity,
color: Colors.green,
child: Center(child: Text('$i')),
),
),
);
}
super.initState();
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
return Scrollbar(
key: PageStorageKey('WidgetD'),
isAlwaysShown: true,
showTrackOnHover: true,
controller: _scrollController,
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: children,
),
),
);
}
@override
bool get wantKeepAlive => true;
}
导入“包装:颤振/材料.省道”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
//此小部件是应用程序的根。
@凌驾
小部件构建(构建上下文){
返回材料PP(
home:TabExample(),
);
}
}
类TabExample扩展StatefulWidget{
const TabExample({Key}):super(Key:Key);
@凌驾
_TabExampleState createState()=>\u TabExampleState();
}
类\u TabExampleState扩展状态{
@凌驾
小部件构建(构建上下文){
返回DefaultTabController(
长度:2,
孩子:脚手架(
appBar:appBar(
底部:选项卡栏(
选项卡:[
选项卡(图标:文本(“选项卡一”),
选项卡(图标:文本(“选项卡二”),
],
),
标题:文本(“选项卡演示”),
),
正文:选项卡视图(
儿童:[
WidgetC(),
WidgetD(),
],
),
),
);
}
}
类WidgetC扩展StatefulWidget{
常量WidgetC({Key}):超级(Key:Key);
@凌驾
_WidgetCState createState()=>\u WidgetCState();
}
类_WidgetCState扩展状态
使用AutomaticEpaLiveClientMixin{
列出儿童名单;
@凌驾
void initState(){
儿童=[];
对于(int i=0;i<20;i++){
children.add(
填充物(
填充:边缘组。对称(垂直:16),
子:容器(
身高:100,
宽度:double.infinity,
颜色:颜色,蓝色,
子:居中(子:文本(“$i”),
),
),
);
}
super.initState();
}
@凌驾
小部件构建(构建上下文){
super.build(上下文);
返回滚动条(
key:PageStorageKey('WidgetC'),
伊莎韦肖恩:没错,
showtrackonhaver:true,
子:SingleChildScrollView(
子:列(
儿童:儿童,,
),
),
);
}
@凌驾
bool get wantKeepAlive=>true;
}
类WidgetD扩展StatefulWidget{
常量WidgetD({Key}):super(Key:Key);
@凌驾
_WidgetDState createState();
}
类_WidgetDState扩展状态
使用AutomaticEpaLiveClientMixin{
列出儿童名单;
ScrollController\u ScrollController;
@凌驾
void initState(){
_scrollController=scrollController();
儿童=[];
对于(int i=0;i<20;i++){
children.add(
填充物(
填充:边缘组。对称(垂直:16),
子:容器(
身高:100,
宽度:double.infinity,
颜色:颜色。绿色,
子:居中(子:文本(“$i”),
),
),
);
}
super.initState();
}
@凌驾
无效处置(){
_scrollController.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
super.build(上下文);
返回滚动条(
key:PageStorageKey('WidgetD'),
伊莎韦肖恩:没错,
showtrackonhaver:true,
控制器:\ u滚动控制器,
子:SingleChildScrollView(
控制器:\ u滚动控制器,
子:列(
儿童:儿童,,
),
),
);
}
@凌驾
bool get wantKeepAlive=>true;
}
这被认为是颤振中的一个缺陷。
请注意以下进展:
对于其他面临相同问题的开发人员,请注意。
为了克服上述问题,我改变了设计布局。我使用Navigationrail小部件代替tabbar视图。这解决了我的问题。
NavigationRail小部件允许我将主滚动控制器连接到多个小部件,而不会给我异常:“ScrollController连接到多个滚动视图。”
示例代码
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key key}) : super(key: key);
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
WidgetC _widgetC = WidgetC();
WidgetD _widgetD = WidgetD();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('NavigationRail Demo'), centerTitle: true),
body: Row(
children: <Widget>[
NavigationRail(
elevation: 8.0,
selectedIndex: _selectedIndex,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: NavigationRailLabelType.all,
groupAlignment: 0.0,
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('Tab ONE'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Tab TWO'),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: _getPageAtIndex(_selectedIndex),
)
],
),
);
}
Widget _getPageAtIndex(int index) {
switch (index) {
case 0:
return _widgetC;
case 1:
return _widgetD;
}
return Container();
}
}
class WidgetC extends StatefulWidget {
const WidgetC({Key key}) : super(key: key);
@override
_WidgetCState createState() => _WidgetCState();
}
class _WidgetCState extends State<WidgetC>
with AutomaticKeepAliveClientMixin<WidgetC> {
List<Widget> children;
@override
void initState() {
children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Container(
height: 100,
width: double.infinity,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
child: Center(child: Text('$i')),
),
),
);
}
super.initState();
}
@override
Widget build(BuildContext context) {
super.build(context);
return Scrollbar(
key: PageStorageKey('WidgetC'),
isAlwaysShown: true,
showTrackOnHover: true,
child: SingleChildScrollView(
child: Column(
children: children,
),
),
);
}
@override
bool get wantKeepAlive => true;
}
class WidgetD extends StatefulWidget {
const WidgetD({Key key}) : super(key: key);
@override
_WidgetDState createState() => _WidgetDState();
}
class _WidgetDState extends State<WidgetD>
with AutomaticKeepAliveClientMixin<WidgetD> {
List<Widget> children;
// ScrollController _scrollController;
@override
void initState() {
// _scrollController = ScrollController();
children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Container(
height: 100,
width: double.infinity,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
child: Center(child: Text('$i')),
),
),
);
}
super.initState();
}
@override
void dispose() {
// _scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
return Scrollbar(
key: PageStorageKey('WidgetD'),
isAlwaysShown: true,
showTrackOnHover: true,
// controller: _scrollController,
child: SingleChildScrollView(
// controller: _scrollController,
child: Column(
children: children,
),
),
);
}
@override
bool get wantKeepAlive => true;
}
import'dart:math';
进口“包装:颤振/材料.省道”;
void main()=>runApp(const MyApp());
///这是主要的应用程序小部件。
类MyApp扩展了无状态小部件{
constmyapp({Key}):超级(Key:Key);
静态常量字符串_title='颤振代码示例';
@凌驾
小部件构建(构建上下文){
返回常数MaterialApp(
标题:_标题,
主页:MyStatefulWidget(),
);
}
}
///这是主应用程序实例化的有状态小部件。
类MyStatefulWidget扩展了StatefulWidget{
constmystatefulwidget({Key}):super(Key:Key);
@凌驾
State createState()=>\u MyStatefulWidgetState();
}
///这是MyStatefulWidget附带的私有状态类。
类_MyStatefulWidgetState扩展状态{
int _selectedIndex=0;
WidgetC_WidgetC=WidgetC();
WidgetD_WidgetD=WidgetD();
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(标题:Text('NavigationRail Demo'),中心标题:true),
正文:世界其他地区(
儿童:[
导航轨道(
标高:8.0,
selectedIndex:\u selectedIndex,
onDestinationSelecte