flutterflutter-layoutflutter-row

Flutter multiple items in Row with Expanded/Flexible


I want to have more(in this example 4) items in Row. I tried use Expanded or Flexible or mainAxisAlignment: MainAxisAlignment.spaceEvenly to fill up all width of screen. But I want to heve items lets say specific width and height 50 pixels, and GestureDetector which is around item to be 1/4 of screen(4 items = full width). So everywhere I tap in the row something will be selected. My problem is that every my solution deforms items(circles) or circle must be very huge to width = height to not be deformed. I also tried wrapping whole _ratingEmoji in Expanded and giving ratingItem.ratingIndicator constraints to max width but with same result.

Row of items:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    for (var ratingItem in editGroceryRatingProvider.foodRatings)
      _ratingEmoji(editGroceryRatingProvider, ratingItem, context),
  ],
),

Item:

Widget _ratingEmoji(EditGroceryRatingProvider editGroceryRatingProvider,
  SelectedFoodRating ratingItem, BuildContext context) {
return GestureDetector(
  child: ratingItem.selected
      ? Container(
          width: MediaQuery.of(context).size.width / 8,
          height: MediaQuery.of(context).size.width / 8,
          padding: const EdgeInsets.all(2.0),
          decoration: BoxDecoration(
              border: Border.all(
                color: Color(0xFF312ADB),
                width: 3.0,
              ),
              borderRadius: BorderRadius.circular(32.0)),
          child: Center(
            child: ratingItem.ratingIndicator,
          ),
        )
      : ratingItem.ratingIndicator,
  onTap: () => editGroceryRatingProvider.updateSelectedRating(ratingItem),
);

}

RatingIndicator which is "circle" item to be on the screen:

Container(
  decoration: BoxDecoration(
    border: Border.all(
      color: color,
      width: 1.5,
    ),
    borderRadius: BorderRadius.circular(64.0),
  ),
  child: Container(
    decoration: BoxDecoration(
      border: Border.all(
        color: Colors.white,
        width: 3.0,
      ),
      borderRadius: BorderRadius.circular(64.0),
    ),
    child: ClipOval(
      child: Container(
        width: width ?? MediaQuery.of(context).size.width / 7,
        height: height ?? MediaQuery.of(context).size.width / 7,
        color: color,
      ),
    ),
  ),
);

Thanks a lot.

Update:

row with items

Items should stay as they are on screenshot, but "whole" row should be clickable(means even if you click between 2 items, one closer to click should be selected)


Solution

  • Check, please solution. The whole area is clickable. You just need to add your item instead of mine.

    row with items

    @override
      Widget build(BuildContext context) {
        final colors = [Colors.red, Colors.blue, Colors.brown, Colors.cyan];
        return Scaffold(
          body: Container(
            alignment: Alignment.center,
            color: const Color(0xffFAFAFA),
            child: Row(
              children: List.generate(
                  colors.length,
                  (index) => Expanded(
                        child: GestureDetector(
                            onTap: () => print('Tapped:$index'),
                            child: Container(
                              height: 50,
                              color: Colors.transparent,
                              child: Container(
                                decoration: BoxDecoration(
                                  shape: BoxShape.circle,
                                  color: colors[index],
                                ),
                              ),
                            )),
                      )),
            ),
          ),
        );