gpt4 book ai didi

user-interface - Flutter ListView.builder - 如何以编程方式跳转到某个索引

转载 作者:行者123 更新时间:2023-12-03 02:39:40 24 4
gpt4 key购买 nike

我有一个使用 MaterialApp 构建的屏幕, DefaultTabController , ScaffoldTabBarView .

在这个屏幕中,我有使用 StreamBuilder 从 sqllite 检索元素列表的正文内容.我使用 ListView 精确显示 100 个元素(“有限列表”) .

我的问题,使用 ListView.builder , 这个画面打开时如何跳转到某个索引?

我的主屏幕:

...
ScrollController controller = ScrollController();

@override
Widget build(BuildContext context) {

return MaterialApp(
debugShowCheckedModeBanner : false,
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
backgroundColor: Pigment.fromString(UIData.primaryColor),
elevation: 0,
centerTitle: true,
title: Text(translations.text("quran").toUpperCase()),
bottom: TabBar(
tabs: [
Text("Tab1"),
Text("Tab2"),
Text("Tab3")
],
),
leading: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: InkWell(
child: SizedBox(child: Image.asset("assets/images/home.png"), height: 10, width: 1,),
onTap: () => Navigator.of(context).pop(),
)
),
],
),
),

floatingActionButton: FloatingActionButton(
onPressed: _scrollToIndex,
tooltip: 'Testing Index Jump',
child: Text("GO"),
),

body:
TabBarView(
children: [
Stack(
children: <Widget>[
MyDraggableScrollBar.create(
scrollController: controller,
context: context,
heightScrollThumb: 25,
child: ListView(
controller: controller,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(30, 15, 30, 8),
child: Container(
alignment: Alignment.center,
height: 30,
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: TextField(
style: TextStyle(color: Colors.green),
decoration: new InputDecoration(
contentPadding: EdgeInsets.all(5),
border: InputBorder.none,
filled: true,
hintStyle: new TextStyle(color: Colors.green, fontSize: 14),
prefixIcon: Icon(FontAwesomeIcons.search,color: Colors.green,size: 17,),
hintText: translations.text("search-quran"),
fillColor: Colors.grey[300],
prefixStyle: TextStyle(color: Colors.green)
),
onChanged: (val) => quranBloc.searchSurah(val),
),
)
)
),

//surah list
streamBuilderQuranSurah(context)

],
)
) // MyDraggableScrollBar

],
),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
)
)));
}

Widget streamBuilderQuranSurah(BuildContext ctx){
return StreamBuilder(
stream: quranBloc.chapterStream ,
builder: (BuildContext context, AsyncSnapshot<ChaptersModel> snapshot){
if(snapshot.hasData){

return ListView.builder(
controller: controller,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount:(snapshot.data.chapters?.length ?? 0),
itemBuilder: (BuildContext context, int index) {
var chapter =
snapshot.data.chapters?.elementAt(index);
return chapterDataCell(chapter);
},
);
}
else{

return SurahItemShimmer();
}
},
);
}
...

类(class) MyDraggableScrollBar.dart :
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
import 'package:flutter/material.dart';

class MyDraggableScrollBar {
static Widget create({
@required BuildContext context,
@required ScrollController scrollController,
@required double heightScrollThumb,
@required Widget child,
}) {
return DraggableScrollbar(

alwaysVisibleScrollThumb: true,
scrollbarTimeToFade: Duration(seconds: 3),
controller: scrollController,
heightScrollThumb: heightScrollThumb,
backgroundColor: Colors.green,
scrollThumbBuilder: (
Color backgroundColor,
Animation<double> thumbAnimation,
Animation<double> labelAnimation,
double height, {
Text labelText,
BoxConstraints labelConstraints,
}) {
return InkWell(
onTap: () {},
child: Container(
height: height,
width: 7,
color: backgroundColor,
),
);
},
child: child,
);
}
}

我曾尝试寻找其他解决方案,但似乎不起作用,例如 indexed_list_view只支持无限列表

并且似乎 flutter 仍然没有此功能,请参阅 this issue

任何的想法 ?

最佳答案

一般解决方案:

为了存储可以表示为数字/字符串/字符串列表的任何内容,Flutter 提供了一个强大的易于使用的插件,用于存储需要与键一起存储的值。因此,下次您需要检索甚至更新该值时,您只需要该键即可。

首先,添加 shared_preferences pubspec.yaml 文件的插件,

dependencies:
flutter:
sdk: flutter
shared_preferences: "<newest version>"

运行 flutter pub get从终端或者如果您使用 IntelliJ 只需单击 Packages get (在查看 pubspec.yaml 文件时,您会在屏幕右上角的某处找到它)

成功执行上述命令后,在您的 main.dart 中导入以下文件或有关文件。
  import 'package:shared_preferences/shared_preferences.dart';

现在只需附上 ScrollController给您的 ListView.builder()小部件并确保在用户以任何方式离开应用程序时使用 shared_preferences 将最终/最后一个偏移量与特定键一起存储,并在调用相关小部件的 initState 时设置。

为了知道检测我们应用程序状态的变化并根据它采取行动,我们将继承 WidgetsBindingObserver到我们类。

操作步骤:
  • 沿 扩展 WidgetsBindingObserver 类与 StatefulWidget 的 State 类。
  • 定义一个异步函数 resumeController()作为上述类的函数成员。
  •   Future<void> resumeController() async{
    _sharedPreferences = await SharedPreferences.getInstance().then((_sharedPreferences){
    if(_sharedPreferences.getKeys().contains("scroll-offset-0")) _scrollController= ScrollController(initialScrollOffset:_sharedPreferences.getDouble("scroll-offset-0"));
    else _sharedPreferences.setDouble("scroll-offset-0", 0);
    setState((){});
    return _sharedPreferences;
    });
  • 声明两个变量,一个用于存储和传递滚动 Controller ,另一个用于存储和使用 SharedPreferences 的实例。
  •   ScrollController _scrollController;
    SharedPreferences _sharedPreferences;
  • 调用 resumeController()并将您的类传递给 WidgetsBinding 类中实例对象的 addObserver 方法。
  •   resumeController();
    WidgetsBinding.instance.addObserver(this);
  • 只需将此代码粘贴到类定义中(在其他成员函数之外)
  •  @override
    void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _scrollController.dispose();
    super.dispose();
    }

    @override
    void didChangeAppLifecycleState(AppLifecycleState state) {
    if(state==AppLifecycleState.paused || state==AppLifecycleState.inactive || state==AppLifecycleState.suspending)
    _sharedPreferences.setDouble("scroll-offset-0", _scrollController.offset);
    super.didChangeAppLifecycleState(state);
    }
  • 通过ScrollController()到相关的 Scrollable。

  • 工作示例:
    class MyWidget extends StatefulWidget {
    @override
    _MyWidgetState createState() => _MyWidgetState();
    }

    class _MyWidgetState extends State<MyWidget> with WidgetsBindingObserver{

    //[...]
    ScrollController _scrollController;
    SharedPreferences _sharedPreferences;

    Future<void> resumeController() async{
    _sharedPreferences = await SharedPreferences.getInstance().then((_sharedPreferences){
    if(_sharedPreferences.getKeys().contains("scroll-offset-0")) _scrollController= ScrollController(initialScrollOffset:_sharedPreferences.getDouble("scroll-offset-0"));
    else _sharedPreferences.setDouble("scroll-offset-0", 0);
    setState((){});
    return _sharedPreferences;
    });

    }

    @override
    void initState() {
    resumeController();
    WidgetsBinding.instance.addObserver(this);
    super.initState();
    }

    @override
    void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _scrollController.dispose();
    super.dispose();
    }

    @override
    void didChangeAppLifecycleState(AppLifecycleState state) {
    if(state==AppLifecycleState.paused || state==AppLifecycleState.inactive || state==AppLifecycleState.suspending)
    _sharedPreferences.setDouble("scroll-offset-0", _scrollController.offset);
    super.didChangeAppLifecycleState(state);
    }

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
    appBar: AppBar(
    title: Text("Smart Scroll View"),
    ),
    body: ListView.builder(
    itemCount: 50,
    controller: _scrollController,
    itemBuilder: (c,i)=>
    Padding(
    padding: EdgeInsets.symmetric(horizontal: 24,vertical: 16),
    child: Text((i+1).toString()),
    ),
    ),
    ),
    );
    }
    }

    关于user-interface - Flutter ListView.builder - 如何以编程方式跳转到某个索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56609059/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com