প্রোগ্রামিয়ালি একটি তালিকাভিউয়ের শেষে স্ক্রোল করছে ling


97

আমার একটি স্ক্রোলযোগ্য আছে ListViewযেখানে আইটেমের সংখ্যা গতিশীল পরিবর্তন করতে পারে। যখনই তালিকার শেষের দিকে একটি নতুন আইটেম যুক্ত করা হবে তখন আমি প্রোগ্রাম ListViewথেকে শেষ পর্যন্ত স্ক্রোল করতে চাই । (যেমন, চ্যাট বার্তার তালিকার মতো এমন কিছু যেখানে নতুন বার্তাগুলি শেষে যুক্ত করা যেতে পারে)

আমার অনুমানটি হ'ল আমাকে ScrollControllerআমার Stateঅবজেক্টে একটি তৈরি করতে হবে এবং ম্যানুয়ালি এটি ListViewকন্সট্রাক্টরের কাছে দিতে হবে, তাই আমি পরে কন্ট্রোলারে কল animateTo()/ jumpTo()পদ্ধতিতে কল করতে পারি । তবে, যেহেতু আমি সহজেই সর্বাধিক স্ক্রোল অফসেটটি নির্ধারণ করতে পারি না, তাই কেবল এক scrollToEnd()ধরণের অপারেশন করা অসম্ভব বলে মনে হয় (যেখানে আমি 0.0এটিকে প্রাথমিক অবস্থানে স্ক্রোল করতে সহজেই পার করতে পারি)।

এটি অর্জন করার কোন সহজ উপায় আছে?

ব্যবহার reverse: trueকরা আমার পক্ষে একটি নিখুঁত সমাধান নয়, কারণ আমি চাই ListViewভিউপোর্টের অভ্যন্তরে যখন খুব কম সংখ্যক আইটেম থাকে তখন আইটেমগুলি শীর্ষে সারিবদ্ধ হয় ।

উত্তর:


95

আপনি যদি একটি সঙ্কুচিত আবৃত ব্যবহার করেন তাহলে ListViewসঙ্গে reverse: true, 0.0 থেকে এটি স্ক্রলিং আপনি যা চান তা করতে হবে।

import 'dart:collection';

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Example',
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Widget> _messages = <Widget>[new Text('hello'), new Text('world')];
  ScrollController _scrollController = new ScrollController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Center(
        child: new Container(
          decoration: new BoxDecoration(backgroundColor: Colors.blueGrey.shade100),
          width: 100.0,
          height: 100.0,
          child: new Column(
            children: [
              new Flexible(
                child: new ListView(
                  controller: _scrollController,
                  reverse: true,
                  shrinkWrap: true,
                  children: new UnmodifiableListView(_messages),
                ),
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.add),
        onPressed: () {
          setState(() {
            _messages.insert(0, new Text("message ${_messages.length}"));
          });
          _scrollController.animateTo(
            0.0,
            curve: Curves.easeOut,
            duration: const Duration(milliseconds: 300),
          );
        }
      ),
    );
  }
}

4
এই কৌশলটি। আমার নির্দিষ্ট ক্ষেত্রে তালিকাভুক্তকে সম্প্রসারিত উইজেটে রাখার জন্য আমাকে নেস্টেড কলামগুলি ব্যবহার করতে হয়েছিল, তবে প্রাথমিক ধারণাটি একই।
ইয়াহুন

19
আমি একটি সমাধান অনুসন্ধান করতে এসেছি, কেবল উল্লেখ করতে চেয়েছিলাম যে অন্য উত্তরটি এটি অর্জনের আরও ভাল উপায় হতে পারে - স্ট্যাকওভারফ্লো.com
অনিমেষ জৈন

6
আমি সম্মত, উত্তরটি (যা আমিও লিখেছিলাম) অবশ্যই আরও ভাল।
কলিন জ্যাকসন

4
@ ডেনিস যাতে তালিকাগুলি নীচের দিক থেকে বিপরীত ক্রমে শুরু হয়।
কপসঅনরোড

4
@CopsOnRoad এর উত্তর আরও ভাল দেখাচ্ছে এবং এই উত্তরটি সমাধানের চেয়ে হ্যাকের মতো দেখাচ্ছে।
রূপক এ নেলিয়াত

117

এটি অর্জনের জন্য ব্যবহার ScrollController.jumpTo()বা ScrollController.animateTo()পদ্ধতি।

উদাহরণ:

final _controller = ScrollController();

@override
Widget build(BuildContext context) {
  
  // After 1 second, it takes you to the bottom of the ListView
  Timer(
    Duration(seconds: 1),
    () => _controller.jumpTo(_controller.position.maxScrollExtent),
  );

  return ListView.builder(
    controller: _controller,
    itemCount: 50,
    itemBuilder: (_, __) => ListTile(title: Text('ListTile')),
  );
}

আপনি যদি মসৃণ স্ক্রোলিং করতে চান তবে jumpToউপরের ব্যবহারের পরিবর্তে

_controller.animateTo(
  _controller.position.maxScrollExtent,
  duration: Duration(seconds: 1),
  curve: Curves.fastOutSlowIn,
);

4
ফায়ারবেস রিয়েলটাইম ডেটাবেসের জন্য, আমি এখনও পর্যন্ত 250 মিমি (যা সম্ভবত সত্যিই দীর্ঘ) দিয়ে পালাতে সক্ষম হয়েছি। আমি ভাবছি আমরা কত নিচু যেতে পারি? সমস্যাটি ম্যাক্সস্ক্রোলএক্সেন্টকে নতুন আইটেম যুক্ত হওয়ার সাথে সাথে উইজেট বিল্ডের জন্য অপেক্ষা করতে হবে। সম্পূর্ণরূপে বিল্ডিং থেকে কলব্যাক থেকে গড় সময়কাল কীভাবে প্রোফাইল করবেন?
SacWebDeveloper

4
আপনি কি মনে করেন যে এটি ফায়ারবেস থেকে ডেটা আনার জন্য স্ট্র্যামবিল্ডার ব্যবহার করে সঠিকভাবে কাজ করবে? পাশাপাশি প্রেরণ বোতামে চ্যাট বার্তা যুক্ত করছেন? এছাড়াও ইন্টারনেট সংযোগ যদি ধীর হয় তবে কি এটি কার্যকর হবে? ভাল কিছু যদি আপনি প্রস্তাব করতে পারেন। ধন্যবাদ
জে মুঙ্গারা

@ স্যাকওয়েব ডেভেলপার এই ইস্যু প্লাস ফায়ারবেস সম্পর্কে আপনার দৃষ্টিভঙ্গি কী ছিল?
ইদ্রিস স্ট্যাক

@ আইড্রিসস্ট্যাক আসলে, 250 মিমি স্পষ্টতই অনেকটা দীর্ঘ হয় না, আপডেটটি আসার আগে জাম্পটো হয় happens আমি মনে করি আপডেটের পরে তালিকার দৈর্ঘ্যের তুলনা করা এবং দৈর্ঘ্য আরও বেশি হলে নীচে লাফানোতে আরও ভাল পন্থা হবে।
স্যাকউইব ডেভেলপার

ধন্যবাদ @ স্যাকওয়েব ডেভেলপার, আপনার পদ্ধতির কাজ করে, ফায়ারস্টোরের প্রসঙ্গে আমি আপনাকে আরও একটি প্রশ্ন জিজ্ঞাসা করতে পারি, এটি বিষয়টিকে অবিচ্ছিন্ন করতে পারে। প্রশ্ন কেন এমন হয় যে আমি যখন কারও কাছে একটি বার্তা প্রেরণ করি তবে তালিকাটি স্বয়ংক্রিয়ভাবে নীচে স্ক্রোল হয় না, বার্তাটি শুনতে এবং নীচে স্ক্রোল করার কোনও উপায় আছে কি?
ইদ্রিস স্ট্যাক

13

listViewScrollController.animateTo(listViewScrollController.position.maxScrollExtent) সহজতম উপায়।


4
হাই জ্যাক, আপনার উত্তরের জন্য ধন্যবাদ, আমি বিশ্বাস করি যে আমিও এটি লিখেছি, তাই আবার একই সমাধান যুক্ত করার কোনও সুবিধা নেই আইএমএইচও।
কপসঅনরোড

4
আমি এই পদ্ধতির ব্যবহার করছিলাম তবে আপনাকে এটির জন্য কিছু এমএস অপেক্ষা করতে হবে কারণ অ্যানিমিটটো (...) চালানোর আগে স্ক্রিনটি রেন্ডার করা দরকার। হ্যাক ছাড়াই এটি করতে ভাল অনুশীলনগুলি ব্যবহার করে আমাদের কাছে দুর্দান্ত উপায় রয়েছে।
রেনান কোয়েলহো

4
এটাই সঠিক উত্তর। আপনি যদি বর্তমান লাইনে +100 করেন তবে এটি আপনার তালিকা নীচে স্ক্রোল করবে। তালিকার মতনস্ক্রোলকন্ট্রোলআর পজিশন.ম্যাক্সস্ক্রোলএক্সেন্ট + 100;
রিজওয়ান আনসার

4
@ রেনানকোয়েলহোর অনুপ্রেরণায়, আমি এই টাইমারে কোডের এই লাইনটি 100 মিলিসেকেন্ডের বিলম্বের সাথে মুড়ে ফেলেছি।
ymerdrengene

5

নিখুঁত ফলাফল পেতে আমি কলিন জ্যাকসন এবং সিপসঅনআরডের উত্তরগুলি নীচে একত্রিত করেছি:

_scrollController.animateTo(
                              _scrollController.position.maxScrollExtent,
                              curve: Curves.easeOut,
                              duration: const Duration(milliseconds: 500),
                            );

2

তালিকার নীচে যাবার জন্য আমি অন্য পদ্ধতির ব্যবহার করতে স্ক্রোল নিয়ামকটি ব্যবহার করার চেষ্টা করে আমার এত সমস্যা হয়েছে।

তালিকায় নীচে প্রেরণে কোনও ইভেন্ট তৈরির পরিবর্তে, আমি বিপরীত তালিকাটি ব্যবহার করতে আমার যুক্তি পরিবর্তন করি।

সুতরাং, প্রতিবার আমার কাছে একটি নতুন আইটেম রয়েছে, আমি কেবলমাত্র তালিকার শীর্ষে সন্নিবেশ করিয়ে।

// add new message at the begin of the list 
list.insert(0, message);
// ...

// pull items from the database
list = await bean.getAllReversed(); // basically a method that applies a descendent order

// I remove the scroll controller
new Flexible(
  child: new ListView.builder(
    reverse: true, 
    key: new Key(model.count().toString()),
    itemCount: model.count(),
    itemBuilder: (context, i) => ChatItem.displayMessage(model.getItem(i))
  ),
),

4
আমি যে সমস্যাটি নিয়েই আসছি তা হ'ল যে কোনও স্ক্রোল বার এখন পিছনের দিকে কাজ করে। আমি যখন নীচে স্ক্রোল করি তখন তারা উপরে উঠে যায়।
থিংডিজিটাল

1

আরম্ভতে উইজেটবাইন্ডিং রাখবেন না, পরিবর্তে, আপনাকে এটি এমন পদ্ধতিতে রাখা দরকার যা ডাটাবেস থেকে আপনার ডেটা আনবে। উদাহরণস্বরূপ, এই মত। যদি আরম্ভ করাতে থাকে, তবে এটি কোনও তালিকার scrollcontrollerসাথে সংযুক্ত হবে না।

    Future<List<Message>> fetchMessage() async {

    var res = await Api().getData("message");
    var body = json.decode(res.body);
    if (res.statusCode == 200) {
      List<Message> messages = [];
      var count=0;
      for (var u in body) {
        count++;
        Message message = Message.fromJson(u);
        messages.add(message);
      }
      WidgetsBinding.instance
          .addPostFrameCallback((_){
        if (_scrollController.hasClients) {
          _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
        }
      });
      return messages;
    } else {
      throw Exception('Failed to load album');
    }
   }

-2

আপনি 0.09*heightতালিকার একটি সারির উচ্চতা যেখানে এটি ব্যবহার করতে পারেন এবং _controllerএটির মতো সংজ্ঞায়িত করা হয়েছে_controller = ScrollController();

(BuildContext context, int pos) {
    if(pos != 0) {
        _controller.animateTo(0.09 * height * (pos - 1), 
                              curve: Curves.easeInOut,
                              duration: Duration(milliseconds: 1400));
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.