I'm trying to add a functionality to each question, represented as a ListTile, so that it can upvote or downvote a question, and show the net votes, just like the one that is used on stack overflow. My current implementation does a bottom overflow for each ListTile.

          Card(
            child: new Column(
              children: <Widget>[
                new ListTile(
                  leading: Column(
                    children: <Widget>[
                      FlatButton(
                        child: Icon(Icons.arrow_drop_up),
                        onPressed: () {},
                      ),
                      StreamBuilder<DocumentSnapshot>(
                        stream: RoomDbService(widget.roomName, widget.roomID)
                            .getQuestionVotes(widget.questionID),
                        builder: (context, snapshot) {
                          if (!snapshot.hasData) {
                            return Center(child: CircularProgressIndicator());
                          } else {
                            print(snapshot.data.data["votes"]);
                            return Text("${snapshot.data.data["votes"]}");
                          }
                        },
                      ),
                      FlatButton(
                        child: Icon(Icons.arrow_drop_down),
                        onPressed: () {},
                      ),
                    ],
                  ), // shows votes of this qn on the left of the tile
                  title: Text(text),
                  trailing: FlatButton(
                    child: Icon(Icons.expand_more),
                    onPressed: toggleExpansion,
                  ),

                )
              ],
            ),
          );

enter image description here

My previous implementation (which I forgot how it looked like) made it look like a row of an up button, the vote count, and the down button. How do I do it properly?


Solution 1: Sagar Acharya

Check out this example Taking you example I have made some modifications in the code

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: HomePage());
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: SingleChildScrollView(
          child: Card(
        child: new Column(
          children: <Widget>[
            SizedBox(
              height: 10,
            ),
            Container(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Column(
                    children: <Widget>[
                      InkWell(onTap: () {}, child: Icon(Icons.arrow_drop_up)),
                      Text(
                        "your Text,
                        style: TextStyle(fontSize: 10),
                      ),
                      InkWell(onTap: () {}, child: Icon(Icons.arrow_drop_down)),
                    ],
                  ),
                  Text('You stream text'),
                  FlatButton(
                    child: Icon(Icons.expand_more),
                    onPressed: () {},
                  ),
                ],
              ),
            )
          ],
        ),
      )),
    );
  }
}

Let me know if it works.


Solution 2: Darshan Rathod

You can make custom widget for your desired layout using Row....

But if you still want to use ListTile, then you have to make somechanges in your code, ListTile's height we can't set as we want, it's depends on subtitle and isThreeLine property.

So you can get some more height if you add subtitle, and with isThreeLine : true, gives your subtitle more height to fit in ListTile....

For your case you need change leading widget....Use InkWell instead of FlatButton....

  • Make some changes in CircularProgressIndicator.
  • use small sized icon for upvote/downvote and use small Text for count, otherwise it will overflow again.

See the code below or play with it at DartPad ListTile_StackOverFlow.

    Card(
      child: ListTile(
        leading: Column(
            children:[
              InkWell(
                child:  Icon(Icons.arrow_drop_up),
                onTap: () {}
              ),
              Container(
                height: 8,
                width:8,
                child: Center(child: CircularProgressIndicator(strokeWidth :2))
              ),
              InkWell(
                child: Icon(Icons.arrow_drop_down),
                onTap: () {}
              ),
            ]
          ),
        title: Text('Titled text'),
        trailing: Icon(Icons.more_vert),
      ),
    );

Better solution is use Row and column and make your own custom Widget that looklike ListTile.... see the official document, here you can see an example which has CustomListTile class which creates the custom looking ListTile( which is not directly using ListTile )....

My advise : You should make your custom class as like above Documentation's CustomListTile class