flutter gridview horizontal how to fill height

Viewed 39

I am imitating telegram desktop app. First time, I tried to put listview in row. But I failed. So I use GridView.count with crossAxisCount: 2.

I want to fill empty area under contents. https://github.com/kangsudal/kkunglegram/issues/1

enter image description here

https://github.com/kangsudal/kkunglegram/blob/main/lib/main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.yellow,
      ),
      home: InitScreen(),
    );
  }
}

class InitScreen extends StatelessWidget {
  const InitScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        final width = constraints.maxWidth;
        final height = constraints.maxHeight;
        final ratio = width / height;
        print(
          "width: $width\nheight: $height\naspect ratio: $ratio",
        );
        return Scaffold(
          body: ratio >= 1 ? const ChatListWithRoom() : const ChatList(),
        );
      },
    );
  }
}

class ChatList extends StatelessWidget {
  const ChatList({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(itemBuilder: (context, index) {
      return ListTile(
        leading: CircleAvatar(),
        title: Text("대화상대명"),
        subtitle: Text("최신메세지"),
        trailing: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: const [
            Text(
              "최근메세지 날짜or시간",
              style: TextStyle(
                // fontSize: 12,
                color: Colors.grey,
              ),
            ),
            CircleAvatar(
              maxRadius: 10,
              child: FittedBox(
                fit: BoxFit.scaleDown,
                child: Text("쌓여있는메세지개수"),
              ),
            ),
          ],
        ),
      );
    });
  }
}

class ChatListWithRoom extends StatelessWidget {
  const ChatListWithRoom({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 2,
      children: [
        ChatList(),
        Container(
          color: Colors.blue,
          child: Center(child: Text("대화방을 선택해주세요")),
        )
      ],
    );
  }
}
2 Answers

Instead of using a gridview which has a child aspect ratio of 1 as default (So you can a square layout for children) you can return a row with 2 expanded widgets (for equal size) and add chat list and image as children of expanded widgets as shown below.


class ChatListWithRoom extends StatelessWidget {
  const ChatListWithRoom({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      
      children: [
       Expanded(
        child: ChatList(),
       ),
       Expanded(
        child: Container(
          color: Colors.blue,
          child: Center(child: Text("대화방을 선택해주세요")),
        )
       )
      ],
    );
  }
}

The GridView is a bit tricky to work with - You'd need to play with GridView.childAspectRatio to make it fill the entire space. The solution is to replace the GridView with a Row and use Expanded on both children so they share the same amount of space horizontally.

Check out the fixed ChatListWithRoom:

Fixed ChatListWithRoom

And here's the code:

class ChatListWithRoom extends StatelessWidget {
  const ChatListWithRoom({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(child: ChatList()),
        Expanded(
          child: Container(
            color: Colors.blue,
            child: Center(child: Text("대화방을 선택해주세요")),
          ),
        ),
      ],
    );
  }
}
Related