【问题标题】:Unable to implement readmore feature to TextView in Android无法在 Android 中为 TextView 实现 readmore 功能
【发布时间】:2017-05-03 17:53:05
【问题描述】:

我正在开发一个 Android 应用程序。在我的应用程序中,我需要在 Facebook 帖子中实现 TextView 的更多功能。我的应用程序还具有像 Facebook 一样的新提要功能。我正在为 RecyclerView 适配器中的每个 TextView 实现。但它给了我错误。

在 RecyclerAdapter 中,我正在像这样使用自定义事件侦听器设置 Readmore 功能。这发生在 Adapter 的 onBindViewHolder 中。

   viewHolder.tvTitle.setText(post.getTitle());
    listener.ReadMoreListener(viewHolder.tvTitle, 3, "Read more", true);

这是事件监听接口

public interface AdapterListener{

        public void ReadMoreListener(TextView textView, int maxLine, String expandText, boolean viewMore);
    }

这就是我为 Fragment 中的每个 TextView 实现事件和阅读更多功能的方式。

在Activity的onCreateView中,我设置了这样的事件。

adapter.setAdapterListener(new MemeListAdapter.AdapterListener() {

            @Override
            public void ReadMoreListener(TextView textView, int maxLine, String expandText, boolean viewMore) {
                makeTextViewResizable(textView, maxLine, expandText, viewMore);
            }
        });

这些是在 Fragment 中实现 readmore 功能所需的方法。

public static void makeTextViewResizable(final TextView tv, final int maxLine, final String expandText, final boolean viewMore) {

        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;//This line is throwing error.
                    tv.setText(text);
                    tv.setMovementMethod(LinkMovementMethod.getInstance());
                    tv.setText(
                            addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, maxLine, expandText,
                                    viewMore), TextView.BufferType.SPANNABLE);
                } else if (maxLine > 0 && 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, maxLine, expandText,
                                    viewMore), TextView.BufferType.SPANNABLE);
                } else {
                    int lineEndIndex = tv.getLayout().getLineEnd(tv.getLayout().getLineCount() - 1);
                    String text = tv.getText().subSequence(0, lineEndIndex) + " " + expandText;
                    tv.setText(text);
                    tv.setMovementMethod(LinkMovementMethod.getInstance());
                    tv.setText(
                            addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, lineEndIndex, expandText,
                                    viewMore), TextView.BufferType.SPANNABLE);
                }
            }
        });

    }

    private static SpannableStringBuilder addClickablePartTextViewResizable(final Spanned strSpanned, final TextView tv,
                                                                            final int maxLine, final String spanableText, final boolean viewMore) {
        String str = strSpanned.toString();
        SpannableStringBuilder ssb = new SpannableStringBuilder(strSpanned);

        if (str.contains(spanableText)) {
            ssb.setSpan(new ClickableSpan() {

                @Override
                public void onClick(View widget) {

                    if (viewMore) {
                        tv.setLayoutParams(tv.getLayoutParams());
                        tv.setText(tv.getTag().toString(), TextView.BufferType.SPANNABLE);
                        tv.invalidate();
                        makeTextViewResizable(tv, -1, "View Less", false);
                    } else {
                        tv.setLayoutParams(tv.getLayoutParams());
                        tv.setText(tv.getTag().toString(), TextView.BufferType.SPANNABLE);
                        tv.invalidate();
                        makeTextViewResizable(tv, 3, "View More", true);
                    }

                }
            }, str.indexOf(spanableText), str.indexOf(spanableText) + spanableText.length(), 0);

        }
        return ssb;

    }

当我运行我的代码时,它给了我这个错误:

我在代码中将“此行正在引发错误”注释到引发错误的位置。我在此链接上引用了 - Add "View More" at the end of TextView after 3 lines。错误的原因是什么?我知道这是空异常错误。我该如何解决?

我发现tv.getLayout() 总是返回null。如何将 Layout 设置为 TextView 不返回 null?

【问题讨论】:

  • 你有什么解决办法吗?我也在复制这个
  • @aj0822ArpitJoshi 你有解决这个问题的办法吗?

标签: android textview


【解决方案1】:

对此最简单的答案是以编程方式设置 textview 的最大行数。例如,假设您的 tvTitle 文本视图下方有一个 tvReadMore 文本视图。首先检查您的 tvTitle textview 的文本是否足以显示 tvReadMore。如果是这样,请将 maxLine 设置为 Integer.MAX_VALUE。看看下面的示例代码

if(post.getTitle.length() > 50) { //assuming you want to show the [Read more] for more than 50 characters
   if(ViewHolder.tvReadMore.getText().toString().equalsIgnoreCase("Read More")) { //you should set the text of tvReadMore textview to [Read more] in the beginning
       viewHoler.tvTitle.setMaxLines(Integer.MAX_VALUE); //set the maximum line to Maximum integer
       viewHolder.tvReadMore.setText("Show Less")
   } else {
        viewHoler.tvTitle.setMaxLines(3); //set the maximum line to 3
        viewHolder.tvReadMore.setText("Read more")
   }
} else { //if there are no enough characters to show the read more text
   viewHolder.tvTitle.setVisibility(View.GONE); //hide the read more textview
}

我已经看到很多变通方法来实现 textview 的阅读更多功能,但在我看来,这是迄今为止最简单和最简单的方法。这样做的好处是,它适用于简单的 textview 和 recyclerview 中的 textview。 如果要在文本末尾添加三个点,当隐藏的行更多时,可以添加

 android::ellipsize(end)

到您的 tvTitle 文本视图。

【讨论】:

    猜你喜欢
    • 2015-02-12
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多