4

I have a TextView with maximun 3 lines and a "Show more" button below it. The logic is that if the text in the TextView can fit inside it, the "Show more" button is hidden; otherwise if the text cannot fit in 3 lines, the "Show more" is shown.

My way (which is not working) is that: detect if the TextView is ellipsized by using textView.getLayout().getEllipsisCount(maxNumberOfline) then hide or show the "Show more" button. But the call textView.getLayout() return null when the layout is not finish yet. I tried to put textView.getLayout().getEllipsisCount(maxNumberOfline) in onStart() and onResume() but no luck.

Does anyone have another way to do this?

Henry Pham
  • 2,429
  • 3
  • 19
  • 19
  • 1
    Take a look at [this](http://stackoverflow.com/questions/16558948/how-to-use-textview-getlayout-it-returns-null) question – SSS Nov 19 '13 at 11:53

2 Answers2

4

Try this way,hope this will help you to solve your problem.

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textview = (TextView) findViewById(R.id.textview);
        textview.setText("demotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotextdemotext");
        TextViewResizable(textview,3,"See More");
    }

    public void TextViewResizable(final TextView tv,final int maxLine, final String expandText) {
        if (tv.getTag() == null) {
            tv.setTag(tv.getText());
        }
        ViewTreeObserver vto = tv.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

            @SuppressWarnings("deprecation")
            @Override
            public void onGlobalLayout() {
                ViewTreeObserver obs = tv.getViewTreeObserver();
                obs.removeGlobalOnLayoutListener(this);
                if (maxLine <= 0) {
                    int lineEndIndex = tv.getLayout().getLineEnd(0);
                    String text = tv.getText().subSequence(0,lineEndIndex - expandText.length() + 1)+ " " + expandText;
                    tv.setText(text);
                    tv.setMovementMethod(LinkMovementMethod.getInstance());
                    tv.setText(addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, expandText), TextView.BufferType.SPANNABLE);
                } else if (tv.getLineCount() >= maxLine) {
                    int lineEndIndex = tv.getLayout().getLineEnd(maxLine - 1);
                    String text = tv.getText().subSequence(0,lineEndIndex - expandText.length() + 1)+ " " + expandText;
                    tv.setText(text);
                    tv.setMovementMethod(LinkMovementMethod.getInstance());
                    tv.setText(addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, expandText), TextView.BufferType.SPANNABLE);
                }
            }
        });



    }

    private  SpannableStringBuilder addClickablePartTextViewResizable(final Spanned strSpanned, final TextView tv,final String expandText) {
        String str = strSpanned.toString();
        SpannableStringBuilder ssb = new SpannableStringBuilder(strSpanned);

        if (str.contains(expandText)) {
            ssb.setSpan(new Spannable(Color.BLUE, true) {
                        @Override
                        public void onClick(View widget) {
                            tv.setLayoutParams(tv.getLayoutParams());
                            tv.setText(tv.getTag().toString(),TextView.BufferType.SPANNABLE);
                            tv.invalidate();
                        }
                    }, str.indexOf(expandText), str.indexOf(expandText)+ expandText.length(), 0);

        }
        return ssb;

    }

    class Spannable extends ClickableSpan {

        private int color = -1;
        private float fontSize = -1;
        private boolean isUnderline = true;

        /**
         * Constructor
         */
        public Spannable() {
        }

        /**
         * Constructor
         */
        public Spannable(int color) {
            this.color = color;
        }

        /**
         * Constructor
         */
        public Spannable(float fontSize) {
            this.fontSize = fontSize;
        }

        /**
         * Constructor
         */
        public Spannable(boolean isUnderline) {
            this.isUnderline = isUnderline;
        }

        /**
         * Constructor
         */
        public Spannable(int color, boolean isUnderline) {
            this.isUnderline = isUnderline;
            this.color = color;
        }

        /**
         * Constructor
         */
        public Spannable(int color, float fontSize) {
            this.color = color;
            this.fontSize = fontSize;
        }

        /**
         * Overrides methods
         */
        @Override
        public void updateDrawState(TextPaint ds) {

            if (color != -1) {
                ds.setColor(color);
            }
            if (fontSize > 0) {
                ds.setTextSize(fontSize);
            }

            ds.setUnderlineText(isUnderline);

        }

        @Override
        public void onClick(View widget) {

        }
    }
Haresh Chhelana
  • 24,720
  • 5
  • 57
  • 67
  • Work like a charm!!! Thank you Haresh (but you don't need to make the demo text that long ;-) – Henry Pham Nov 19 '13 at 16:19
  • @haresh Chhelana: is it possible to have max characteres instead of lines ? – user2234 Oct 10 '14 at 15:52
  • @Sneha,Yes i have modify my code as per your requirement so can you please ask question provide me link or if your already asked then just provide me you question link. – Haresh Chhelana Oct 11 '14 at 05:08
  • @HareshChhelana: Thanks for your reply! My problem is instead of specifying maxLine, i needed a maxCharacters. Such as if chars ==200 show the text as it is.. if maxChars > 200 then show "see more" option. Once the text is expanded, if user clicks on the text anywhere it should compress again. I tried it, but facing problem while setting click listener to the whole text. As even "see more" spanned text listens to the click event. – user2234 Oct 12 '14 at 17:14
  • @Sneha,You just ask question and i provide ans which is help you to solve your problem. – Haresh Chhelana Oct 13 '14 at 04:35
  • @HareshChhelana: I am not getting what you saying! :( – user2234 Oct 13 '14 at 05:18
  • @Sneha,ask new question with your requirement in stack overflow and give me link to this question. – Haresh Chhelana Oct 13 '14 at 05:35
  • @HareshChhelana: Here is my question link: http://stackoverflow.com/questions/26333721/issue-with-handling-click-on-expandable-textview – user2234 Oct 13 '14 at 05:55
1

I also had this kind of problem, the following code actually fixed it:

    mTextView.getViewTreeObserver().addOnGlobalLayoutListener(
                            new OnGlobalLayoutListener() {
                                @Override
                                public void onGlobalLayout() {
                                    showHideMoreButton(mTextView);
                                }
                            });


    public void showHideMoreButton(TextView mTextView) {
            Layout layout = mTextView.getLayout();
            if (layout != null) {
                int lines = layout.getLineCount();
                if (lines > 0) {
                    int ellipsisCount = layout.getEllipsisCount(lines - 1);
                    if (ellipsisCount > 0) {
                        mShowMoreButton.setVisibility(View.VISIBLE);
                    }
                }
            }
    }

until I noticed that it's not working in OS version 2.3.5. Even though the mTextView.getLineCount() is returning the correct number of lines, the layout.getEllipsisCount(lines - 1) never returns number which is greater than 0. What happened next is that the "Show More" button never appears although the TextView has already been truncated at the end. Then I realized that the implementation can be changed to the following. It's working now.

public void showHideMoreButton(TextView mTextView) {
    int lines = mTextView.getLineCount();

    if (lines > 2) {
        mShowMoreButton.setVisibility(View.VISIBLE);
        mTextView.setSingleLine(false);
        mTextView.setEllipsize(TextUtils.TruncateAt.END);
        mTextView.setLines(2); //no. of lines you want your textview to display
    }

}
Rain
  • 11
  • 2