在RecyclerView小部件中使用自定义视图

时间:2015-07-19 17:11:12

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

我在渲染自定义视图内部回收器视图窗口小部件时遇到问题。传统上,我们将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。我尝试手动添加但没有任何结果。

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

非常简单。如果您通过对其进行膨胀来查看添加视图的方式,则会意识到您将其添加到父级(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));

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我以迂回的方式成功地解决了这个问题,这可能会有所帮助

在自定义视图中,比如说SampleView,无论你想修改布局的方法是什么(我猜这里onLayout()),注册

getViewTreeObserver().addOnGlobalLayoutListener(new LayoutViewTreeObserver())

在LayoutViewTreeObserver的回调中:

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

另外,作为旁注,请不要忘记在修改之前删除GlobalOnLayoutListener,这样回调就不再需要调用(实际上,我必须调用{{1}而不是保持对观察者的引用,因为很多时候引用停止了#34; alive&#34;并且当我尝试取消注册它时会抛出错误。)

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

答案 3 :(得分:0)

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