📜  Flutter – 可定制的评分栏

📅  最后修改于: 2021-09-02 05:53:56             🧑  作者: Mango

顾名思义,评级栏用于对应用程序内部的内容进行评级。或多或少所有应用程序都使用它们来控制用户对其应用程序的反馈或获得应用程序托管的内容的评级。 IMDB 等应用程序使用它们对电影和电视剧进行评分,Uber 和 Uber 等应用程序使用它们从客户那里获取对其服务的反馈。

在本文中,我们将构建一个具有以下功能的简单应用程序:

  • 水平评级栏
  • 使上面的所有评级条从右向左移动的开关
  • 使评级栏垂直的开关
  • 三种不同的模式来改变第一个评分栏的图标

要构建上述应用程序,请按照以下步骤操作:

  • 将依赖添加到pubspec.yaml 文件中
  • 将依赖项导入到 main.js 中。dart文件
  • 使用StatefulWidget为应用程序提供结构
  • 添加垂直评分栏
  • 添加开关以从右到左 (RTL) 更改评级条的对齐方式
  • 添加一个开关来改变评级栏的对齐方式从水平到垂直
  • 添加 3 种不同的模式来更改 UI 图标。

添加依赖:

要将依赖项添加到pubspec.yaml 文件,可以遵循以下图像:

依赖

导入依赖:

flutter_rating_bar依赖项导入到主文件中。 dart文件,使用以下内容:

import 'package:flutter_rating_bar/flutter_rating_bar.dart';

构建应用程序:

StatefulWidget可用于为应用程序提供一个应用和一个主体来保存内容,如下所示:

Dart
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
  
class _MyAppState extends State {
  var _ratingController = TextEditingController();
  double _rating;
  int _ratingBarMode = 1;
  bool _isRTLMode = false;
  bool _isVertical = false;
  IconData _selectedIcon;
  
  @override
  void initState() {
    _ratingController.text = "3.0";
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
        appBarTheme: AppBarTheme(
          textTheme: TextTheme(
            title: Theme.of(context).textTheme.title.copyWith(
              color: Colors.white,
            ),
          ),
        ),
      ),


Dart
RatingBar(
   initialRating: 3,
   minRating: 1,
   direction: Axis.horizontal,
   allowHalfRating: true,
   itemCount: 5,
   itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
   itemBuilder: (context, _) => Icon(
     Icons.star,
     color: Colors.amber,
   ),
   onRatingUpdate: (rating) {
     print(rating);
   },
);


Dart
mainAxisAlignment: MainAxisAlignment.center,
                   children: [
                     Text(
                       'Switch to RTL Mode',
                       style: TextStyle(
                         fontWeight: FontWeight.w300,
                       ),
                     ),
                     Switch(
                       value: _isRTLMode,
                       onChanged: (value) {
                         setState(() {
                           _isRTLMode = value;
                         });
                       },


Dart
mainAxisAlignment: MainAxisAlignment.center,
                   children: [
                     Text(
                       'Switch to Vertical Bar',
                       style: TextStyle(
                         fontWeight: FontWeight.w300,
                       ),
                     ),
                     Switch(
                       value: _isVertical,
                       onChanged: (value) {
                         setState(() {
                           _isVertical = value;
                         });
                       },
                       activeColor: Colors.amber,
                     ),
                   ],
                 ),


Dart
Widget _ratingBar(int mode) {
   switch (mode) {
     case 1:
       return RatingBar(
         initialRating: 2,
         minRating: 1,
         direction: _isVertical ? Axis.vertical : Axis.horizontal,
         allowHalfRating: true,
         unratedColor: Colors.amber.withAlpha(50),
         itemCount: 5,
         itemSize: 50.0,
         itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
         itemBuilder: (context, _) => Icon(
           _selectedIcon ?? Icons.star,
           color: Colors.amber,
         ),
         onRatingUpdate: (rating) {
           setState(() {
             _rating = rating;
           });
         },
       );
     case 2:
       return RatingBar(
         initialRating: 3,
         direction: _isVertical ? Axis.vertical : Axis.horizontal,
         allowHalfRating: true,
         itemCount: 5,
         ratingWidget: RatingWidget(
           full: _image('assets/heart.png'),
           half: _image('assets/heart_half.png'),
           empty: _image('assets/heart_border.png'),
         ),
         itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
         onRatingUpdate: (rating) {
           setState(() {
             _rating = rating;
           });
         },
       );
     case 3:
       return RatingBar(
         initialRating: 3,
         direction: _isVertical ? Axis.vertical : Axis.horizontal,
         itemCount: 5,
         itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
         itemBuilder: (context, index) {
           switch (index) {
             case 0:
               return Icon(
                 Icons.sentiment_very_dissatisfied,
                 color: Colors.red,
               );
             case 1:
               return Icon(
                 Icons.sentiment_dissatisfied,
                 color: Colors.redAccent,
               );
             case 2:
               return Icon(
                 Icons.sentiment_neutral,
                 color: Colors.amber,
               );
             case 3:
               return Icon(
                 Icons.sentiment_satisfied,
                 color: Colors.lightGreen,
               );
             case 4:
               return Icon(
                 Icons.sentiment_very_satisfied,
                 color: Colors.green,
               );
             default:
               return Container();
           }
         },
         onRatingUpdate: (rating) {
           setState(() {
             _rating = rating;
           });
         },
       );
     default:
       return Container();
   }
 }


Dart
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
  
void main() => runApp(MyApp());
  
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
  
class _MyAppState extends State {
  var _ratingController = TextEditingController();
  double _rating;
  int _ratingBarMode = 1;
  bool _isRTLMode = false;
  bool _isVertical = false;
  IconData _selectedIcon;
  
  @override
  void initState() {
    _ratingController.text = "3.0";
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
        appBarTheme: AppBarTheme(
          textTheme: TextTheme(
            title: Theme.of(context).textTheme.title.copyWith(
              color: Colors.white,
            ),
          ),
        ),
      ),
      home: Builder(
        builder: (context) => Scaffold(
          appBar: AppBar(
            title: Text('GeeksForGeeks'),
            backgroundColor: Colors.green,
          ),
          body: Directionality(
            textDirection: _isRTLMode ? TextDirection.rtl : TextDirection.ltr,
            child: SingleChildScrollView(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: [
                  SizedBox(
                    height: 40.0,
                  ),
                  _heading('Rating Bar'),
                  _ratingBar(_ratingBarMode),
                  SizedBox(
                    height: 20.0,
                  ),
                  _rating != null
                      ? Text(
                    "Rating: $_rating",
                    style: TextStyle(fontWeight: FontWeight.bold),
                  )
                      : Container(),
                  Row(
                    children: [
                      _radio(1),
                      _radio(2),
                      _radio(3),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        'Switch to Vertical Bar',
                        style: TextStyle(
                          fontWeight: FontWeight.w300,
                        ),
                      ),
                      Switch(
                        value: _isVertical,
                        onChanged: (value) {
                          setState(() {
                            _isVertical = value;
                          });
                        },
                        activeColor: Colors.amber,
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        'Switch to RTL Mode',
                        style: TextStyle(
                          fontWeight: FontWeight.w300,
                        ),
                      ),
                      Switch(
                        value: _isRTLMode,
                        onChanged: (value) {
                          setState(() {
                            _isRTLMode = value;
                          });
                        },
                        activeColor: Colors.amber,
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
  
  Widget _radio(int value) {
    return Expanded(
      child: RadioListTile(
        value: value,
        groupValue: _ratingBarMode,
        dense: true,
        title: Text(
          'Mode $value',
          style: TextStyle(
            fontWeight: FontWeight.w300,
            fontSize: 12.0,
          ),
        ),
        onChanged: (value) {
          setState(() {
            _ratingBarMode = value;
          });
        },
      ),
    );
  }
  
  Widget _ratingBar(int mode) {
    switch (mode) {
      case 1:
        return RatingBar(
          initialRating: 2,
          minRating: 1,
          direction: _isVertical ? Axis.vertical : Axis.horizontal,
          allowHalfRating: true,
          unratedColor: Colors.amber.withAlpha(50),
          itemCount: 5,
          itemSize: 50.0,
          itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
          itemBuilder: (context, _) => Icon(
            _selectedIcon ?? Icons.star,
            color: Colors.amber,
          ),
          onRatingUpdate: (rating) {
            setState(() {
              _rating = rating;
            });
          },
        );
      case 2:
        return RatingBar(
          initialRating: 3,
          direction: _isVertical ? Axis.vertical : Axis.horizontal,
          allowHalfRating: true,
          itemCount: 5,
          ratingWidget: RatingWidget(
            full: _image('assets/heart.png'),
            half: _image('assets/heart_half.png'),
            empty: _image('assets/heart_border.png'),
          ),
          itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
          onRatingUpdate: (rating) {
            setState(() {
              _rating = rating;
            });
          },
        );
      case 3:
        return RatingBar(
          initialRating: 3,
          direction: _isVertical ? Axis.vertical : Axis.horizontal,
          itemCount: 5,
          itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
          itemBuilder: (context, index) {
            switch (index) {
              case 0:
                return Icon(
                  Icons.sentiment_very_dissatisfied,
                  color: Colors.red,
                );
              case 1:
                return Icon(
                  Icons.sentiment_dissatisfied,
                  color: Colors.redAccent,
                );
              case 2:
                return Icon(
                  Icons.sentiment_neutral,
                  color: Colors.amber,
                );
              case 3:
                return Icon(
                  Icons.sentiment_satisfied,
                  color: Colors.lightGreen,
                );
              case 4:
                return Icon(
                  Icons.sentiment_very_satisfied,
                  color: Colors.green,
                );
              default:
                return Container();
            }
          },
          onRatingUpdate: (rating) {
            setState(() {
              _rating = rating;
            });
          },
        );
      default:
        return Container();
    }
  }
  
  Widget _image(String asset) {
    return Image.asset(
      asset,
      height: 30.0,
      width: 30.0,
      color: Colors.amber,
    );
  }
  
  Widget _heading(String text) => Column(
    children: [
      Text(
        text,
        style: TextStyle(
          fontWeight: FontWeight.w300,
          fontSize: 24.0,
        ),
      ),
      SizedBox(
        height: 20.0,
      ),
    ],
  );
}


设计垂直评级栏:

可以通过调用RatingBar小部件从flutter_rating_bar包中调用一个简单的评级栏,如下所示:

Dart

RatingBar(
   initialRating: 3,
   minRating: 1,
   direction: Axis.horizontal,
   allowHalfRating: true,
   itemCount: 5,
   itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
   itemBuilder: (context, _) => Icon(
     Icons.star,
     color: Colors.amber,
   ),
   onRatingUpdate: (rating) {
     print(rating);
   },
);

添加 RTL 开关:

在这个阶段,我们将添加一个开关,可以改变评级栏的对齐方式,从左到右,从右到左。可以通过使用MainAxisAlignment作为MainAxisAlignment.center 并调用_isRTL 模式来完成,如下所示:

Dart

mainAxisAlignment: MainAxisAlignment.center,
                   children: [
                     Text(
                       'Switch to RTL Mode',
                       style: TextStyle(
                         fontWeight: FontWeight.w300,
                       ),
                     ),
                     Switch(
                       value: _isRTLMode,
                       onChanged: (value) {
                         setState(() {
                           _isRTLMode = value;
                         });
                       },

添加垂直对齐开关:

在这个阶段,我们将添加一个开关,可以改变评级栏的对齐方式,从左到右,从右到左。可以通过使用MainAxisAlignment作为MainAxisAlignment.center并调用_isVertical模式来完成,如下所示:

Dart

mainAxisAlignment: MainAxisAlignment.center,
                   children: [
                     Text(
                       'Switch to Vertical Bar',
                       style: TextStyle(
                         fontWeight: FontWeight.w300,
                       ),
                     ),
                     Switch(
                       value: _isVertical,
                       onChanged: (value) {
                         setState(() {
                           _isVertical = value;
                         });
                       },
                       activeColor: Colors.amber,
                     ),
                   ],
                 ),

将模式添加到评级栏:

在此应用程序中,我们将添加 3 种模式,并且在选择每种模式时,评级栏图标将发生变化。我们将使用 switch()函数将案例分配给模式并将图标分配给相同的模式,如下所示:

Dart

Widget _ratingBar(int mode) {
   switch (mode) {
     case 1:
       return RatingBar(
         initialRating: 2,
         minRating: 1,
         direction: _isVertical ? Axis.vertical : Axis.horizontal,
         allowHalfRating: true,
         unratedColor: Colors.amber.withAlpha(50),
         itemCount: 5,
         itemSize: 50.0,
         itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
         itemBuilder: (context, _) => Icon(
           _selectedIcon ?? Icons.star,
           color: Colors.amber,
         ),
         onRatingUpdate: (rating) {
           setState(() {
             _rating = rating;
           });
         },
       );
     case 2:
       return RatingBar(
         initialRating: 3,
         direction: _isVertical ? Axis.vertical : Axis.horizontal,
         allowHalfRating: true,
         itemCount: 5,
         ratingWidget: RatingWidget(
           full: _image('assets/heart.png'),
           half: _image('assets/heart_half.png'),
           empty: _image('assets/heart_border.png'),
         ),
         itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
         onRatingUpdate: (rating) {
           setState(() {
             _rating = rating;
           });
         },
       );
     case 3:
       return RatingBar(
         initialRating: 3,
         direction: _isVertical ? Axis.vertical : Axis.horizontal,
         itemCount: 5,
         itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
         itemBuilder: (context, index) {
           switch (index) {
             case 0:
               return Icon(
                 Icons.sentiment_very_dissatisfied,
                 color: Colors.red,
               );
             case 1:
               return Icon(
                 Icons.sentiment_dissatisfied,
                 color: Colors.redAccent,
               );
             case 2:
               return Icon(
                 Icons.sentiment_neutral,
                 color: Colors.amber,
               );
             case 3:
               return Icon(
                 Icons.sentiment_satisfied,
                 color: Colors.lightGreen,
               );
             case 4:
               return Icon(
                 Icons.sentiment_very_satisfied,
                 color: Colors.green,
               );
             default:
               return Container();
           }
         },
         onRatingUpdate: (rating) {
           setState(() {
             _rating = rating;
           });
         },
       );
     default:
       return Container();
   }
 }

完整的源代码:

Dart

import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
  
void main() => runApp(MyApp());
  
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
  
class _MyAppState extends State {
  var _ratingController = TextEditingController();
  double _rating;
  int _ratingBarMode = 1;
  bool _isRTLMode = false;
  bool _isVertical = false;
  IconData _selectedIcon;
  
  @override
  void initState() {
    _ratingController.text = "3.0";
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
        appBarTheme: AppBarTheme(
          textTheme: TextTheme(
            title: Theme.of(context).textTheme.title.copyWith(
              color: Colors.white,
            ),
          ),
        ),
      ),
      home: Builder(
        builder: (context) => Scaffold(
          appBar: AppBar(
            title: Text('GeeksForGeeks'),
            backgroundColor: Colors.green,
          ),
          body: Directionality(
            textDirection: _isRTLMode ? TextDirection.rtl : TextDirection.ltr,
            child: SingleChildScrollView(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: [
                  SizedBox(
                    height: 40.0,
                  ),
                  _heading('Rating Bar'),
                  _ratingBar(_ratingBarMode),
                  SizedBox(
                    height: 20.0,
                  ),
                  _rating != null
                      ? Text(
                    "Rating: $_rating",
                    style: TextStyle(fontWeight: FontWeight.bold),
                  )
                      : Container(),
                  Row(
                    children: [
                      _radio(1),
                      _radio(2),
                      _radio(3),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        'Switch to Vertical Bar',
                        style: TextStyle(
                          fontWeight: FontWeight.w300,
                        ),
                      ),
                      Switch(
                        value: _isVertical,
                        onChanged: (value) {
                          setState(() {
                            _isVertical = value;
                          });
                        },
                        activeColor: Colors.amber,
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        'Switch to RTL Mode',
                        style: TextStyle(
                          fontWeight: FontWeight.w300,
                        ),
                      ),
                      Switch(
                        value: _isRTLMode,
                        onChanged: (value) {
                          setState(() {
                            _isRTLMode = value;
                          });
                        },
                        activeColor: Colors.amber,
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
  
  Widget _radio(int value) {
    return Expanded(
      child: RadioListTile(
        value: value,
        groupValue: _ratingBarMode,
        dense: true,
        title: Text(
          'Mode $value',
          style: TextStyle(
            fontWeight: FontWeight.w300,
            fontSize: 12.0,
          ),
        ),
        onChanged: (value) {
          setState(() {
            _ratingBarMode = value;
          });
        },
      ),
    );
  }
  
  Widget _ratingBar(int mode) {
    switch (mode) {
      case 1:
        return RatingBar(
          initialRating: 2,
          minRating: 1,
          direction: _isVertical ? Axis.vertical : Axis.horizontal,
          allowHalfRating: true,
          unratedColor: Colors.amber.withAlpha(50),
          itemCount: 5,
          itemSize: 50.0,
          itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
          itemBuilder: (context, _) => Icon(
            _selectedIcon ?? Icons.star,
            color: Colors.amber,
          ),
          onRatingUpdate: (rating) {
            setState(() {
              _rating = rating;
            });
          },
        );
      case 2:
        return RatingBar(
          initialRating: 3,
          direction: _isVertical ? Axis.vertical : Axis.horizontal,
          allowHalfRating: true,
          itemCount: 5,
          ratingWidget: RatingWidget(
            full: _image('assets/heart.png'),
            half: _image('assets/heart_half.png'),
            empty: _image('assets/heart_border.png'),
          ),
          itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
          onRatingUpdate: (rating) {
            setState(() {
              _rating = rating;
            });
          },
        );
      case 3:
        return RatingBar(
          initialRating: 3,
          direction: _isVertical ? Axis.vertical : Axis.horizontal,
          itemCount: 5,
          itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
          itemBuilder: (context, index) {
            switch (index) {
              case 0:
                return Icon(
                  Icons.sentiment_very_dissatisfied,
                  color: Colors.red,
                );
              case 1:
                return Icon(
                  Icons.sentiment_dissatisfied,
                  color: Colors.redAccent,
                );
              case 2:
                return Icon(
                  Icons.sentiment_neutral,
                  color: Colors.amber,
                );
              case 3:
                return Icon(
                  Icons.sentiment_satisfied,
                  color: Colors.lightGreen,
                );
              case 4:
                return Icon(
                  Icons.sentiment_very_satisfied,
                  color: Colors.green,
                );
              default:
                return Container();
            }
          },
          onRatingUpdate: (rating) {
            setState(() {
              _rating = rating;
            });
          },
        );
      default:
        return Container();
    }
  }
  
  Widget _image(String asset) {
    return Image.asset(
      asset,
      height: 30.0,
      width: 30.0,
      color: Colors.amber,
    );
  }
  
  Widget _heading(String text) => Column(
    children: [
      Text(
        text,
        style: TextStyle(
          fontWeight: FontWeight.w300,
          fontSize: 24.0,
        ),
      ),
      SizedBox(
        height: 20.0,
      ),
    ],
  );
}

输出:

想要一个更快节奏和更具竞争力的环境来学习 Android 的基础知识吗?
单击此处前往由我们的专家精心策划的指南,旨在让您立即做好行业准备!