skip to Main Content
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:get/get.dart';
import 'package:mkpos/controller/index_controller.dart';
import 'package:mkpos/controller/invoices_controller.dart';
import 'package:mkpos/utils/constants/colors.dart';
import 'package:mkpos/view/widgets/products/product_add_dialog_widget.dart';

class ProductsScreen extends StatefulWidget {
  ProductsScreen({
    super.key,
    this.refreshPage,
  });
  final bool? refreshPage;

  @override
  State<ProductsScreen> createState() => _ProductsScreenState();
}

class _ProductsScreenState extends State<ProductsScreen> {
  final InvoicesController controller = Get.find();
  final IndexController indexController = Get.find();
  final ScrollController scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return GetBuilder<InvoicesController>(
      initState: (state) => controller.setSkip(controller.products.length),
      builder: (controller) => Scaffold(
        appBar: AppBar(
          title: Text('products'.tr),
          actions: [
            IconButton(
              iconSize: 34,
              color: Colors.green,
              onPressed: () async {
                return showDialog(
                  useSafeArea: false,
                  context: context,
                  builder: (BuildContext context) => Dialog.fullscreen(
                    insetAnimationCurve: Curves.easeInOut,
                    child: ProductAddDialogWidget(
                      controller: indexController,
                      title: 'categories',
                      redirectPage: 'productScreen',
                    ),
                  ),
                );
              },
              icon: const Icon(
                Icons.add_circle_rounded,
              ),
            ),
          ],
        ),
        body: Ink(
            color: Colors.white,
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: TextField(
                    //controller: TextEditingController(text: controller.searchTerm),
                    onChanged: (value) async {
                      await controller.setSearchTerm(value.toString());
                      await controller
                          .getProductsSearchTerm(controller.searchTerm);
                    },
                    decoration: InputDecoration(
                      contentPadding: REdgeInsets.all(5),
                      hintText: 'productSearch'.tr,
                      prefixIcon: const Icon(Icons.search),
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(10.sp),
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: controller.isLoadingProducts
                      ? Center(
                          child: SizedBox(
                            height: MediaQuery.sizeOf(context).height - 250,
                            child: const SpinKitWaveSpinner(
                              color: Colors.blue,
                            ),
                          ),
                        )
                      : Container(
                          height: MediaQuery.of(context).size.height,
                          child: Column(
                            children: [
                              Expanded(
                                child: ListView.separated(
                                  controller: scrollController,
                                  padding: REdgeInsets.symmetric(
                                    horizontal: 2.sp,
                                    vertical: 1.sp,
                                  ),
                                  scrollDirection: Axis.vertical,
                                  separatorBuilder: (context, index) =>
                                      const Divider(height: 0.2),
                                  itemCount: controller.products.length,
                                  itemBuilder: (context, index) {
                                    return ListTile(
                                      contentPadding:
                                          EdgeInsets.only(left: 20, right: 10),
                                      dense: true,
                                      leading: IconButton(
                                        icon: const Icon(
                                          Icons.delete,
                                          size: 24,
                                          color: Colors.red,
                                        ),
                                        onPressed: () async {
                                          await controller.deleteProduct(
                                              controller.products[index].Id);
                                        },
                                      ),
                                      title: Text(
                                        controller.products[index].title,
                                        style: const TextStyle(
                                          color: MKPColors.darkGrey,
                                          fontSize: 15,
                                          fontWeight: FontWeight.bold,
                                        ),
                                      ),
                                      subtitle: Text(
                                        controller.products[index].price
                                                .toStringAsFixed(2) +
                                            ' CHF',
                                        style: TextStyle(
                                          color: Theme.of(context).primaryColor,
                                          fontSize: 12,
                                        ),
                                      ),
                                      trailing: IconButton(
                                        iconSize: 24,
                                        color: Colors.blue,
                                        onPressed: () async {
                                          await controller.addProductToCart(
                                              controller.products[index].Id);
                                        },
                                        icon: const Icon(
                                          Icons.edit,
                                        ),
                                      ),
                                    );
                                  },
                                ),
                              ),
                              Padding(
                                padding: const EdgeInsets.only(bottom: 10),
                                child: SizedBox(
                                  height: 35,
                                  //width: MediaQuery.of(context).size.width / 2.5,
                                  child: controller.skip ==
                                          controller.products.length
                                      ? TextButton.icon(
                                          icon: const Icon(
                                            Icons.check,
                                            color: Colors.white,
                                            size: 20,
                                          ),
                                          style: TextButton.styleFrom(
                                            shape: RoundedRectangleBorder(
                                              borderRadius:
                                                  BorderRadius.circular(20),
                                            ),
                                            backgroundColor: Colors.green,
                                          ),
                                          onPressed: () async {},
                                          label: Text(
                                            'allLoadedMore'.tr,
                                            style: const TextStyle(
                                                color: Colors.white,
                                                fontSize: 13),
                                          ),
                                        )
                                      : TextButton.icon(
                                          icon: const Icon(
                                            Icons.add,
                                            color: Colors.white,
                                            size: 20,
                                          ),
                                          style: TextButton.styleFrom(
                                            shape: RoundedRectangleBorder(
                                              borderRadius:
                                                  BorderRadius.circular(20),
                                            ),
                                            backgroundColor:
                                                Theme.of(context).primaryColor,
                                          ),
                                          onPressed: () async {
                                            await controller.setSkip(
                                                controller.products.length);
                                            controller.getProducts();
                                            scrollController.animateTo(
                                              scrollController
                                                  .position.extentTotal,
                                              duration: const Duration(
                                                  milliseconds: 300),
                                              curve: Curves.easeOut,
                                            );
                                          },
                                          label: Text(
                                            'loadMore'.tr,
                                            style: const TextStyle(
                                                color: Colors.white,
                                                fontSize: 13),
                                          ),
                                        ),
                                ),
                              ),
                            ],
                          ),
                        ),
                ),
              ],
            )),
      ),
    );
  }
}

I’m working on a Flutter application where I have a ListView.separated widget. When I click the "Load More" button, I fetch new data from my controller and append it to the list. However, I want the ListView to automatically scroll down to the bottom to show the newly loaded data.

Here is the code I’m currently using:

onPressed: () async {
  await controller.setSkip(controller.products.length);
  controller.getProducts();

  scrollController.animateTo(
    scrollController.position.extentTotal,
    duration: const Duration(milliseconds: 300),
    curve: Curves.easeOut,
  );
}

Despite using this code, the ListView doesn’t scroll to the bottom as expected. I’ve tried various approaches, but none seem to work. What alternative methods can I try to ensure the ListView scrolls to the bottom when new data is added?

Thank you for your help!

2

Answers


  1. Chosen as BEST ANSWER

    I figured out what the issue was. The problem occurred because I wasn’t using async and await properly in my code. Here’s the corrected code that solved the issue:

    onPressed: () async {
      await controller.setSkip(controller.products.length);
      await controller.getProducts(); // Make sure to await this call
    
      scrollController.animateTo(
        scrollController.position.maxScrollExtent, // Scroll to the end
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeOut,
      );
    }
    
    

    By properly awaiting the getProducts() call, the ListView now correctly scrolls to the bottom after new data is loaded.


  2. Scroll to the end of the list through max scroll extent:

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

    for more about scroll controller

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search