Home > other >  How to align icons with richtext in two columns in Flutter?
How to align icons with richtext in two columns in Flutter?

Time:01-24

I am having difficulties to align my icons with my two lines rich text in Flutter. As you can seen in the picture below, I want to align my ONE richtext widget with ONE icon. Example: Richtext containing "Revision Notes" and "Free notes." should be in the same line as the green icon tick. If I try using just one liner of text, the tick will align with it, but now if I have two liners rich text, it won't align.

Appreciate any help!

Picture: enter image description here

Code:

              child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        RichText(
                          text: TextSpan(
                            style: DefaultTextStyle.of(context).style,
                            children: const <TextSpan>[
                              TextSpan(
                                  text: 'Revision notes\n',
                                  style: TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold)),
                              TextSpan(text: 'Free notes.'),
                            ],
                          ),
                        ),
                      
                        RichText(
                          text: TextSpan(
                            style: DefaultTextStyle.of(context).style,
                            children: const <TextSpan>[
                              TextSpan(
                                  text: 'Quizzes\n',
                                  style: TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold)),
                              TextSpan(text: 'Free quizzes.'),
                            ],
                          ),
                        ),
                        RichText(
                          text: TextSpan(
                            style: DefaultTextStyle.of(context).style,
                            children: const <TextSpan>[
                              TextSpan(
                                  text: 'No Ads\n',
                                  style: TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold)),
                              TextSpan(text: 'All annoying ads gone.'),
                            ],
                          ),
                        ),
                        RichText(
                          text: TextSpan(
                            style: DefaultTextStyle.of(context).style,
                            children: const <TextSpan>[
                              TextSpan(
                                  text: '10 Flashcards\n',
                                  style: TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold)),
                              TextSpan(text: 'Create your own 10 flashcards.'),
                            ],
                          ),
                        ),
                        RichText(
                          text: TextSpan(
                            style: DefaultTextStyle.of(context).style,
                            children: const <TextSpan>[
                              TextSpan(
                                  text: 'Textbooks\n',
                                  style: TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold)),
                              TextSpan(text: 'Download all textbooks in PDF.'),
                            ],
                          ),
                        ),
                          RichText(
                          text: TextSpan(
                            style: DefaultTextStyle.of(context).style,
                            children: const <TextSpan>[
                              TextSpan(
                                  text: 'State Trial Papers\n',
                                  style: TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold)),
                              TextSpan(text: 'Download all trial papers in PDF.'),
                            ],
                          ),
                        ),
                      ],
                    ),
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Icon(
                          Icons.done_rounded,
                          color: Colors.green,
                          size: 24.0,
                        ),
                        Icon(
                          Icons.done_rounded,
                          color: Colors.green,
                          size: 24.0,
                        ),
                        Icon(
                          Icons.done_rounded,
                          color: Colors.green,
                          size: 24.0,
                        ),
                        Icon(
                          Icons.done_rounded,
                          color: Colors.green,
                          size: 24.0,
                        ),
                        Icon(
                          Icons.close,
                          color: Colors.red,
                          size: 24.0,
                        ),
                        Icon(
                          Icons.close,
                          color: Colors.red,
                          size: 24.0,
                        ),
                      ],
                    ),
                  ]),

CodePudding user response:

Solution 1

I would first try to put the rich text widget and the corresponding icon in one Row centering elements vertically, instead of two separate columns which makes it a little more complicated. Like this (just 1 a row example):

Column(
    children: [
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          RichText(
            text: TextSpan(
              style: DefaultTextStyle.of(context).style,
              children: const <TextSpan>[
                TextSpan(
                    text: 'Revision notes\n',
                    style: TextStyle(
                        fontSize: 20, fontWeight: FontWeight.bold)),
                TextSpan(text: 'Free notes.'),
              ],
            ),
          ),
          const Icon(
            Icons.done_rounded,
            color: Colors.green,
            size: 24.0,
          ),
        ],
      ),
    ],
  )

The mainAxisAlignment attribute will align your elements pushing them one to the left and one to the right of the screen.

The crossAxisAlignment attribute will align the element by centering them vertically.


Solution 2

If you still need two columns, then you can read the heights of the single rows on the left with LayoutBuilder and use that size for the height of the icon. Another way is giving all rows fixed height since you always have title and subtitle of the same sizes (better test smaller screens for this one), so you work around the problem entirely. I would leave this one as last solution.

CodePudding user response:

Use a Row and put a Space between them (i used a Spacer here, you can use a SizedBox or something like that):

 Row(
                        children: [
                          RichText(
                          text: TextSpan(
                            style: DefaultTextStyle.of(context).style,
                            children: const <TextSpan>[
                              TextSpan(
                                  text: 'Revision notes\n',
                                  style: TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold)),
                              TextSpan(text: 'Free notes.'),
                            ],
                          ),
                        ),
                          Spacer(),
                          Icon(
                          Icons.close,
                          color: Colors.red,
                          size: 24.0,
                        ),
                        ],
                        ),

CodePudding user response:

I recommend that you make a widget for create each line, so your code will be more readable. Look my example:

    class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Material App Bar'),
        ),
        backgroundColor: Colors.amber,
        body: SizedBox(
          width: 300,
          child: ListView(
            children: const [

              CustomListTile(
                title: 'Revision notes', 
                subtitle: 'Free notes', 
                trailing: Icon( Icons.check, color: Colors.greenAccent, )),
              
              CustomListTile(
                title: 'Quizzes', 
                subtitle: 'Free quizzes', 
                trailing: Icon( Icons.check, color: Colors.greenAccent, )),
              
              CustomListTile(
                title: 'No Ads', 
                subtitle: 'All ... ', 
                trailing: Icon( Icons.check, color: Colors.greenAccent, )),
              
              CustomListTile(
                title: 'Flashcards', 
                subtitle: 'Create your own...', 
                trailing: Icon( Icons.close, color: Colors.redAccent, )),
              
              CustomListTile(
                title: 'Textbooks', 
                subtitle: 'Download all ...', 
                trailing: Icon( Icons.close, color: Colors.redAccent, )),
                
            ],
          ),
        ),
      ),
    );
  }
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class CustomListTile extends StatelessWidget {
  const CustomListTile({
    super.key, 
    required this.title, 
    required this.subtitle, 
    required this.trailing
  });
  final String title;
  final String subtitle;
    final Icon trailing;
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text( title, style: const TextStyle( fontSize: 20 ), ),
      subtitle: Text( subtitle,  style: const TextStyle( fontSize: 14 ), ),
      trailing: trailing,
    );
  }
}

This was my output:

enter image description here

  • Related