How to update the UI with Get Controller with custom tab view?

  Kiến thức lập trình

my main screen has a tab bar with a custom TabBarView and an icon button that shows a dialog to change the location state to reload the data with the new state

that’s my dialog code that gets my state names from my API server

  void showMyDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          backgroundColor: Colors.white,
          title: const Text(
            "Choose Your Destination",
            style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.w700),
          ),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              SizedBox(
                width: double.maxFinite,
                height: 300.0,
                child: FutureBuilder<void>(
                  future: getStates(),
                  builder: (context, snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting) {
                      return const Center(child: CircularProgressIndicator());
                    } else if (snapshot.hasError) {
                      return Center(child: Text('Error: ${snapshot.error}'));
                    } else if (states == null || states!.isEmpty) {
                      return const Center(child: Text('No states available'));
                    } else {
                      return ListView.builder(
                        itemCount: states!.length,
                        shrinkWrap: true,
                        scrollDirection: Axis.vertical,
                        itemBuilder: (context, index) {
                          return Obx(
                            () => RadioListTile(
                              title: Text(states![index].en_name),
                              value: states![index].en_name,
                              groupValue: userController.newstate.value,
                              onChanged: (value) {
                                userController.newstate.value =
                                    value.toString();
                              },
                            ),
                          );
                        },
                      );
                    }
                  },
                ),
              ),
            ],
          ),
          actions: <Widget>[
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: const Text('Close'),
            ),
            TextButton(
              onPressed: () async {
                Navigator.of(context).pop();
                userController.state.value = userController.newstate.value;
                userController.reloadItems();
              },
              child: const Text('Select'),
            ),
          ],
        );
      },
    );
  }

and that’s my custom Tabbarview related to my user control of my Getx controller to get the new state name that the user selected.

      Expanded(
        child: Obx(
          () => TabBarView(
            controller: _tabController,
            children: tabs.map((tab) {
              return CustomTabView(
                type: tab,
                iconfav: false,
                state: userController.state.value,
              );
            }).toList(),
          ),
        ),
      ),

and that’s my Tabbarview screen it works very well with paging items and displaying the items at my custom. grid every time I change the Tabbar it fetches the items from the start and that’s fine with that, but my issue when the user changes the location don’t know how to change the UI again with the new results I get the new data but I don’t know how to use the box with it and I will add my UI code

  @override
  void initState() {
    super.initState();
    future = fetchItems();
    controller.addListener(() {
      if (controller.position.pixels == controller.position.maxScrollExtent &&
          hasMore) {
        fetchItems();
      }
    });
  }

  Future<void> fetchItems() async {
    if (isLoading) return;
    setState(() {
      isLoading = true;
    });

    try {
      PaginatedCategoryItems paginatedItems = await AppMethods()
          .fetchCategoryItems(widget.type!, widget.state!, currentPage);

      setState(() {
        dataList.addAll(paginatedItems.items);
        currentPage++;
        totalCount = paginatedItems.totalCount;
        hasMore = dataList.length < totalCount;
      });
    } catch (e) {
      // Handle error
    } finally {
      setState(() {
        isLoading = false;
      });
    }
  }

that’s my UI code

  child: FutureBuilder<void>(
    future: future,
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting &&
          dataList.isEmpty) {
        return const Center(child: CircularProgressIndicator());
      } else if (snapshot.hasError) {
        return Center(child: Text('Error: ${snapshot.error}'));
      } else if (dataList.isEmpty) {
        return const Center(child: Text('No items available'));
      } else {
        return NotificationListener<ScrollNotification>(
          onNotification: (scrollInfo) {
            if (scrollInfo.metrics.pixels ==
                    scrollInfo.metrics.maxScrollExtent &&
                hasMore) {
              fetchItems();
            }
            return true;
          },
          child: GridView.custom(
            shrinkWrap: true,
            padding: const EdgeInsets.symmetric(vertical: 10),
            gridDelegate: SliverStairedGridDelegate(
              mainAxisSpacing: 6,
              crossAxisSpacing: 8,
              pattern: [
                const StairedGridTile(0.53, 0.8),
                const StairedGridTile(0.470, 0.8),
                const StairedGridTile(0.470, 0.8),
                const StairedGridTile(0.53, 0.8),
              ],
            ),
            childrenDelegate: SliverChildBuilderDelegate(
              (context, index) {
                if (index == dataList.length) {
                  return const Center(child: CircularProgressIndicator());
                }
                final item = dataList[index];
                return Container(
                  color: WColors.forthColor.withOpacity(0.6),
                  margin: const EdgeInsets.symmetric(horizontal: 2.0),
                  padding: const EdgeInsets.symmetric(vertical: 5.0),
                  child: Stack(
                    children: [
                      ClipRRect(
                        borderRadius: BorderRadius.circular(15),
                        child: InkWell(
                          onTap: () {
                            Get.to(() => const ItemDetails());
                          },
                          child: CachedNetworkImage(
                            imageUrl: item.image_url!,
                            imageBuilder: (context, imageProvider) =>
                                Container(
                              decoration: BoxDecoration(
                                image: DecorationImage(
                                  image: imageProvider,
                                  fit: BoxFit.fitWidth,
                                ),
                              ),
                            ),
                            placeholder: (context, url) =>
                                const CircularProgressIndicator(
                              color: Colors.blue,
                            ),
                            errorWidget: (context, url, error) =>
                                const Icon(Icons.error),
                          ),
                        ),
                      ),
                      Positioned(
                        top: 10,
                        right: 0,
                        child: widget.iconfav
                            ? IconButton(
                                icon: const Icon(
                                  Icons.favorite_border,
                                  color: Colors.white,
                                ),
                                onPressed: () {},
                              )
                            : const SizedBox(),
                      ),
                      Positioned(
                        bottom: 10,
                        left: 10,
                        child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text(
                            '${item.count.toString()} Items',
                            style: const TextStyle(
                              color: Colors.black,
                              fontSize: 18,
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                );
              },
              childCount: dataList.length + (hasMore ? 1 : 0),
            ),
          ),
        );
      }
    },
  ),

and that’s my Getx controller

class UserController extends GetxController {
  static UserController get instance => Get.find();
  RxString state = "".obs;
  RxString newstate = "".obs;

  @override
  void onInit() {
    if (email.isNotEmpty) {
      refreshUser(); // Fetch user data on controller initialization
    }
    super.onInit();
  }


  RxList<dynamic>? categoyItems = [].obs;
  RxInt listLength = 20.obs;
  RxInt offset = 0.obs;
  RxInt currentPage = 1.obs;
  PaginatedCategoryItems? paginatedItems;
  RxBool isLoading = false.obs;
  RxBool hasMore = true.obs;
  RxInt totalCount = 0.obs;
  RxString type = "all".obs;
  List<CategoryItems>? dataList = [];
  final ScrollController controller = ScrollController();

  Future<void> fetchItems() async {
    if (isLoading.value) return;
    isLoading.value = true;
    try {
      PaginatedCategoryItems paginatedItems = await AppMethods()
          .fetchCategoryItems(type.value, state.value, currentPage.value);

      dataList!.addAll(paginatedItems.items);
      currentPage.value++;
      totalCount.value = paginatedItems.totalCount;
      hasMore.value = dataList!.length < totalCount.value;
      categoyItems?.addAll(paginatedItems.items);
    } catch (e) {
      // Handle error
    } finally {
      isLoading.value = false;
    }
  }

  void reloadItems() {
    currentPage.value = 1;
    hasMore.value = true;
    dataList?.clear();
    categoyItems?.clear();
    fetchItems();
  }
}

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT