【问题标题】:Using custom view in RecyclerView widget在 RecyclerView 小部件中使用自定义视图
【发布时间】:2015-07-19 17:11:12
【问题描述】:

我在呈现自定义视图内部回收器视图小部件时遇到问题。传统上我们在 RecylerView.Adapter 中膨胀视图,就像

public RowLayoutViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    View view = LayoutInflater.from(context).inflate(R.layout.sample_view, viewGroup, false);
    RowLayoutViewHolder rowLayoutViewHolder = new RowLayoutViewHolder(view);
    return rowLayoutViewHolder;
}

这很好用,我们可以将数据绑定到 onBindViewHolder(...) 方法中的视图。但是当我尝试创建 ViewGroup 的子类并像这样使用它时,我得到一个空白(“黑色”)屏幕。

public ImageGalleryAdapter.RowLayoutViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
  SampleView view = new SampleView(context);
  RowLayoutViewHolder rowLayoutViewHolder = new RowLayoutViewHolder(view);
  return rowLayoutViewHolder;
}

这是我的 SampleView 类 -

public class SampleView extends ViewGroup {

  public SampleView(Context context) {
    super(context);
    initView();
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b)  {
    for (int i = 0; i < getChildCount(); i++) {
      View child = getChildAt(i);
      child.layout(l, t, l + 600, t + 200);
    }
  }

  private void initView() {
    inflate(getContext(), R.layout.sample_view, this);
    TextView textView = (TextView) findViewById(R.id.sampleTextView);
    textView.setTextColor(Color.WHITE);
    textView.setText("Hello from textview");
  }
}

这是布局 -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:background="@color/white"
          android:layout_width="match_parent"
          android:layout_height="wrap_content">

    <TextView
        android:id="@+id/sampleTextView"
        android:text="Sample TextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

查看源代码似乎膨胀布局的行为与创建视图完全相同,只是膨胀过程基于 rootView 为子视图添加了合适的 LayoutParameter。我试过手动添加,但没有任何结果。

我们将不胜感激。

【问题讨论】:

  • 你找到解决这个问题的方法了吗,我有类似的问题,因为我在我的回收站视图中使用视图持有者如何在其布局中自定义视图,当我向后滚动并快速滚动时回收站视图只是错过了一些绘制,并在屏幕上留下了回收站视图中的一些先前项目
  • 我找到了解决方案。因为我错过了滚动时回收器视图需要重新填充所有内容的部分,所以我没有填充布局的每个部分,这非常重要,这就是为什么我从其他一些子视图中查看数据的原因。

标签: android android-custom-view android-recyclerview


【解决方案1】:

这很简单。如果您看到通过膨胀添加视图的方式,您会意识到您正在将其添加到父级(ViewGroup)但没有附加它。在此过程中,将生成默认 LayoutParams 并将其设置为您的视图。 (查看 LayoutInflater 源码)

SampleView view = new SampleView(context);
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

这是应该的。甚至以下似乎也有效。

viewGroup.add(view, new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

【讨论】:

    【解决方案2】:

    我已经习惯了最初的方法,所以我不确定发生了什么。 你试过从 onLayout() 方法调用 initView 吗?

    【讨论】:

    • 我刚试过,没用。仍然看到黑屏。当我在 onBindViewHolder(...) 方法中调用 view.isAttachedToWindow() 时,它返回 true。
    【解决方案3】:

    我已经以一种可能有帮助的迂回方式成功解决了这个问题

    在自定义视图中,比如 SampleView,用任何你想修改布局的方法(我猜这里是onLayout()),注册

    getViewTreeObserver().addOnGlobalLayoutListener(new LayoutViewTreeObserver())
    

    在 LayoutViewTreeObserver 的回调中:

    @Override
        public void onGlobalLayout() {
            // Do layout stuff here
        }
    

    另外,作为旁注,不要忘记在修改之前删除 GlobalOnLayoutListener,这样回调就不会再得到必要的调用(实际上,我不得不调用 getViewTreeObserver() 而不是保留对观察者很多时候引用停止“活着”并在我尝试取消注册时抛出错误)。


    虽然上述方法对我有用,但我意识到它远非理想,因为它依赖于自定义视图通常获取容器类的 LayoutParams 的事实,如果在其他地方使用不会是 RecyclerView.LayoutParams,从而导致一个错误。但是,我发现使用仅将 CustomView 作为 XML 中的基本标记的 XML 布局并以标准方式膨胀/绑定可以按预期工作。它与 RecyclerView 如何附加视图和之前完成的测量有关,但我还没有深入了解究竟是为什么。

    【讨论】:

      【解决方案4】:

      在您的onCreateViewHolder() 中尝试将参数设置为您创建的视图并将其宽度设置为parent.getMeasuredWidth() 看看是否有帮助,它解决了我的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多