4

在我的recyclerview项目中,我需要检查 textview 是否为椭圆形。基于这个条件,我需要做一些逻辑。这是我的项目布局 xml 代码:

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_list_item_root_view"
    style="@style/ClickableRectanglePrimary"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingHorizontal="16dp"
    android:paddingTop="13.5dp"
    android:paddingBottom="14.5dp">

    <ImageView
        android:id="@+id/activity_list_item_contact_image"
        android:layout_width="@dimen/ui_size_xl_2"
        android:layout_height="@dimen/ui_size_xl_2"
        tools:ignore="ContentDescription"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/activity_list_item_name"
        style="@style/activity_list_item_name_v2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|start"
        android:text="ABC India Pvt. Ltd."
        tools:ignore="HardcodedText"
        app:layout_constraintStart_toEndOf="@+id/activity_list_item_contact_image"
        app:layout_constraintEnd_toStartOf="@+id/activity_list_item_amount"
        app:layout_constraintTop_toTopOf="@+id/activity_list_item_contact_image"
        android:layout_marginStart="12dp"
        android:layout_marginEnd="4dp"/>

    <TextView
        android:id="@+id/activity_list_item_date"
        style="@style/activity_list_item_details"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|start"
        android:text="Yesterday"
        tools:ignore="HardcodedText"
        app:layout_constraintTop_toBottomOf="@id/activity_list_item_name"
        app:layout_constraintStart_toEndOf="@id/activity_list_item_contact_image"
        android:layout_marginStart="12dp"
        android:layout_marginTop="4dp"/>

    <TextView
        android:id="@+id/activity_list_item_dot_text"
        style="@style/activity_list_item_details"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|start"
        android:text=" \u00b7 "
        tools:ignore="HardcodedText"
        app:layout_constraintStart_toEndOf="@id/activity_list_item_date"
        app:layout_constraintTop_toBottomOf="@id/activity_list_item_name"
        android:layout_marginTop="4dp"/>

    <ImageView
        android:id="@+id/activity_list_item_status_icon"
        android:layout_width="@dimen/ui_size_xs"
        android:layout_height="@dimen/ui_size_xs"
        android:layout_marginEnd="6dp"
        android:scaleType="fitXY"
        tools:ignore="ContentDescription"
        app:srcCompat="@drawable/ui_purchase_protection_alt"
        app:layout_constraintStart_toEndOf="@id/activity_list_item_dot_text"
        app:layout_constraintTop_toBottomOf="@id/activity_list_item_name"
        android:layout_marginTop="4dp"/>

    <TextView
        android:id="@+id/activity_list_item_status_text"
        style="@style/activity_list_item_details"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|start"
        android:text="Request Received"
        tools:ignore="HardcodedText"
        android:ellipsize="end"
        android:maxLines="1"
        app:layout_constraintStart_toEndOf="@id/activity_list_item_status_icon"
        app:layout_constraintTop_toBottomOf="@id/activity_list_item_name"
        app:layout_constraintEnd_toStartOf="@id/activity_list_item_amount"
        android:layout_marginEnd="4dp"
        android:layout_marginTop="4dp"/>

    <TextView
        android:id="@+id/activity_list_item_status_spillover_text"
        style="@style/activity_list_item_details"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|start"
        android:text="Request Received"
        tools:ignore="HardcodedText"
        android:visibility="gone"
        tools:visibility="visible"
        app:layout_constraintTop_toBottomOf="@id/activity_list_item_date"
        app:layout_constraintStart_toEndOf="@id/activity_list_item_contact_image"
        android:layout_marginStart="12dp"
        android:layout_marginTop="4dp"/>
 
    <TextView
        android:id="@+id/activity_list_item_amount"
        style="@style/UiTextView.Xl.Regular"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center|end"
        android:text="$149.99"
        android:textColor="?attr/ui_v2_color_grey_600"
        android:textSize="18sp"
        tools:ignore="HardcodedText"
        app:layout_constraintTop_toTopOf="@id/activity_list_item_contact_image"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

布局如下所示: 在此处输入图像描述

现在,我想检查这个 textview 是否activity_list_item_status_text是椭圆的,如果它是椭圆的,则在第三行显示 textview activity_list_item_status_spillover_text。如果没有,请隐藏它。我曾经TreeObserver检查过这个。这是里面的代码ViewHolder

TextView statusTextView = binding.activityListItemStatusText;
statusTextView.getViewTreeObserver().addOnDrawListener(() -> {
      Layout layout = statusTextView.getLayout();
      if (layout != null) {
           int lines = layout.getLineCount();
           if (layout.getEllipsisCount(lines - 1) > 0) {
                binding.activityListItemStatusSpilloverText.setVisibility(View.VISIBLE);
           }else {
                binding.activityListItemStatusSpilloverText.setVisibility(View.GONE);
           }
       }
 });

当我打开 recyclerview 时,此代码工作正常。但是,当我滚动 recyclerview 时,对于某些项目,layout.getEllipsisCount(lines - 1) > 0即使文本不是椭圆形并且activity_list_item_status_spillover_text变得可见,这种情况也会变为真。它的类似文本在滚动过程中变得椭圆形。我无法弄清楚为什么会这样。代码有问题吗?

编辑: 添加问题的屏幕录像: https ://drive.google.com/file/d/1l-xUyBJzHy-7BScsbcJPpznhwVSN7Ah4/view?usp=sharing

4

5 回答 5

1

我得到了答案。我更改了查找 tetxview 是否为椭圆的逻辑。我将 textview 代码更改为:

    <TextView
        android:id="@+id/activity_list_item_status_text"
        style="@style/activity_list_item_details"
        android:layout_width="wrap_content"
        app:layout_constrainedWidth="true"
        app:layout_constraintHorizontal_bias="0"
        android:layout_height="wrap_content"
        android:gravity="center_vertical|start"
        android:text="Request Received"
        tools:ignore="HardcodedText"
        app:layout_constraintStart_toEndOf="@id/activity_list_item_status_icon"
        app:layout_constraintTop_toBottomOf="@id/activity_list_item_name"
        app:layout_constraintEnd_toStartOf="@id/activity_list_item_amount"
        android:layout_marginEnd="4dp"
        android:layout_marginTop="4dp"
        android:maxLines="1" />

从上面的代码可以看出,我在代码中添加了这两行:

    app:layout_constrainedWidth="true"
    app:layout_constraintHorizontal_bias="0"

并删除ellipsize="end"

然后我更改了逻辑以检查此代码的省略号:

if (statusTextView.getLineCount() > statusTextView.getMaxLines()) {
     //Ellipsized
} else {
     //Not ellipsized
}

这解决了我的问题。

于 2021-02-16T04:39:16.783 回答
0

这是因为addOnDrawListener()在我们滚动回收站视图时不会按预期工作。onDraw()这里的 lambda 函数表示它本质上是异步的,它会反复调用自身,直到视图显示在屏幕上。

最初,函数会在使用nullPointerException向下滚动回收器视图时崩溃,如果layout.getLines()会调用外部if(layout != null)子句,因为负责创建布局的 textViewHolder 只创建一次,之后它会被反复绑定和重用。因此,textView.getLayout()在滚动的确切时刻给出一个空值

基本上,我们试图在一个视图被销毁和另一个视图即将被绑定的时刻之间调用 textLayout 。这会使布局变量在短时间内为空。

现在,因为当我们向下滚动时布局为空,这部分代码在滚动时永远不会真正起作用,它仅在视图绑定并已显示后才起作用。

if (layout != null) {
           int lines = layout.getLineCount();
           if (layout.getEllipsisCount(lines - 1) > 0) {
                binding.activityListItemStatusSpilloverText.setVisibility(View.VISIBLE);
           }else {
                binding.activityListItemStatusSpilloverText.setVisibility(View.GONE);
           }
       }

这就是为什么一旦向下或向上滚动回收站视图,它会在某些地方产生异常。最好的方法是使用非生命周期相关的方式来定义 textview 是否为椭圆形。

你也可以参考这个文件,最后说

即将绘制视图树时调用的回调方法。此时,不能以任何方式修改视图。

于 2021-02-16T15:45:54.267 回答
0

这在 Recycler 视图中很常见 顾名思义,它回收和重用视图,并且视图获得的属性不会失效。

对不想被回收的 ViewHolder执行viewHolder.setIsRecyclable(false) 。

来自 ViewHolder#setIsRecyclable(boolean) 的文档:

通知回收商此项目是否可以回收。不可回收的视图不会再用于其他项目,直到

setIsRecyclable()

稍后设置为 true。

这将导致仅创建一个ViewHolder

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    ...
    @Override
    public void onViewAttachedToWindow(final RecyclerView.ViewHolder holder) {
        if (holder instanceof VideoViewHolder) {
            holder.setIsRecyclable(false);
        }
        super.onViewAttachedToWindow(holder);
    }

    @Override
    public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder) {
        if (holder instanceof VideoViewHolder){
            holder.setIsRecyclable(true);
        }
        super.onViewDetachedFromWindow(holder);
    }
    ...
}

虽然在长列表的情况下发表这么多观点会有点费力,但是这个问题还是可以解决的。因为每个视图都有其单独的视图

于 2021-02-12T11:12:51.817 回答
0

我想你可以避免使用树观察者。

相反,在视图支架内,您可以测量文本宽度。

使用 textview paint 和这些答案测量要在 Canvas 上绘制的文本宽度(Android)

如果文本宽度超过 textview 宽度,这意味着 textview 将被椭圆化。

于 2021-02-16T18:21:34.860 回答
0

我不知道为什么getEllipsisCount()在您的情况下不起作用(Android 充满了魔力)但是,您可以将支架中的文本与显示的实际文本进行比较,而不是使用它,TextView然后根据结果执行你的逻辑。

于 2021-02-11T07:56:30.220 回答