Clip the 1st widget with ellipsis (on overflow) in a Row of 3 Text widgets

Viewed 235

I have a Row of 3 text widgets. I want the first two to stay together and the third one to be aligned at the end of the row. The first text has the potential to cause an overflow, and when that happens, I only want the first text to be clipped by an ellipsis. Note that the 2nd and 3rd text can vary in length too, so the width at which clipping should be done varies.

I have tried various things, with RichText, Spacer, Expanded, Flexible, etc. The closest I have come to a solution is with this:

Row(
  mainAxisAlignment: MainAxisAlignment.start,
  children: [
    Flexible(
      child: Text(
          "Left most text that overflows the screen and creates an ellipsis",
          overflow: TextOverflow.ellipsis,
      ),
    ),
    Text(
      "Xyz",
      style: customStyle1,
    ),
    Text(
      " 10:20",
      style: customStyle2,
    ),
  ],
),

This is what it leads to (with added colors). If the time stays to the right in the first row, the problem will be solved.

enter image description here

Adding a spacer between the last two texts causes the first to occupy just half the screen, i.e., the ellipsis gets added prematurely. Adding an Expanded to last Text causes the

"NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE" bug.

The first and the last row in this image are the desired outputs.

enter image description here

How do I accomplish this? And can anyone explain the issue with using a Spacer or an Expanded as mentioned above?

3 Answers

We can use two rows to align items, Flexible and Text softWrap to fix the overflow

 Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    Expanded(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: const [
          Flexible(
            child: Text(
              "Left most text that overflows the screen and creates an ellipsis",
              overflow: TextOverflow.ellipsis,
              softWrap: false,
            ),
          ),
          Text("Xyz"),
        ],
      ),
    ),
    Text(
      " 10:20",
    ),
  ],
),

enter image description here

enter image description here

You can use a constrained box

Row(
 children: [
 ConstrainedBox(
  constraints: BoxConstraints(
    maxWidth: MediaQuery.of(context).size.width / 2,
  ),
   child: const Text(
     "Left most text that overflows the screen and creates an ellipsis",
     overflow: TextOverflow.ellipsis,
   ),
 ),
 const Text('xyz'),
 const Spacer(),
 const Text('10:20'),
 ],
),

Screen Shot

///you can use SizedBox and assign width and you can set your text. This is not the perfect solution but this works for me. 
    import 'package:flutter/material.dart';
    
    class MyAseet extends StatefulWidget {
      const MyAseet({Key? key}) : super(key: key);
    
      @override
      _MyAseetState createState() => _MyAseetState();
    }
    
    class _MyAseetState extends State<MyAseet> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Padding(
            padding: const EdgeInsets.only(left:20.0,top: 50),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    SizedBox(
                      width: 200,
                      child: Text(
                        "Left most text that overflows the screen and creates an ellipsis",
                        overflow: TextOverflow.ellipsis,
                        maxLines: 1,
                      ),
                    ),
                    Text(
                      "Xyz",
                      style: TextStyle(color: Colors.grey),
    
                    ),
                    Container(
                      color: Colors.blue,
                      child: Text(
                        " 10:20",
                      ),
                    ),
                  ],
                ),
                Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    SizedBox(
                      width: 200,
                      child: Text(
                        "Left most text that overflows the screen and creates an ellipsis",
                        overflow: TextOverflow.ellipsis,
                        maxLines: 1,
                      ),
                    ),
                    Text(
                      "Xyz",
                      style: TextStyle(color: Colors.grey),
    
                    ),
                    Container(
                      color: Colors.blue,
                      child: Text(
                        " 10:20",
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        );
      }
    }
Related