RecyclerView 2 Columns with CardView

62,380

Solution 1

Extracted required info from the accepted answer in case URL becomes invalid in future and to save time.

GridLayoutManager is used to display the RecyclerView in Grid manner instead of list.

RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(mLayoutManager);

Kotlin version:

recyclerView.apply {
   layoutManager = GridLayoutManager(this, 2)
}

Solution 2

You can use this code simply

<android.support.v7.widget.RecyclerView
    app:layoutManager="android.support.v7.widget.GridLayoutManager"
    app:spanCount="2"/>

Solution 3

With androidX libraries simply do:

<androidx.recyclerview.widget.RecyclerView
    app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
    app:spanCount="2"/>
Share:
62,380

Related videos on Youtube

Harry Pulvirenti
Author by

Harry Pulvirenti

Updated on November 04, 2020

Comments

  • Harry Pulvirenti
    Harry Pulvirenti over 3 years

    I have a problem with my layout. I'm trying to do something like this:

    Image

    For now, i have a RecyclerView with a CardView inside it. in the CardView I have put an ImageView and a TextView but I don't know why but the CardView is more height than ImageView inside it.

    Here is The code and a Sample Image.

    Image

    And Here is the code: Activity

    public class AddRoomActivity extends AppCompatActivity implements View.OnClickListener {
    
    private View snackView;
    private FloatingActionButton fabDoneAddRoom;
    private EditText etRoomName;
    private String roomName = null;
    public final static String KEY_PI_IP = "MyPi_IP";
    private final static String KEY_ROOM = "myRoom";
    private final static String KEY_ROOM_TYPE = "myRoom_Type";
    
    private RecyclerView typeRecyclerView;
    private GridLayoutManager layoutManager;
    private AddRoomActivity.TypeAdapter adapter;
    
    
    private String myPi;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_room);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    
        fabDoneAddRoom = (FloatingActionButton) findViewById(R.id.doneAddRoom);
        fabDoneAddRoom.setOnClickListener(this);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    
        etRoomName = (EditText) findViewById(R.id.addRoomName);
        myPi = getIntent().getStringExtra(KEY_PI_IP);
    
        layoutManager = new GridLayoutManager(this, 2);
    
    
        typeRecyclerView = (RecyclerView) findViewById(R.id.recyclerTypeRoom);
        typeRecyclerView.setHasFixedSize(true);
    
        typeRecyclerView.setLayoutManager(layoutManager);
    
        // specify an adapter (see also next example)
        adapter = new TypeAdapter(getResources().getStringArray(R.array.roomTypeName));
        typeRecyclerView.setAdapter(adapter);
    
    
    }
    
    
    void showToastMessage(String message) {
        Snackbar.make(snackView, message, Snackbar.LENGTH_LONG).show();
    }
    
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.doneAddRoom) {
            snackView = v;
            String myString = etRoomName.getText().toString();
    
            if (myString.length() > 0) {
                roomName = myString.substring(0, 1).toUpperCase() + myString.substring(1);
                addRoomToPi();
            } else {
                showToastMessage(getString(R.string.noNameRoom));
    
            }
        }
    }
    
    private void addRoomToPi() {
        Integer ret = -1;
        try {
            ret = (Integer) new RaspberryTCPClient(myPi, getResources(), RaspberryTCPClient.TYPE_ADD_ROOM, roomName, XMLRoom.TYPE_KITCHEN_ROOM).execute().get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    
        if (ret == RaspberryTCPClient.OPERATION_DONE) {
    
            showToastMessage(getString(R.string.roomAdded));
    
            Intent data = new Intent();
            data.putExtra(KEY_ROOM, roomName);
            setResult(Activity.RESULT_OK, data);
    
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    finish();
                }
            }, 1500);
        } else {
            showToastMessage(getString(R.string.addRoomError));
        }
    
    }
    
    
    private class TypeAdapter extends RecyclerView.Adapter<AddRoomActivity.TypeAdapter.ViewHolder> {
    
        private String[] myData;
    
    
        public TypeAdapter(String[] roomList) {
            myData = roomList;
        }
    
    
        public void onItemClick(int position) {
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder {
            // each data item is just a string in this case
            public TextView tvType;
            public CardView cvRoomCard;
            public ImageView imgRoomType;
    
            public ViewHolder(View vCard) {
                super(vCard);
                cvRoomCard = (CardView) vCard;
                tvType = (TextView) vCard.findViewById(R.id.tvTypeName);
                imgRoomType = (ImageView) vCard.findViewById(R.id.img_roomType);
            }
        }
    
    
        @Override
        public AddRoomActivity.TypeAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.type_room_recycler_view, parent, false);
            // set the view's size, margins, paddings and layout parameters
            //...
            AddRoomActivity.TypeAdapter.ViewHolder vh = new AddRoomActivity.TypeAdapter.ViewHolder(v);
            return vh;
        }
    
        @Override
        public void onBindViewHolder(AddRoomActivity.TypeAdapter.ViewHolder holder, int position) {
            // - get element from your dataset at this position
            // - replace the contents of the view with that element
            holder.tvType.setText(myData[position]);
    
            switch (position) {
                case XMLRoom.TYPE_ROOM:
                    holder.imgRoomType.setImageResource(R.drawable.img_room_sqr);
                    break;
                case XMLRoom.TYPE_BED_ROOM:
                    holder.imgRoomType.setImageResource(R.drawable.img_bedroom_sqr);
                    break;
                case XMLRoom.TYPE_GARDEN_ROOM:
                    holder.imgRoomType.setImageResource(R.drawable.img_garden_sqr);
                    break;
                case XMLRoom.TYPE_KITCHEN_ROOM:
                    holder.imgRoomType.setImageResource(R.drawable.img_kitchen_sqr);
                    break;
                case XMLRoom.TYPE_LIVING_ROOM:
                    holder.imgRoomType.setImageResource(R.drawable.img_living_room_sqr);
                    break;
                case XMLRoom.TYPE_SWIMMING_POOL_ROOM:
                    holder.imgRoomType.setImageResource(R.drawable.img_swimming_pool_sqr);
                    break;
            }
    
            holder.cvRoomCard.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onItemClick(position);
                }
            });
    
    
        }
    
        @Override
        public int getItemCount() {
            return myData.length;
        }
    
    
    }
    

    The MainLayout

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/toolbar"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />
    
    </android.support.design.widget.AppBarLayout>
    
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="90dp"
        android:layout_marginTop="@dimen/toolbar"
        android:descendantFocusability="beforeDescendants"
        android:focusableInTouchMode="true">
    
    
        <TextView
            android:id="@+id/tvAddRoom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_margin="5dp"
            android:gravity="center"
            android:text="@string/textAddRoom"
            android:textColor="@color/primary_text"
            android:textSize="20dp"
            android:textStyle="bold" />
    
        <android.support.design.widget.TextInputLayout
            android:id="@+id/inputaddRoomName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/tvAddRoom"
            android:layout_gravity="center"
            android:layout_margin="5dp">
    
            <EditText
                android:id="@+id/addRoomName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/prompt_RoomName"
                android:inputType="textEmailAddress"
                android:maxLines="1"
                android:singleLine="true" />
    
        </android.support.design.widget.TextInputLayout>
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerTypeRoom"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/inputaddRoomName"
            android:scrollbars="vertical" />
    
    </RelativeLayout>
    
    
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/doneAddRoom"
        android:layout_width="@dimen/fab_Dimension"
        android:layout_height="@dimen/fab_Dimension"
        android:layout_gravity="bottom|center"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@drawable/ic_done" />
    
    </android.support.design.widget.CoordinatorLayout>
    

    and The View Layout:

    <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    
    card_view:cardCornerRadius="4dp">
    
    
    <ImageView
        android:id="@+id/img_roomType"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:src="@drawable/img_room" />
    
    <TextView
        android:id="@+id/tvTypeName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:gravity="center"
        android:textColor="@android:color/white"
        android:textSize="20sp" />
    
    
    </android.support.v7.widget.CardView>
    
  • Ayxan Haqverdili
    Ayxan Haqverdili almost 3 years
    This is much cleaner than setting it from the code later on.