Skip to content

Instantly share code, notes, and snippets.

@sma
Created March 24, 2019 11:09
Show Gist options
  • Save sma/1f22ef926ef878f10915aa9e00bc9eaa to your computer and use it in GitHub Desktop.
Save sma/1f22ef926ef878f10915aa9e00bc9eaa to your computer and use it in GitHub Desktop.
A simple star display and interactive star rating widget
import 'package:flutter/material.dart';
class StarDisplayWidget extends StatelessWidget {
final int value;
final Widget filledStar;
final Widget unfilledStar;
const StarDisplayWidget({
Key key,
this.value = 0,
@required this.filledStar,
@required this.unfilledStar,
}) : assert(value != null),
super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(5, (index) {
return index < value ? filledStar : unfilledStar;
}),
);
}
}
class StarDisplay extends StarDisplayWidget {
const StarDisplay({Key key, int value = 0})
: super(
key: key,
value: value,
filledStar: const Icon(Icons.star),
unfilledStar: const Icon(Icons.star_border),
);
}
class StarRating extends StatelessWidget {
final void Function(int index) onChanged;
final int value;
final IconData filledStar;
final IconData unfilledStar;
const StarRating({
Key key,
@required this.onChanged,
this.value = 0,
this.filledStar,
this.unfilledStar,
}) : assert(value != null),
super(key: key);
@override
Widget build(BuildContext context) {
final color = Theme.of(context).accentColor;
final size = 36.0;
return Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(5, (index) {
return IconButton(
onPressed: onChanged != null
? () {
onChanged(value == index + 1 ? index : index + 1);
}
: null,
color: index < value ? color : null,
iconSize: size,
icon: Icon(
index < value ? filledStar ?? Icons.star : unfilledStar ?? Icons.star_border,
),
padding: EdgeInsets.zero,
tooltip: "${index + 1} of 5",
);
}),
);
}
}
@mortada-jafar
Copy link

mortada-jafar commented Jun 21, 2019

import 'package:flutter/material.dart';

class StarDisplayWidget extends StatelessWidget {
  final int value;
  final Widget filledStar;
  final Widget unfilledStar;
  final double size;
  final Color color;
  final int marginFactor;

  const StarDisplayWidget({
    Key key,
    this.value = 0,
    this.filledStar,
    this.unfilledStar,
    this.color = Colors.orange,
    this.size = 20,
    this.marginFactor = 5,
  })  : assert(value != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.end,
      children: List.generate(5, (index) {
        return Container(
          width: size - size / marginFactor,
          height: size,
          child: Icon(
            index < value
                ? filledStar ?? Icons.star
                : unfilledStar ?? Icons.star_border,
            color: color,
            size: size,
          ),
        );
      }),
    );
  }
}

class StarRating extends StatelessWidget {
  final void Function(int index) onChanged;
  final int value;
  final IconData filledStar;
  final IconData unfilledStar;
  final double size;
  final Color color;
  final int marginFactor;

  const StarRating({
    Key key,
    @required this.onChanged,
    this.value = 0,
    this.filledStar,
    this.unfilledStar,
    this.color = Colors.orange,
    this.size = 20,
    this.marginFactor = 5,
  })  : assert(value != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: List.generate(5, (index) {
        return RawMaterialButton(
          child: Icon(
            index < value
                ? filledStar ?? Icons.star
                : unfilledStar ?? Icons.star_border,
            color: color,
            size: size,
          ),
          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
          shape: CircleBorder(),
          constraints: BoxConstraints.expand(
              width: size - size / marginFactor, height: size),
          padding: EdgeInsets.zero,
          highlightColor: Colors.transparent,
          splashColor: Colors.transparent,
          onPressed: onChanged != null
              ? () {
                  onChanged(value == index + 1 ? index : index + 1);
                }
              : null,
        );
      }),
    );
  }
}

@jmnicolino
Copy link

Great work Mortadda, I used it and it works perfectly.
However, I used the first version because the 2nd one with modifications generates a RenderFlex Overflow.

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment