Flutter - настраиваемая панель рейтингов

Опубликовано: 5 Января, 2022

Панель рейтинга, как следует из названия, используется для оценки контента внутри приложения. Более или менее все приложения используют их либо для получения отзывов пользователей о своем приложении, либо для получения рейтинга контента, размещенного в приложении. Такие приложения, как IMDB, используют их для оценки фильмов и сериалов, а приложения, подобные IMDB, используют их для получения отзывов о своих услугах от клиентов.

В этой статье мы создадим простое приложение со следующими функциями:

  • Горизонтальная полоса рейтинга
  • Переключатель, позволяющий перемещать все рейтинговые полосы вверху справа налево.
  • Переключатель, позволяющий сделать шкалу рейтинга вертикальной.
  • Три различных режима для изменения значка первой панели рейтинга

Чтобы создать указанное выше приложение, выполните следующие действия:

  • Добавьте зависимость в файл pubspec.yaml
  • Импортировать зависимость в файл main.dart
  • Используйте StatefulWidget, чтобы структурировать приложение
  • Добавьте вертикальную полосу рейтинга
  • Добавьте переключатель, чтобы изменить выравнивание рейтинговых полос справа налево (RTL)
  • Добавьте переключатель, чтобы изменить выравнивание шкалы рейтинга с горизонтального на вертикальное.
  • Добавьте 3 разных режима, которые изменяют значки пользовательского интерфейса.

Добавление зависимости:

Чтобы добавить зависимость в файл pubspec.yaml, следуйте следующему изображению:

Импорт зависимости:

Чтобы импортировать зависимость flutter_rating_bar к файлу main.dart, используйте следующее:

 import 'package: flutter_rating_bar / flutter_rating_bar.dart';

Структурирование приложения:

StatefulWidget можно использовать для предоставления приложению панели приложений и тела для хранения содержимого, как показано ниже:

Дротик

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
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,
),
),
),
),

Создание вертикальной шкалы оценок:

Простую панель рейтинга можно вызвать из пакета flutter_rating_bar , вызвав виджет RatingBar, как показано ниже:

Дротик

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, как показано ниже:

Дротик

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

Добавление переключателя вертикального выравнивания:

На этом этапе мы добавим переключатель, который может изменять выравнивание шкалы рейтинга слева направо, справа налево. Это можно сделать, используя MainAxisAlignment как MainAxisAlignment.center и вызывая режим _isVertical, как показано ниже:

Дротик

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

Добавление режимов в панель рейтинга:

В этом приложении мы добавим 3 режима, и при выборе каждого режима значок шкалы рейтинга изменится. Мы будем использовать функцию switch (), чтобы назначить случаи режимам и назначить значки таким же образом, как показано ниже:

Дротик

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:
Icon( return
Icons.sentiment_very_dissatisfied,
color: Colors.red,
);
case 1:
Icon( return
Icons.sentiment_dissatisfied,
color: Colors.redAccent,
);
case 2:
Icon( return
Icons.sentiment_neutral,
color: Colors.amber,
);
case 3:
Icon( return
Icons.sentiment_satisfied,
color: Colors.lightGreen,
);
case 4:
Icon( return
Icons.sentiment_very_satisfied,
color: Colors.green,
);
default :
return Container();
}
},
onRatingUpdate: (rating) {
setState(() {
_rating = rating;
});
},
);
default :
return Container();
}
}

Полный исходный код:

Дротик

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<MyApp> {
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: <Widget>[
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: <Widget>[
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: <Widget>[
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:
Icon( return
Icons.sentiment_very_dissatisfied,
color: Colors.red,
);
case 1:
Icon( return
Icons.sentiment_dissatisfied,
color: Colors.redAccent,
);
case 2:
Icon( return
Icons.sentiment_neutral,
color: Colors.amber,
);
case 3:
Icon( return
Icons.sentiment_satisfied,
color: Colors.lightGreen,
);
case 4:
Icon( return
Icons.sentiment_very_satisfied,
color: Colors.green,
);
default :
return Container();
}
},
onRatingUpdate: (rating) {
setState(() {
_rating = rating;
});
},
);
default :
return Container();
}
}