简体   繁体   中英

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 .

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

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

截屏

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),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Try childAspectRatio inside grid delegate and value (Child width / child height)

GridView.count(
childAspectRatio = value

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM