如何在用户评分栏中保存用户评分? [英] How to save User rating in flutter rating bar?

查看:72
本文介绍了如何在用户评分栏中保存用户评分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试保存用户评分以在用户返回页面时显示它.但是,我陷入困境,无法弄清楚该如何做.评级是有效的,但正如我所说的储蓄无效.所以发生的事情是它总是空的.我真正想要的是,如果用户返回页面,他会看到他的评分,如果他再次评分,并且该评分与上次评分不同,则我让他评分,如果不是,那么按不清除,如果他按清除,评分将删除哪些内容.也可以正常工作.

也许任何人都可以提供帮助.

  lass Ratingpage扩展了StatefulWidget {final int maximumRating;final Function(int)onRatingSelected;Ratingpage(this.onRatingSelected,[this.maximumRating = 5]);@override_RatingpageState createState()=>_RatingpageState();}class _RatingpageState扩展了State< Ratingpage>{int haveusercurrentchoice;int _currentRating = 0;小部件_buildRatingStar(int index){if(index< _currentRating){返回图标(Icons.star,颜色:Colors.yellow,);} 别的 {返回图标(Icons.star,颜色:Colors.white,);}}小部件_buildBody(){最终星星= List< Widget> .generate(this.widget.maximumRating,(index){返回Expanded(子代:GestureDetector(子级:_buildRatingStar(index),onTap:(){setState((){_currentRating =索引;});this.widget.onRatingSelected(_currentRating);},),);});返回行(孩子们: [展开(子级:Row(孩子:星星,),),展开(子代:TextButton(onPressed:(){setState((){_currentRating = 0;});this.widget.onRatingSelected(_currentRating);},子代:文字(清除",样式:TextStyle(颜色:Colors.white),),),),],);}@override窗口小部件build(BuildContext context){返回_buildBody();} 

如果您需要更多信息,请发表评论.

这就是即时通讯页面的调用方式

 容器(宽度:210,高度:94,//颜色:Colors.blue.withOpacity(0.5),子:列(孩子们: [功率onTap:(){setState((){israting = true;});//if(_rating!= null& _amp; _rating> 0){//likevideo(videos.data()['id']);}},孩子:正在分心?容器(高度:50,边距:EdgeInsets.fromLTRB(0,0,5,0),子:列(孩子们: [Ratingpage((rating){setState((){_rating =评分;});如果(_rating!= null&_rating>0){likevideo(videos.data()['id'],_评分);打印(delteuserchoicing);}否则,如果(_rating ==空||_rating == 0){不喜欢(videos.data()['id'],_评分);}}),],),): 图标(Icons.star,大小:37,颜色:视频.data()['喜欢'].contains(uid)?颜色.黄色:Colors.white,),), 

它实际上在一列之内

解决方案

因此,您遇到了在页面之间存储状态的问题,然后又遇到了在应用重启时存储评级的问题.2件分开的东西.您可能只关心前者,但这就是使用

Im trying to saving user rating to displaying it when user comes back to page. But im a lit struggling cannot figure out how to do this. Rating works but as I said the saving not . So what happens is that its always empty. What I actually want is that if user comes back to the page he see his rating and if he rate again and the rating is different the last rating I let him rating and if not then not and if he press clear the rating will be deleting what also works fine.

Maybe anyone can help.

lass Ratingpage extends StatefulWidget {
  final int maximumRating;
  final Function(int) onRatingSelected;

  Ratingpage(this.onRatingSelected, [this.maximumRating = 5]);

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

class _RatingpageState extends State<Ratingpage> {
  int haveusercurrentchoice;

  int _currentRating = 0;

  Widget _buildRatingStar(int index) {
    if (index < _currentRating) {
      return Icon(
        Icons.star,
        color: Colors.yellow,
      );
    } else {
      return Icon(
        Icons.star,
        color: Colors.white,
      );
    }
  }

  Widget _buildBody() {
    final stars = List<Widget>.generate(this.widget.maximumRating, (index) {
      return Expanded(
        child: GestureDetector(
          child: _buildRatingStar(index),
          onTap: () {
            setState(() {
              _currentRating = index;
            });

            this.widget.onRatingSelected(_currentRating);
          },
        ),
      );
    });
    return Row(
      children: [
        Expanded(
          child: Row(
            children: stars,
          ),
        ),
        Expanded(
          child: TextButton(
            onPressed: () {
              setState(() {
                _currentRating = 0;
              });

              this.widget.onRatingSelected(_currentRating);
            },
            child: Text(
              "Clear",
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return _buildBody();
  }

if you need more information please leave a comment.

This is how im calling the page

 Container(
                                width: 210,
                                height: 94,
                                //color: Colors.blue.withOpacity(0.5),
                                child: Column(
                                  children: [
                                    InkWell(
                                      onTap: () {
                                        setState(() {
                                          israting = true;
                                        });
                                        //  if( _rating !=null && _rating >0){
                                        // likevideo(videos.data()['id']);}
                                      },
                                      child: israting
                                          ? Container(
                                              height: 50,
                                              margin: EdgeInsets.fromLTRB(
                                                  0, 0, 5, 0),
                                              child: Column(
                                                children: [
                                                  Ratingpage((rating) {
                                                    setState(() {
                                                      _rating = rating;
                                                    });

                                                    if (_rating != null &&
                                                        _rating > 0) {
                                                      likevideo(
                                                          videos.data()['id'],
                                                          _rating);

                                                      print(delteuserchoicing);
                                                    } else if (_rating ==
                                                            null ||
                                                        _rating == 0) {
                                                      dislike(
                                                          videos.data()['id'],
                                                          _rating);
                                                    }
                                                  }),
                                                ],
                                              ),
                                            )
                                          : Icon(
                                              Icons.star,
                                              size: 37,
                                              color: videos
                                                      .data()['likes']
                                                      .contains(uid)
                                                  ? Colors.yellow
                                                  : Colors.white,
                                            ),
                                    ),

it is inside a column actually

解决方案

So you have an issue of storing state between pages, then you have an issue of storing the rating upon app restart. 2 separate things. You may only be concerned with the former but here's how you would do both with GetX State management and GetStorage for local database storage. Same thing can be accomplished with literally any other state management solution ie. Provider, Riverpod, Bloc etc...

GetStorage is interchangeable with SharedPreferences but I think anyone who has used both would agree GetStorage is a bit easier to use.

To clean up my example I got rid of anything that wasn't necessary for accomplishing what you're asking. Depending on whats going on in the rest of your app, you probably won't need to bring back most or all of the variables I got rid of.

For starters, let's move the logic and variables to a GetX class so they're accessible from anywhere in the app. It also helps clean up your UI code.

class RatingController extends GetxController {
  int currentRating = 0;
  final box = GetStorage();

  @override
  void onInit() { // called whenever we initialize the controller
    super.onInit();
    currentRating = box.read('rating') ?? 0; // initializing current rating from storage or 0 if storage is null
  }

  void updateAndStoreRating(int rating) {
    currentRating = rating;
    box.write('rating', rating); // stores to local database
    update(); // triggers a rebuild of the GetBuilder Widget
  }

  Widget buildRatingStar(int index) {
    if (index < currentRating) {
      return Icon(
        Icons.star,
        color: Colors.yellow,
      );
    } else {
      return Icon(
        Icons.star,
        color: Colors.white,
      );
    }
  }
}

I added a button on this page just for demo purposes. Since this demo includes routing, I'm using Getx for a way easier to do routing also, but it's not at all related or necessary to answer your question. This page can now also be stateless.

class Ratingpage extends StatelessWidget {
  static const id = 'rating_page'; // see GetMaterialApp for this usage

  final controller = Get.find<RatingController>(); // finding the same instance of initialized controller

  Widget _buildBody() {
    final stars = List<Widget>.generate(5, (index) {
      return GetBuilder<RatingController>( // rebuilds when update() is called from GetX class
        builder: (controller) => Expanded(
          child: GestureDetector(
            child: controller.buildRatingStar(index),
            onTap: () {
              controller.updateAndStoreRating(index + 1); // +1 because index starts at 0 otherwise the star rating is offset by one
            },
          ),
        ),
      );
    });
    return Row(
      children: [
        Expanded(
          child: Row(
            children: stars,
          ),
        ),
        Expanded(
          child: TextButton(
            onPressed: () {
              controller.updateAndStoreRating(0);
            },
            child: Text(
              "Clear",
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        _buildBody(),
        ElevatedButton(
          onPressed: () {
            Get.to(() => OtherPage()); // equivalent of Navigator.push....
          },
          child: Text('Other Page'),
        )
      ],
    );
  }
}

Your main method now looks like this because we need to initialize the controller and storage.

void main() async {
  await GetStorage.init();
  Get.put(RatingController());

  runApp(MyApp());
}

And again, only necessary for easier routing, we use GetMaterialApp and define pages there.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Material App',
      home: Ratingpage(),
      getPages: [ // only necessary for routing, not for storage or state management
        GetPage(name: OtherPage.id, page: () => OtherPage()),
        GetPage(name: Ratingpage.id, page: () => Ratingpage()),
      ],
    );
  }
}

EDIT: Added with SharedPreferences due to an unmaintained package conflicting with GetStorage path provider dependency.

Add SharedPreferences prefs; to your GetX class.

This is your update function now.

void updateAndStoreRating(int rating) {
    currentRating = rating;
    prefs.setInt('rating', rating); //SharedPreferences way
    update(); // triggers a rebuild of the GetBuilder Widget
  }

Add an init function in GetX Controller class.

 Future<void> initSp() async {
    prefs = await SharedPreferences.getInstance();
    currentRating = prefs.getInt('rating') ?? 0;
  }

Now your main is a bit different.

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  final controller = Get.put(RatingController());
  await controller.initSp();

  runApp(MyApp());
}

这篇关于如何在用户评分栏中保存用户评分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆