Search code examples
fluttersqlitedartgridviewgridview.builder

How to calculate widget height in GridView.builder in flutter?


I'm trying to develop some notebook like this :

Picture of NoteBook

my issue is when user add some description of note .. if it long text , I got overflow error when I tying to show that note in HomeScreen . check this pictures:

picture of add some note in AddScreen

picture of overflow error note

I use GridView.builder to show Notes in Home page but I can not Develop Some code that Check if description of note is Long text , Change height of Card to same height that description does ! Here is my code :

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:samsung_note/CustomWidget/base_container.dart';
import 'package:samsung_note/Database/database.dart';
import 'package:samsung_note/Screens/add_screen.dart';
import 'package:samsung_note/Screens/details_screen.dart';
import 'package:samsung_note/app_style.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late Database _database;

  @override
  void initState() {
    _database = Database();
    super.initState();
  }
  @override
  void dispose() {
    _database.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final double itemHeight = (size.height - kToolbarHeight - 24) / 2;
    final double itemWidth = size.width / 2;
    return Scaffold(
      backgroundColor: Colors.grey.shade200,
      drawer: const Drawer(),
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Colors.grey.shade200,
        title: Text(
          "All notes",
          style: AppStyle.normalTextStyle.copyWith(fontWeight: FontWeight.w600),
        ),
        actions: [
          IconButton(onPressed: () {}, icon: const Icon(Icons.search)),
          IconButton(
              onPressed: () {}, icon: const Icon(Icons.more_vert_outlined))
        ],
      ),
      body: FutureBuilder<List<NoteEntityData>>(
        future: _database.getAllNotes(),
        builder: (context, snapshot) {
          final List<NoteEntityData>? notes = snapshot.data;
          if (snapshot.connectionState != ConnectionState.done) {
            return Center(
              child: LoadingAnimationWidget.inkDrop(
                  color: Colors.deepOrange, size: 200),
            );
          } else if (snapshot.hasError) {
            return Center(
              child: Text(snapshot.error.toString()),
            );
          } else if (notes!.isNotEmpty) {
            return Padding(
                padding: const EdgeInsets.symmetric(vertical: 16),
                child: GridView.builder(
                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                      mainAxisExtent: 160,
                      crossAxisCount: 2),
                  itemCount: notes.length,
                  itemBuilder: (context, index) {
                    final note = notes[index];
                    return GestureDetector(
                        onTap: () => Get.to(() => DetailsScreen(id: note.id)),
                        child: BaseContainer(note: note));
                  },
                ));
          } else if (notes.isEmpty) {
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    "No notes",
                    style: AppStyle.normalTextStyle.copyWith(
                        color: Colors.grey.shade700,
                        fontWeight: FontWeight.w600),
                  ),
                  const SizedBox(height: 20),
                  Text("Tap the Add button to create a note",
                      style: AppStyle.normalTextStyle
                          .copyWith(color: Colors.grey.shade500, fontSize: 17)),
                ],
              ),
            );
          }
          return const Text('No Data Found');
        },
      ),
      floatingActionButton: SizedBox(
        height: 65,
        width: 65,
        child: FloatingActionButton(
          tooltip: 'Add note',
          child: const Icon(
            Icons.add,
            size: 30,
          ),
          onPressed: () => Get.to(() => const AddScreen()),
        ),
      ),
    );
  }
}

Here is my card widget (baseContainer) code :

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:samsung_note/Database/database.dart';
import 'package:samsung_note/app_style.dart';
class BaseContainer extends StatelessWidget {
  final NoteEntityData note ;
  const BaseContainer({Key? key,required this.note}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    //final time = DateFormat.Hm().format(note.createdTime);
    final dateTime = DateFormat.yMMMd().format(note.createdTime);
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8.0,vertical: 8),
      child: Container(
        width: MediaQuery.of(context).size.width*0.45,
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(30)
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children:  [
              const CircleAvatar(
                backgroundColor: Colors.grey,
                radius: 4,
              ),
              const SizedBox(height: 6),
              Text(note.title,style: AppStyle.normalTextStyle,),
              const SizedBox(height: 5),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(dateTime,style: AppStyle.smallTextStyle.copyWith(color: Colors.grey),),
                  note.isImportant ? const Icon(Icons.star,color: Colors.orange,size: 20,): Container(),
                ],
              ),
              const SizedBox(height: 15),
              Text(note.description,style: AppStyle.smallTextStyle,),
            ],
          ),
        ),
      ),
    );
  }
}

I want to solve this issue that if Height of Description text is more than that 160 pixel , Extented to whatever height description have .


Solution

  • To fix the problem with the card not resizing with the text you'd need to change from the GridView to 2 Columns side by side because GridViews have fixed width and height.

    Take a look at the screenshot and the live demo on DartPad:

    Screenshot

    import 'package:flutter/material.dart';
    import 'package:intl/intl.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.blue,
            appBarTheme: const AppBarTheme(
              foregroundColor: Color.fromARGB(255, 95, 95, 95),
              backgroundColor: Colors.transparent,
            ),
          ),
          home: const HomeScreen(),
        );
      }
    }
    
    class NoteEntityData {
      final DateTime createdTime;
      final String title;
      final bool isImportant;
      final String description;
    
      const NoteEntityData({
        required this.createdTime,
        required this.title,
        this.isImportant = false,
        required this.description,
      });
    }
    
    class HomeScreen extends StatefulWidget {
      const HomeScreen({Key? key}) : super(key: key);
    
      @override
      State<HomeScreen> createState() => _HomeScreenState();
    }
    
    class _HomeScreenState extends State<HomeScreen> {
      // late Database _database;
    
      @override
      void initState() {
        // _database = Database();
        super.initState();
      }
    
      @override
      void dispose() {
        // _database.close();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        final size = MediaQuery.of(context).size;
        final double itemHeight = (size.height - kToolbarHeight - 24) / 2;
        final double itemWidth = size.width / 2;
        return Scaffold(
          backgroundColor: Colors.grey.shade200,
          drawer: const Drawer(),
          appBar: AppBar(
            elevation: 0,
            backgroundColor: Colors.grey.shade200,
            title: const Text(
              "All notes",
              style: TextStyle(
                  fontWeight: FontWeight.w600,
                  color: Color.fromARGB(255, 95, 95, 95)),
            ),
            actions: [
              IconButton(onPressed: () {}, icon: const Icon(Icons.search)),
              IconButton(
                  onPressed: () {}, icon: const Icon(Icons.more_vert_outlined))
            ],
          ),
          body: FutureBuilder<List<NoteEntityData>>(
            future: Future.value([
              NoteEntityData(
                createdTime: DateTime.now(),
                title: 'Some title',
                isImportant: true,
                description: 'Hello guys 😗😂',
              ),
              NoteEntityData(
                createdTime: DateTime.now(),
                title: 'Work stuff',
                isImportant: true,
                description:
                    '1 : go to office\n2 : secret\n3 : get back to home\n4 : bela bela bela\n5 : ...\n6 : ...\n.\n.\n.\n.',
              ),
              NoteEntityData(
                createdTime: DateTime.now(),
                title: 'alireza',
                description: 'Arash shakibaee',
              ),
            ]),
            builder: (context, snapshot) {
              final List<NoteEntityData>? notes = snapshot.data;
              if (notes == null) {
                return const Center(
                  child: SizedBox(
                    height: 200,
                    child: CircularProgressIndicator(color: Colors.deepOrange),
                  ),
                );
              } else if (snapshot.hasError) {
                return Center(
                  child: Text(snapshot.error.toString()),
                );
              } else if (notes.isNotEmpty) {
                return Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  child: SingleChildScrollView(
                    child: Center(
                      child: Row(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: [
                          Expanded(
                            child: Column(
                              children: [
                                for (int i = 0; i < notes.length; i += 2)
                                  GestureDetector(
                                      onTap:
                                          () {}, // => Get.to(() => DetailsScreen(id: note.id)),
                                      child: BaseContainer(note: notes[i])),
                              ],
                            ),
                          ),
                          Expanded(
                            child: Column(
                              children: [
                                for (int i = 1; i < notes.length; i += 2)
                                  GestureDetector(
                                      onTap:
                                          () {}, // => Get.to(() => DetailsScreen(id: note.id)),
                                      child: BaseContainer(note: notes[i])),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                );
              } else if (notes.isEmpty) {
                return Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        "No notes",
                        style: TextStyle(
                            color: Colors.grey.shade700,
                            fontWeight: FontWeight.w600),
                      ),
                      const SizedBox(height: 20),
                      Text("Tap the Add button to create a note",
                          style:
                              TextStyle(color: Colors.grey.shade500, fontSize: 17)),
                    ],
                  ),
                );
              }
              return const Text('No Data Found');
            },
          ),
          floatingActionButton: SizedBox(
            height: 65,
            width: 65,
            child: FloatingActionButton(
                tooltip: 'Add note',
                child: const Icon(
                  Icons.add,
                  size: 30,
                ),
                onPressed: () {} // => Get.to(() => const AddScreen()),
                ),
          ),
        );
      }
    }
    
    class BaseContainer extends StatelessWidget {
      final NoteEntityData note;
      const BaseContainer({Key? key, required this.note}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        //final time = DateFormat.Hm().format(note.createdTime);
        final dateTime = DateFormat.yMMMd().format(note.createdTime);
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 8),
          child: Container(
            width: MediaQuery.of(context).size.width * 0.45,
            decoration: BoxDecoration(
                color: Colors.white, borderRadius: BorderRadius.circular(30)),
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const CircleAvatar(
                    backgroundColor: Colors.grey,
                    radius: 4,
                  ),
                  const SizedBox(height: 6),
                  Text(
                    note.title,
                    style: TextStyle(fontSize: 22),
                  ),
                  const SizedBox(height: 5),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text(
                        dateTime,
                        style: TextStyle(color: Colors.grey, fontSize: 16),
                      ),
                      if (note.isImportant)
                          const Icon(
                              Icons.star,
                              color: Colors.orange,
                              size: 20,
                            ),
                    ],
                  ),
                  const SizedBox(height: 15),
                  Text(
                    note.description,
                    style: TextStyle(fontSize: 16)
                    .copyWith(overflow: TextOverflow.fade),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }