Search code examples
javaandroidandroid-recyclerviewandroid-custom-view

Embedding a RecyclerView within a custom view


I am trying to embed a RecyclerView within the body of a custom view (a RefreshableList).

This is my project's structure: it contains 2 modules, app & rlist.

Project view

the rlist module holds the custom view (RefreshableList) in which I want to embed a RecyclerView.

RefreshableList.java (The custom view)

public class RefreshableList extends RelativeLayout {

    private RecyclerView mRecyclerView;

    private Context mContext;
    private MyAdapter mAdapter;

    public RefreshableList(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        Log.i("ADAPTER", "RefreshableList is initializing views...");

        setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT));

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.refreshable_list, null);

        findViewsById(view);
        setupRecyclerView();
    }

    private void findViewsById(View view) {
        mRecyclerView = (RecyclerView) view.findViewById(R.id.dataRecyclerView);
        Log.i("ADAPTER", "RecyclerView has been initialized.");
    }

    private void setupRecyclerView() {
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
        Log.i("ADAPTER", "RecyclerView has been setup.");
    }

    public void setAdapter(MyAdapter adapter) {
        mAdapter = adapter;
        mRecyclerView.setAdapter(mAdapter);
        Log.i("ADAPTER", "Adapter has been set." + mAdapter.getItemCount());
    }
}

MyAdapter.java (The RecyclerView's adapter)

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    protected Context mContext;
    protected List<String> mItems;

    public MyAdapter(Context context, List<String> items) {
        mContext = context;
        mItems = new ArrayList<>(items);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_row, parent, false);
        Log.i("ADAPTER", "Creating row...");

        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.label.setText(mItems.get(position));
    }

    @Override
    public int getItemCount() {
        return mItems.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {

        TextView label;

        public ViewHolder(View itemView) {
            super(itemView);
            label = (TextView) itemView.findViewById(R.id.label);
        }
    }
}

item_row.xml: (the XML layout of the RecyclerView's elements)

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="New Text"
        android:id="@+id/label"
        android:gravity="left|center_vertical"
        android:padding="8dp"
        android:background="#ff0000"/>
</LinearLayout>

refreshable_list.xml: (The XML layout of the RefreshableList custom view)

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/dataRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

All this code belongs to the rlist module. In order to test it out, I added a MainActivity to the app module where I embed a RefreshableList:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Bind(R.id.list)
    RefreshableList mRefreshableList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        mRefreshableList.setAdapter(new MyAdapter(
                this, Arrays.asList("Java", "Android", "Python", "Kivy")));
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.zouag.refreshablelist.MainActivity"
    android:background="#00ff00">

    <com.zouag.rlist.RefreshableList
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffff00"/>
</RelativeLayout>

After running the application, I can't see any of the RecyclerView's elements: (even though the RecyclerView is clearly visible, marked with yellow)

Run

What am I missing here ?


Solution

  • Not your recyclerview is visible, your relativelayout is. You don't attach the inflated layout to your viewgroup.

    The call :

    View view = inflater.inflate(R.layout.refreshable_list, null);
    

    just inflates the layout but dosen't attach it to a view. If u wanna stick with this you need to attach the view after inflating by:

    this.addView(view)
    

    Or just call:

    View view = inflater.inflate(R.layout.refreshable_list, this,true);
    

    which attaches the inflated layout to the root view.