Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请问如何在顶部加载了数据以后保持位置不变? #64

Closed
yzxh24 opened this issue Nov 23, 2023 · 4 comments
Closed

请问如何在顶部加载了数据以后保持位置不变? #64

yzxh24 opened this issue Nov 23, 2023 · 4 comments
Labels
bug Something isn't working

Comments

@yzxh24
Copy link

yzxh24 commented Nov 23, 2023

Platforms

Android, iOS

Description

我希望用户在往上滚动到 ListView 顶部的时候加载一些历史数据,测试发现当给数组添加了新内容时列表会直接跳到最顶上,而我想要的效果是历史数据在顶部加载出来了,但是当前位置不变,继续往上滚动的时候再开始显示新加载的历史数据,比如下面的图:

Simulator Screenshot - iPhone 15 Pro - 2023-11-23 at 13 31 51
这是默认的列表。

Simulator Screenshot - iPhone 15 Pro - 2023-11-23 at 13 32 11
当我点击了右下角的 + 号按钮后依次添加了 -1、-2、-3、-4 四条数据。

我希望的效果是添加数据时当前位置不变动,即 -1、-2、-3、-4 这四条在顶部,等继续向上滚动时才出现。

My code

import 'package:flutter/material.dart';
import 'package:scrollview_observer/scrollview_observer.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomeTest(),
    );
  }
}

class HomeTest extends StatefulWidget {
  const HomeTest({Key? key}) : super(key: key);

  @override
  State<HomeTest> createState() => _HomeTestState();
}

class _HomeTestState extends State<HomeTest> {
  List<String> list = List.generate(100, (index) => index.toString());

  late ScrollController controller;
  late ListObserverController observerController;
  late ChatScrollObserver chatScrollObserver;

  @override
  void initState() {
    super.initState();

    controller = ScrollController();
    observerController = ListObserverController(controller: controller);
    chatScrollObserver = ChatScrollObserver(observerController)
    // 超过该偏移量才会触发保持当前聊天位置的功能
      ..fixedPositionOffset = 5
      ..toRebuildScrollViewCallback = () {
        // 这里可以重建指定的滚动视图即可
        setState(() {});
      };
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListViewObserver(
        controller: observerController,
        child: ListView(
          controller: controller,
          children: list.map((e) {
            return SizedBox(
              height: 100,
              child: Center(
                child: Text(e),
              ),
            );
          }).toList()
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          chatScrollObserver.standby();
          setState(() {
            list.insert(0, '-1');
            list.insert(0, '-2');
            list.insert(0, '-3');
            list.insert(0, '-4');
          });
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

Try do it

No response

@LinXunFeng
Copy link
Member

设置这个

fixedPositionOffset = -1

@yzxh24
Copy link
Author

yzxh24 commented Nov 23, 2023

设置这个

fixedPositionOffset = -1

我设置了一下,添加数据后依然会跳到顶部,我将列表拉到了很靠下的地方再添加数据,发现列表会跳动一下。

同时我尝试设置了 cacheJumpIndexOffset = false 还是一样的结果。

下面是我的测试代码:

import 'package:flutter/material.dart';
import 'package:scrollview_observer/scrollview_observer.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomeTest(),
    );
  }
}

class HomeTest extends StatefulWidget {
  const HomeTest({Key? key}) : super(key: key);

  @override
  State<HomeTest> createState() => _HomeTestState();
}

class _HomeTestState extends State<HomeTest> {
  List<String> list = List.generate(100, (index) => index.toString());

  late ScrollController controller;
  late ListObserverController observerController;
  late ChatScrollObserver chatScrollObserver;

  @override
  void initState() {
    super.initState();

    controller = ScrollController();
    observerController = ListObserverController(controller: controller)..cacheJumpIndexOffset = false;
    chatScrollObserver = ChatScrollObserver(observerController)
      ..fixedPositionOffset = -1;
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListViewObserver(
        controller: observerController,
        child: ListView.builder(
          itemCount: list.length,
          physics: ChatObserverBouncingScrollPhysics(observer: chatScrollObserver),
          controller: controller,
          itemBuilder: (context, index) {
            return SizedBox(
              height: 100,
              child: Center(
                child: Text(list[index]),
              )
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          chatScrollObserver.standby();
          setState(() {
            list.insert(0, '-1');
            list.insert(0, '-2');
            list.insert(0, '-3');
            list.insert(0, '-4');
          });
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

@LinXunFeng
Copy link
Member

确实有这个问题,在 item 高度相近的情况下,更新数据并 setStateviewport 并没有更新高度,你可以先用下面的方式临时解决问题,后面我再研究一下

class _HomeTestState extends State<HomeTest> {
  ...
+  bool isUpdate = false;
  ...

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
+          Expanded(child: _buildListView()),
+          SizedBox(height: isUpdate ? 0.000001 : 0.000002),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
+          // changeCount需要跟你更新的数据量对应上
+          chatScrollObserver.standby(changeCount: 4);
+          isUpdate = !isUpdate;
          setState(() {
            list.insert(0, '-1');
            list.insert(0, '-2');
            list.insert(0, '-3');
            list.insert(0, '-4');
          });
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

@LinXunFeng LinXunFeng added the bug Something isn't working label Nov 24, 2023
@LinXunFeng
Copy link
Member

请更新至 1.18.2 版本,你需要做的事:

  1. 保持你原来的布局写法
  2. standy 方法的 changeCount 参数需传入相应的更新数:chatScrollObserver.standby(changeCount: 4);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants