Flutter: Rendering working fine on android device but overflowing on iOS device of a different size

Viewed 389

From the AppWidget (home of the material app), I am returning a GridView. Below is the code of AppWidget's build method:

Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBarWidget(widget.title),
  body: SafeArea(
          child: GridView.count(
        physics: ScrollPhysics(),
        padding: EdgeInsets.all(MediaQuery.of(context).size.width * 0.03),
        shrinkWrap: true,
        crossAxisCount: 2,
        crossAxisSpacing: MediaQuery.of(context).size.width * 0.03,
        mainAxisSpacing: MediaQuery.of(context).size.width * 0.03,
        children: List.generate(workoutList.length, (index) {
          return WorkoutOverviewWidget(workoutList[index]);
        })),
  ),
); 

}

Below is the code for WorkoutOverviewWidget's build method:

Widget build(BuildContext context) {
return InkWell(
  splashColor: Colors.black,
  onTap: () => gotoWorkoutDetailsWidget(context),
  child: Card(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(10.0),
    ),
    elevation: 5,
    child: Container(
      height: (MediaQuery.of(context).size.height -
              MediaQuery.of(context).padding.top -
              kToolbarHeight) *
          (0.30),
      width: MediaQuery.of(context).size.width * (0.4),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Stack(
            children: [
              ClipRRect(
                borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(10.0),
                  topRight: Radius.circular(10.0),
                ),
                child: Image.asset(
                  getWorkoutImagePath(this._workout.type),
                  height: (MediaQuery.of(context).size.height -
                          MediaQuery.of(context).padding.top -
                          kToolbarHeight) *
                      (0.225),
                  width: double.infinity,
                  fit: BoxFit.cover,
                ),
              ),
              Positioned(
                bottom: 10,
                right: 10,
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.black54,
                    borderRadius: BorderRadius.all(Radius.circular(5.0)),
                  ),
                  padding: EdgeInsets.all(5),
                  child: Text(
                    Utils.getEnumName(this._workout.type.toString()),
                    style: TextStyle(
                        fontSize: 15,
                        color: Colors.white,
                        fontWeight: FontWeight.w700),
                  ),
                ),
              )
            ],
          ),
          SizedBox(
            height: (MediaQuery.of(context).size.height -
                    MediaQuery.of(context).padding.top -
                    kToolbarHeight) *
                (0.015),
          ),
          Row(
            children: [
              SizedBox(
                width: 4,
              ),
              Icon(
                Icons.calendar_today_rounded,
                size: 20,
              ),
              SizedBox(
                width: 3,
              ),
              Utils.displayText(
                text: getReadableTimestamp(this._workout.timestamp),
                allPadding: 5,
                fontSize: 15,
                fontWeight: FontWeight.w700,
                fontFamily:
                    Theme.of(context).textTheme.headline1.fontFamily,
              ),
            ],
          ),
        ],
      ),
    ),
  ),
);}

I have used MediaQuery to avoid hardcoding the size of any widget. The code is working fine when I tested it on the Google Pixel emulator but overflows on iPhone 12 Max Pro emulator. Below are the screenshots:

Output on Google Pixel emulator:

Output on Google Pixel emulator

Output on iPhone 12 Max Pro emulator:

Output on iPhone 12 Max Pro emulator

What is the thing I am doing wrong?

2 Answers

Using MediaQuery is a good first step, but this will adjust your dimensions according to the screen, but if those dimensions are bigger than their parent, they will over Flow. Wrap your sized box with an Expanded, wrap your Last Row with an expanded also, and it's children, which are overflowing [children of row] in an expanded], the overflow will go away, then you can readjust the heights as you want. It has nothing to do with android or iOS, it's only related to the dimensions of the screens you are using. It can overflow on an android device with similar device dimensions as the one you are using for iOS. Try it out, it would solve your problem.

Solved it by not defining the height of the image in ClipRRect explicitly but instead wrapping them in the Expanded() widget with flex property defined to adjust the percentage of height distributed between the children in column. Updated code for WorkoutOverviewWidget's build method:

return InkWell(
  splashColor: Colors.black,
  onTap: () => gotoWorkoutDetailsWidget(context),
  child: Card(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(10.0),
    ),
    elevation: 5,
    child: Container(
      height: this._availableHeight * (0.30),
      width: this._screenWidth * (0.4),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Expanded(
            flex: 4,
            child: Stack(
              children: [
                ClipRRect(
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(10.0),
                    topRight: Radius.circular(10.0),
                  ),
                  child: Image.asset(
                    getWorkoutImagePath(this._workout.type),
                    width: double.infinity,
                    fit: BoxFit.cover,
                  ),
                ),
                Positioned(
                  bottom: 10,
                  right: 10,
                  child: Container(
                    decoration: BoxDecoration(
                      color: Colors.black54,
                      borderRadius: BorderRadius.all(Radius.circular(5.0)),
                    ),
                    padding: EdgeInsets.all(5),
                    child: Text(
                      Utils.getEnumName(this._workout.type.toString()),
                      style: TextStyle(
                          fontSize: 15,
                          color: Colors.white,
                          fontWeight: FontWeight.w700),
                    ),
                  ),
                )
              ],
            ),
          ),
          Expanded(
            flex: 1,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                SizedBox(
                  width: this._screenWidth * (0.02),
                ),
                Icon(
                  Icons.calendar_today_rounded,
                  size: 20,
                ),
                SizedBox(
                  width: this._screenWidth * (0.01),
                ),
                Utils.displayText(
                  text: getReadableTimestamp(this._workout.timestamp),
                  allPadding: 5,
                  fontSize: 15,
                  fontWeight: FontWeight.w700,
                  fontFamily:
                      Theme.of(context).textTheme.headline1.fontFamily,
                ),
              ],
            ),
          ),
        ],
      ),
    ),
  ),
);
Related