Using custom view in RecyclerView widget

I am having trouble rendering a widget widget for widgets. Traditionally we inflate the view inside the RecylerView.Adapter like

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

      

This works great and we can bind data to the view inside the onBindViewHolder (...) method. But when I try to subclass ViewGroup and use it like this, I get a blank ("black") screen.

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

      

Here's my SampleView class -

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

      

And here is the layout -

<?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>

      

Looking at the source code, it seems that inflating the layout behaves exactly like creating a view, except that the inflation process adds a suitable LayoutParameter to the rootView based child view. I tried adding this manually but without any results.

Any help would be appreciated.

+3


source to share


4 answers


It's pretty simple. If you see a way to add a view by inflating it, you know you are adding it to the parent (ViewGroup), but not attaching it. This process creates default LayoutParams by default. (Check source LayoutInflater)

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

      



This is how it should be. Even the following seems to work.

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

      

+3


source


I'm used to the original methodology so I'm not sure what's going on. have you tried calling initView from onLayout () method?



0


source


I have successfully solved the problem with a workaround that might help

In a custom view, say SampleView, in any method you want to change the layout (I think here onLayout()

), register

getViewTreeObserver().addOnGlobalLayoutListener(new LayoutViewTreeObserver())

      

in the callback for LayoutViewTreeObserver:

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

      

Also, as a side note, remember to remove the GlobalOnLayoutListener before making changes, so the callback doesn't receive any more calls it needs (in practice I had to call getViewTreeObserver()

instead of referring to the observer how many times the link stops being "live" and throws an error. when I try to cancel it).


While the above worked for me, I realized that it is far from ideal as it relies on the fact that the custom view usually gets the LayoutParams of the container class, which, if used elsewhere, will not be RecyclerView.LayoutParams, which is causes an error. However, I found that using the XML layout only with the CustomView as the base tag in the XML and bloating / binding the standard way works as expected. It has something to do with how the RecyclerView bind the view and dimensions (dimensions) before, but I still have a deep dive to do to figure out why.

0


source


In yours onCreateViewHolder()

try setting the options for the view you created and for the width set it to parent.getMeasuredWidth()

to see if that helps and solved my problem.

0


source







All Articles