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

Saving the items order #31

Closed
RoyalCoder88 opened this issue Mar 17, 2022 · 13 comments
Closed

Saving the items order #31

RoyalCoder88 opened this issue Mar 17, 2022 · 13 comments
Labels
help wanted Extra attention is needed

Comments

@RoyalCoder88
Copy link

Hi Karvulf,

Can you please add the feature on how to save the order of times, so for the next time the user gets the list to have the order he saved?
Or can you guide me how to achieve this, please?

Thanks in advance!

@karvulf karvulf added the help wanted Extra attention is needed label Mar 18, 2022
@karvulf
Copy link
Owner

karvulf commented Mar 18, 2022

Hi @RoyalCoder88,

I am not sure what you exactly want to know.
Do you want to know how you could update the order of your items, when you reordered them?

In my read.me-file I have an example with a list of fruits.
Or you could look in my folder example. There are some more examples when I update the list.

I hope that helps.

@RoyalCoder88
Copy link
Author

Hi @RoyalCoder88,

I am not sure what you exactly want to know. Do you want to know how you could update the order of your items, when you reordered them?

In my read.me-file I have an example with a list of fruits. Or you could look in my folder example. There are some more examples when I update the list.

I hope that helps.

Hi thanks,
Basically what I want to achieve is to save the order of grid items on reorder, so when I get back into the app to the items to be ordered by previous reorder time.

Saving the order of items somehow.
Thanks!

@karvulf
Copy link
Owner

karvulf commented Mar 18, 2022

Sounds like you want to save that to your local storage.
I don't know how your items look, but generally if you want consistently save the order, your items need something like an id for the order or you save them in a list with the correct order.

You could look for a package like SharedPreferences to save your data. @RoyalCoder88

@RoyalCoder88
Copy link
Author

@karvulf I'm using SharedPreferences but can you guide how to achieve saving the order, please?

@karvulf
Copy link
Owner

karvulf commented Mar 18, 2022

Do you have some code snippets for me? Or do you need some guides from scratch? @RoyalCoder88

@RoyalCoder88
Copy link
Author

RoyalCoder88 commented Mar 18, 2022

@karvulf

My item code:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
//import '/../constant/constant.dart';
import 'package:lottie/lottie.dart';

import '../pages/settings/settingGeneral.dart';
import '../widgets/menuGrid.dart';

class GridMenuItem2 extends StatelessWidget {
  GridMenuItem2({
    required this.color,
    required this.animId,
    required this.category,
    required this.activeAnim,
    required this.menuId,
    required this.newIndex,
    required this.oldIndex,
    Key? key,
  }) : super(key: key);

  final String menuId;
  final Color color;
  final String animId;
  final String category;
  final bool activeAnim;
  int newIndex = 0;
  int oldIndex = 0;
  int get oindex => oldIndex;

  set oindex(int value) {
    oldIndex = value;
  }

  int get nindex => newIndex;

  set nindex(int value) {
    newIndex = value;
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      key: ValueKey(animId),
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25.0)),
      shadowColor: Colors.black54,
      //color: culoare,
      child: InkWell(
        onTap: () {
          print(menuId);
          Navigator.push(
              context,
              CupertinoPageRoute(
                builder: (context) => const SettingsScreen(),
              ));
        },
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          //verticalDirection: VerticalDirection.down,
          children: <Widget>[
            Lottie.asset('assets/lotties/$category/$animId.json',
                animate: activeAnim, width: 70, height: 70, fit: BoxFit.fill),
            const SizedBox(height: 2.0),
            Text(animId.toUpperCase(),
                style: const TextStyle(
                    fontSize: 10.0, fontWeight: FontWeight.bold))
          ],
        ),
      ),
    );
  }
}

And for the grid I'm using your example, I tried a lot for saving the items ordered on reorder and retrieve them on initState() but so far not so successfully, I think this will be an amazing feature for your package and much appreciated by devs.
Thanks a lot for your help!

@karvulf
Copy link
Owner

karvulf commented Mar 18, 2022

How did you use my example, can you add this code also? @RoyalCoder88

@RoyalCoder88
Copy link
Author

RoyalCoder88 commented Mar 19, 2022

How did you use my example, can you add this code also? @RoyalCoder88

Hi @karvulf

This is my code implementation:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart';
import 'package:flutter_reorderable_grid_view/widgets/reorderable_builder.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../widgets/app_placeholder.dart';
import '../../widgets/progress.dart';
import '../../constant/constant.dart';
import '../../models/menuIGridtem.dart';
import '../../models/user.dart';
import '../../widgets/app_user_info.dart';
import '../../widgets/headerMenuGeneral.dart';
import '../home.dart';
import 'package:sticky_headers/sticky_headers.dart';

class MainMenuUni extends StatefulWidget {
  //final String? currentUserId;
  //const MainMenuUni({Key? key, this.currentUserId}) : super(key: key);

  @override
  _MainMenuUniState createState() {
    return _MainMenuUniState();
  }
}

class _MainMenuUniState extends State<MainMenuUni> {
  //SharedPreferences _preferences =  SharedPreferences.getInstance();
  final _prefs = SharedPreferences.getInstance();
  late List<String> _menuItemsSavedGrid = [];

  final _scaffoldKey = GlobalKey<ScaffoldState>();
  late GloabalUser user;
  bool isLoading = false;

  final lockedIndices = <int>[];
  List<GridMenuItem> menuGridList = [];
  List<SavedMenuItemGrid> listSavedGridMenu = [];

  final ReorderableType reorderableType = ReorderableType.gridView;

  @override
  void initState() {
    getUser();
    initGrid();
    super.initState();
  }

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

  initGrid() async {
    _generateMenuItems();
    getGridData();

    if (_menuItemsSavedGrid.isNotEmpty) {
      // for (int i = 0; i < _menuItemsSavedGrid!.length; i++) {
      //   insertData(i);
      // }
      reorderlistview();
    }
  }

  getGridData() async {
    SharedPreferences _prefs = await SharedPreferences.getInstance();
    _menuItemsSavedGrid = _prefs.getStringList('menuGridItems') ?? ['menuGol'];

    print('MENU GRID LIST: $_menuItemsSavedGrid');
  }

  setGridData() async {
    SharedPreferences _prefs = await SharedPreferences.getInstance();
    _prefs.setStringList('menuGridItems', <String>[menuGridList.toString()]);
  }

  //REORDER LOGIC**************************************************************
  reorderlistview() {
    for (int i = 0; i < menuGridList.length; i++) {
      print(menuGridList[i].menuID);

      setState(() {});
    }
  }

  void _generateMenuItems() {
    menuGridList.addAll(
      [
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'angry',
          category: 'uni',
          animActiva: true,
          oldIndex: 0,
          newIndex: 0,
          key: ValueKey('angry'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'camp-fire',
          category: 'uni',
          animActiva: true,
          oldIndex: 1,
          newIndex: 1,
          key: ValueKey('camp'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'like',
          category: 'uni',
          animActiva: true,
          oldIndex: 2,
          newIndex: 2,
          key: ValueKey('like'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'lol',
          category: 'uni',
          animActiva: true,
          oldIndex: 3,
          newIndex: 3,
          key: ValueKey('lol'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'love',
          category: 'uni',
          animActiva: true,
          oldIndex: 4,
          newIndex: 4,
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'sad',
          category: 'uni',
          animActiva: true,
          oldIndex: 5,
          newIndex: 5,
          key: ValueKey('sad'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'trend',
          category: 'uni',
          animActiva: true,
          oldIndex: 6,
          newIndex: 6,
          key: ValueKey('trend'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'uni_loading',
          category: 'uni',
          animActiva: true,
          oldIndex: 7,
          newIndex: 7,
          key: ValueKey('uni_loading'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'wow',
          category: 'uni',
          animActiva: true,
          oldIndex: 8,
          newIndex: 8,
          key: ValueKey('wow'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'upIn',
          category: 'uni',
          animActiva: true,
          oldIndex: 9,
          newIndex: 9,
          key: ValueKey('upIn'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'upIn2',
          category: 'uni',
          animActiva: true,
          oldIndex: 10,
          newIndex: 10,
          key: ValueKey('upIn2'),
        ),
        GridMenuItem(
          menuID: 'Menu 1',
          colorWidget: Colors.orange,
          idAnim: 'angry',
          category: 'uni',
          animActiva: true,
          oldIndex: 11,
          newIndex: 11,
          key: ValueKey('angry22'),
        ),
      ],
    );
  }

  ///On navigation
//  void _onNavigate(String route) {
//    Navigator.pushNamed(context, route);
 // }

  @override
  Widget build(BuildContext context) {
    return AnimatedTheme(
      duration: const Duration(milliseconds: 100),
      data: Theme.of(context),
      child: Scaffold(
        //backgroundColor: Colors.white,
        appBar: headerMenuGeneral(context,
            isAppTitle: true,
            iscenterTitle: false,
            removeBackButton: false,
            showOnlineToggle: true),
        body: isLoading
            ? circularProgress()
            : SingleChildScrollView(
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  child: Column(
                    children: <Widget>[
                      StickyHeader(
                        content: _meniuSecundar(),
                        header: Container(
                          padding: const EdgeInsets.all(1),
                          //margin: const EdgeInsets.symmetric(horizontal: 2),
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(4),
                            color: Theme.of(context).cardColor,
                            boxShadow: [
                              BoxShadow(
                                color:
                                    Theme.of(context).dividerColor.withOpacity(
                                          .25,
                                        ),
                                spreadRadius: 4,
                                blurRadius: 4,
                                offset: const Offset(
                                  0,
                                  2,
                                ), // changes position of shadow
                              ),
                            ],
                          ),
                          //child: AppUserInfo(
                          //  user: user,
                          //  type: AppUserType.information,
                        //    onPressed: () {},
                       //   ),
                        ),
                      ),
                      const SizedBox(height: 30),
                    ],
                  ),
                ),
              ),
      ),
    );
  }

  _handleReorder(List<OrderUpdateEntity> onReorderList) async {
    for (final reorder in onReorderList) {
      final child = menuGridList.removeAt(reorder.oldIndex);
      menuGridList.insert(reorder.newIndex, child);

      // final childNew = _menuItemsSavedGrid.removeAt(reorder.oldIndex);
      // _menuItemsSavedGrid.insert(reorder.newIndex, 'child');

      print(reorder.oldIndex.toString() +
          " MENU INDX  " +
          reorder.newIndex.toString());
    }
    setGridData();
    //setState(() {});
  }

  Widget _meniuSecundar() {
    return Column(
      children: [
        const SizedBox(height: 20),
        //_statsUser(),
        const SizedBox(height: 16),
        Column(
          children: <Widget>[
            Container(
              height: 700,
              color: Colors.white,
              child: _getReorderableWidget(),
            ),
          ],
        ),
      ],
    );
  }

  Widget _getReorderableWidget() {
    final generatedChildren = List<Widget>.generate(
      menuGridList.length,
      (index) => GridMenuItem(
        menuID: menuGridList[index].menuID,
        colorWidget: Colors.orange,
        idAnim: menuGridList[index].idAnim,
        category: menuGridList[index].category,
        animActiva: menuGridList[index].animActiva,
        oldIndex: menuGridList[index].oldIndex,
        newIndex: menuGridList[index].newIndex,
        key: menuGridList[index].key,
      ),
    );

    switch (reorderableType) {
      case ReorderableType.gridView:
        return ReorderableBuilder(
          children: generatedChildren,
          onReorder: _handleReorder,
          lockedIndices: lockedIndices,
          builder: (children, scrollController) {
            return GridView(
              controller: scrollController,
              children: children,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 4,
                mainAxisSpacing: 4,
                crossAxisSpacing: 8,
              ),
            );
          },
        );

      case ReorderableType.gridViewCount:
        return ReorderableBuilder(
          children: generatedChildren,
          onReorder: _handleReorder,
          lockedIndices: lockedIndices,
          dragChildBoxDecoration: BoxDecoration(
            color: Colors.orange.withOpacity(0.5),
            borderRadius: BorderRadius.circular(25.0),
            boxShadow: [
              BoxShadow(
                color: Colors.grey.withOpacity(0.5),
                spreadRadius: 5,
                blurRadius: 7,
                offset: const Offset(0, 3), // changes position of shadow
              ),
            ],
            //border: BoxBorder.
            //shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25.0)),
          ),
          builder: (children, scrollController) {
            return GridView.count(
              scrollDirection: Axis.vertical,
              controller: scrollController,
              key: const Key('count'),
              children: children,
              crossAxisCount: 3,
            );
          },
        );

      case ReorderableType.gridViewExtent:
        return ReorderableBuilder(
          children: generatedChildren,
          onReorder: _handleReorder,
          lockedIndices: lockedIndices,
          builder: (children, scrollController) {
            return GridView.extent(
              controller: scrollController,
              key: const Key('extent'),
              children: children,
              maxCrossAxisExtent: 200,
            );
          },
        );

      case ReorderableType.gridViewBuilder:
        return ReorderableBuilder(
          children: generatedChildren,
          onReorder: _handleReorder,
          lockedIndices: lockedIndices,
          builder: (children, scrollController) {
            return GridView.builder(
              key: const Key('builder'),
              controller: scrollController,
              itemCount: children.length,
              itemBuilder: (context, index) {
                return children[index];
              },
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 4,
                mainAxisSpacing: 4,
                crossAxisSpacing: 8,
              ),
            );
          },
        );
    }
  }
}

class SavedMenuItemGrid {
  String itemId = "";
  int itemIndex = 0;
}

Thanks in advance!

@karvulf
Copy link
Owner

karvulf commented Mar 19, 2022

Ok I see, there are some points, that are a bit unusual, Im coming back with an example, how you could write this code, so that it works for you @RoyalCoder88

@RoyalCoder88
Copy link
Author

Thanks a lot @karvulf

@karvulf
Copy link
Owner

karvulf commented Mar 19, 2022

Well your example is really difficult to fix like that is, so I created an example that could be similar to your code and I hope it helps.
I ignored some of your widgets just for simplicity. Also if you save data to your shared_preferences, you should never save your widgets. You should save a class, that has the data you need for your widget.
This is the reason, that I created the class GridMenuItemEntity. It saves the list just in the order like the last time, when you reordered the items. When you restart your app, it would read the data from shared_preferences and updates your list.

There are also other things, that should be changed, but I think, this is enough for the beginning. You should try to work a little bit more with flutter to get in touch with the other things. You could also think about a state management like BLoC.

Also you should separate your logic from your widget e. g. loading data from storage.

I am closing this issue, because it was not related to the package. @RoyalCoder88

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart';
import 'package:flutter_reorderable_grid_view/widgets/reorderable_builder.dart';
import 'package:shared_preferences/shared_preferences.dart';

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

  @override
  _MainMenuUniState createState() => _MainMenuUniState();
}

class _MainMenuUniState extends State<MainMenuUni> {
  var menuGridListEntities = List<GridMenuItemEntity>.generate(
    12,
    (index) => GridMenuItemEntity(
      id: 'menu_item_$index',
    ),
  );
  bool isLoading = true;

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

    getGridData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('MainMenuUni')),
      body: isLoading
          ? const CircularProgressIndicator()
          : SingleChildScrollView(
              child: Padding(
                padding: const EdgeInsets.symmetric(vertical: 16),
                child: Column(
                  children: <Widget>[
                    Container(
                      height: 700,
                      color: Colors.white,
                      child: _getReorderableWidget(),
                    ),
                  ],
                ),
              ),
            ),
    );
  }

  Widget _getReorderableWidget() {
    final generatedChildren = List<Widget>.generate(
      menuGridListEntities.length,
      (index) => ColoredBox(
        key: Key(menuGridListEntities[index].id.toString()),
        color: Colors.orange,
        child: Text(
          menuGridListEntities[index].id.toString(),
        ),
      ),
    );

    return ReorderableBuilder(
      children: generatedChildren,
      onReorder: _handleReorder,
      builder: (children, scrollController) {
        return GridView(
          controller: scrollController,
          children: children,
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 4,
            mainAxisSpacing: 4,
            crossAxisSpacing: 8,
          ),
        );
      },
    );
  }

  void _handleReorder(List<OrderUpdateEntity> onReorderList) {
    for (final reorder in onReorderList) {
      final child = menuGridListEntities.removeAt(reorder.oldIndex);
      menuGridListEntities.insert(reorder.newIndex, child);
    }
    setGridData();
  }

  Future<void> getGridData() async {
    SharedPreferences _prefs = await SharedPreferences.getInstance();
    final jsonString = _prefs.getStringList('menuGridItems');

    if (jsonString != null) {
      menuGridListEntities = jsonString
          .map((e) => GridMenuItemEntity.fromJson(
                jsonDecode(e),
              ))
          .toList();
    }

    setState(() {
      isLoading = false;
    });
  }

  Future<void> setGridData() async {
    final jsonList = menuGridListEntities
        .map((e) => jsonEncode(
              e.toJson(),
            ))
        .toList();

    SharedPreferences _prefs = await SharedPreferences.getInstance();
    _prefs.setStringList('menuGridItems', jsonList);
  }
}

class GridMenuItemEntity {
  final String id;

  const GridMenuItemEntity({
    required this.id,
  });

  factory GridMenuItemEntity.fromJson(Map<String, dynamic> json) =>
      GridMenuItemEntity(
        id: json['id'],
      );

  Map<String, dynamic> toJson() => {'id': id};
}

@karvulf karvulf closed this as completed Mar 19, 2022
@RoyalCoder88
Copy link
Author

@karvulf Thanks a lot for your example I managed to remake my entire logic & code, thanks for your feature suggestion and thanks your support is amazing!

@karvulf
Copy link
Owner

karvulf commented Mar 20, 2022

Glad to hear that and no problem!
Happy coding :) @RoyalCoder88

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants