【问题标题】:Detect if TextVIew is ellipsized before layout is shown在显示布局之前检测 TextVIew 是否被椭圆化
【发布时间】:2013-11-19 11:09:55
【问题描述】:

我有一个最多 3 行的 TextView,下面有一个“显示更多”按钮。逻辑是,如果 TextView 中的文本可以放入其中,则隐藏“显示更多”按钮;否则,如果文本不能容纳 3 行,则会显示“显示更多”。

我的方法(不起作用)是:使用textView.getLayout().getEllipsisCount(maxNumberOfline) 检测 TextView 是否为椭圆形,然后隐藏或显示“显示更多”按钮。但是当布局尚未完成时,调用 textView.getLayout() 返回 null。我试图将textView.getLayout().getEllipsisCount(maxNumberOfline) 放入onStart()onResume() 但没有运气。

有没有其他方法可以做到这一点?

【问题讨论】:

标签: android android-layout


【解决方案1】:

试试这个方法,希望能帮助你解决问题。

    @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(但你不需要把演示文本写那么长 ;-)
  • @haresh Chhelana:是否可以使用最大字符而不是行数?
  • @Sneha,是的,我已经根据您的要求修改了我的代码,所以您能否提出问题,提供我的链接,或者如果您已经提出问题,请提供问题链接。
  • @HareshChhelana:感谢您的回复!我的问题不是指定 maxLine,而是需要一个 maxCharacters。例如如果 chars ==200 显示文本原样.. 如果 maxChars > 200 则显示“查看更多”选项。一旦文本被展开,如果用户在任何地方点击文本,它应该再次压缩。我试过了,但是在将点击监听器设置为整个文本时遇到了问题。甚至“查看更多”跨区文本也会监听点击事件。
  • @Sneha,您只需提出问题,我会提供帮助您解决问题的答案。
【解决方案2】:

我也遇到过这种问题,下面的代码居然解决了:

    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);
                    }
                }
            }
    }

直到我注意到它在操作系统版本 2.3.5 中不起作用。即使 mTextView.getLineCount() 返回正确的行数,layout.getEllipsisCount(lines - 1) 也永远不会返回大于 0 的数字。接下来发生的是“显示更多”按钮从未出现,尽管 TextView最后已经被截断了。然后我意识到可以将实现更改为以下。它现在正在工作。

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
    }

}

【讨论】:

    猜你喜欢
    • 2011-08-16
    • 2013-03-12
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 2021-01-19
    相关资源
    最近更新 更多