Cassie Liu
Cassie Liu

Reputation: 195

Flutter - Expandable text not working properly with overflow property

Basically I want to achieve exactly the same thing as Flutter: How to hide or show more text within certain length. Here is my code snippet.

LayoutBuilder(
                  builder: (BuildContext context, BoxConstraints constraints) {
                final TextSpan span = TextSpan(
                  text: text,
                  style: TextStyle(
                    fontSize: 13,
                  ),
                );
                final TextPainter textPainter = TextPainter(
                  text: span,
                  maxLines: 1,
                  ellipsis: '...',
                  textDirection: TextDirection.ltr,
                );
                textPainter.layout(maxWidth: constraints.maxWidth);

                if (textPainter.didExceedMaxLines)
                  return Row(
                    crossAxisAlignment: _basicInformationIsExpanded
                        ? CrossAxisAlignment.end
                        : CrossAxisAlignment.start,
                    children: <Widget>[
                      Expanded(
                        child: Text(
                          text,
                          style: TextStyle(
                            fontSize: 13,
                          ),
                          maxLines: _isExpanded ? null : 1,
                          //overflow: TextOverflow.ellipsis,
                        ),
                      ),
                      GestureDetector(
                        child: _isExpanded
                            ? Icon(
                                Icons.expand_less,
                              )
                            : Icon(
                                Icons.expand_more,
                              ),
                        onTap: () {
                          setState(() => _isExpanded =
                              !_isExpanded);
                        },
                      ),
                    ],
                  );
                else
                  return Text(
                    text,
                    style: TextStyle(
                      fontSize: 13,
                    ),
                  );
              }),

The weird thing is if I comment overflow: TextOverflow.ellipsis,, everything is fine. But I need to show the ellipsis and if I add that line, the text doesn't expand when I click the icon.

Can anyone help me with it? Thanks.

Upvotes: 0

Views: 966

Answers (2)

chunhunghan
chunhunghan

Reputation: 54367

You can copy paste run full code below
You can set overflow based on _isExpanded

overflow: _isExpanded ? null : TextOverflow.ellipsis,

working demo

enter image description here

full code

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
                width: 200,
                child: ExpandText(
                  text: "long string" * 10,
                )),

          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class ExpandText extends StatefulWidget {
  String text;
  ExpandText({this.text});
  @override
  _ExpandTextState createState() => _ExpandTextState();
}

class _ExpandTextState extends State<ExpandText> {
  bool _isExpanded = false;
  bool _basicInformationIsExpanded = true;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
      final TextSpan span = TextSpan(
        text: widget.text,
        style: TextStyle(
          fontSize: 13,
        ),
      );
      final TextPainter textPainter = TextPainter(
        text: span,
        maxLines: 1,
        ellipsis: '...',
        textDirection: TextDirection.ltr,
      );
      textPainter.layout(maxWidth: constraints.maxWidth);

      if (textPainter.didExceedMaxLines) {
        print("exceed");
        return Row(
          crossAxisAlignment: _basicInformationIsExpanded
              ? CrossAxisAlignment.end
              : CrossAxisAlignment.start,
          children: <Widget>[
            Expanded(
              flex: 1,
              child: Text(
                widget.text,
                style: TextStyle(
                  fontSize: 13,
                ),
                maxLines: _isExpanded ? null : 1,
                overflow: _isExpanded ? null : TextOverflow.ellipsis,
              ),
            ),
            GestureDetector(
              child: _isExpanded
                  ? Icon(
                      Icons.expand_less,
                    )
                  : Icon(
                      Icons.expand_more,
                    ),
              onTap: () {
                setState(() => _isExpanded = !_isExpanded);
              },
            ),
          ],
        );
      } else {
        print("not exceed");
        return Text(
          widget.text,
          style: TextStyle(
            fontSize: 13,
          ),
        );
      }
    });
  }
}

Upvotes: 1

Manish
Manish

Reputation: 436

A long ago i stumbled onto same thing, surely using these widget's is a way to do this, but here is the code which i wrote and its totally customizable.

You can change the limit variable to use it accordinly

class QNAContainer extends StatefulWidget {
  final String ques;
  final String answer;
  QNAContainer({@required this.ques, @required this.answer});
  @override
  _QNAContainerState createState() => _QNAContainerState();
}

class _QNAContainerState extends State<QNAContainer> {
  String truncAns;
  bool showingAll = false;
  int limit = 80;
  @override
  void initState() {
    super.initState();
    if (widget.answer.length > limit ) {
      print("truncc");
      truncAns = widget.answer.toString().substring(0, limit) + '...';
    } else {
      truncAns = widget.answer;
    }
  }

  @override
  Widget build(BuildContext context) {
    ScreenUtil.instance = ScreenUtil(
        width: Styles.get_width(context),
        height: Styles.get_height(context),
        allowFontScaling: true);
    return Container(
      width: double.infinity,
      padding: EdgeInsets.symmetric(horizontal: ScreenUtil().setWidth(10), vertical: ScreenUtil().setHeight(10)),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(5),
        color: AppColors.greyFillColor.withOpacity(0.6),
      ),
      margin: EdgeInsets.symmetric(vertical: ScreenUtil().setHeight(7)),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(widget.ques,
              style: TextStyle(
                fontSize: ScreenUtil().setHeight(14),
                fontWeight: FontWeight.bold,
              )),
          SizedBox(height: ScreenUtil().setHeight(5)),
          Text(showingAll ? widget.answer : truncAns,
              style: TextStyle(
                fontSize: ScreenUtil().setHeight(14),
              )),
          SizedBox(height: ScreenUtil().setHeight(5)),
          truncAns.contains('...')
              ? GestureDetector(
                  onTap: () {
                    setState(() {
                      showingAll = !showingAll;
                    });
                  },
                  child: Align(
                    alignment: Alignment.centerRight,
                    child: Container(
                      margin: EdgeInsets.only(bottom: ScreenUtil().setHeight(5)),
                      padding: EdgeInsets.symmetric(vertical: ScreenUtil().setHeight(5), horizontal: ScreenUtil().setWidth(9)),
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: AppColors.kDefaultPink),
                      child: Text(
                        showingAll ? 'see less' : 'see more',
                        style: TextStyle(color: Colors.white, fontSize: ScreenUtil().setHeight(14)),
                      ),
                    ),
                  ),
                )
              : SizedBox()
        ],
      ),
    );
  }
}

Upvotes: 0

Related Questions