简体   繁体   中英

How can I make the Android RecyclerView responsive to fit the screen initially?

Sometimes RecyclerView shows empty spaces at bottom if the screen is large or it has fewer items to cover the screen. Also sometimes it shows some items partially if it has more items. What I want is:

RecyclerView will cover the full available space with the given number of rows. It will always fill the screen, no matter what is the size of the screen.

How can I do that?

将 match_parent 用于宽度和高度。

I'm posting my solution now for any future questioner. Here, by the word RESPONSIVE , I want the Items to take the available screen-space equally. For example, if we want 4 rows initially, the 4 rows will cover up the screen fully; that means, no item will be visible partially when the RecyclerView appears on the screen for the first time. And this will only work if the RecyclerView has fixed height irrespective of its Children, means, don't give WRAP_CONTENT to RecyclerView layout_height, give anything else like MATCH_PARENT or Constrained height.

Step1: You need to pass a parameter rows to the Adapter. You also need to pass the RecyclerView to the Adapter.

Step2: We need to keep a FLAG which will decide when to reveal the Child Items on the Screen. This FLAG will be FALSE initially, this will be TRUE when we finish calculating the available HEIGHT of RecyclerView on the screen. When we get the height of RecyclerView, we divide it by rows and get the height of each row. So we need to put a OnGlobalLayoutListener on the RecyclerView.

Here is a sample code.

RecyclerView layout will be like:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:id="@+id/recycler_view"
        tools:listitem="@layout/item"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Item layout will be like:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.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:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardPreventCornerOverlap="true"
    app:cardUseCompatPadding="true"
    card_view:cardCornerRadius="5dp"
    card_view:cardElevation="5dp">

    <TextView
        android:padding="15dp"
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:enabled="true"
        android:focusable="true"
        android:longClickable="true"
        android:textIsSelectable="true" />

</androidx.cardview.widget.CardView>

Adapter will be like:

public class ResponsiveItemListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements View.OnClickListener
{
    public static final int NUMBER_OF_ROWS_AUTO = -1;

    Context context;
    LayoutInflater layoutInflater;
    RecyclerViewItemClickListeners listener;
    List<Item> items;
    RecyclerView recyclerView;
    int numberOfRows;
    int rowHeightInPx = 0;
    boolean itemHeightCalculationCompleted = false;

    public ResponsiveItemListAdapter(Context context, List<Item> items, RecyclerViewItemClickListeners listener, RecyclerView rv, int rows)
    {
        super();
        this.context = context;
        this.items = items;
        this.listener = listener;
        this.layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.recyclerView = rv;
        this.numberOfRows = rows;

        if (this.numberOfRows > 0)
        {
            this.recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
            {
                @Override
                public void onGlobalLayout()
                {
                    if (recyclerView.getMeasuredHeight() > 0)
                    {
                        recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        setRowHeightInPx(recyclerView.getMeasuredHeight() / numberOfRows);
                        itemHeightCalculationCompleted = true;
                        notifyDataSetChanged();
                    }
                }
            });
        } else
        {
            itemHeightCalculationCompleted = true;
        }

    }

    public int getRowHeightInPx()
    {
        return rowHeightInPx;
    }

    public void setRowHeightInPx(int rowHeightInPx)
    {
        this.rowHeightInPx = rowHeightInPx;
    }

    @Override
    public int getItemCount()
    {
        if (this.items != null && this.itemHeightCalculationCompleted)
            return this.items.size();
        else
            return 0;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        RecyclerView.ViewHolder vh;
        View view = this.layoutInflater.inflate(R.layout.item, parent, false);
        if (getRowHeightInPx() > 0)
        {
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
            layoutParams.height = getRowHeightInPx();
            layoutParams.width = MATCH_PARENT;
            view.setLayoutParams(layoutParams);
        }
        vh = new GeneralViewHolder(view);
        return vh;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        Item page = items.get(position);

        CardView view = ((CardView) ((GeneralViewHolder) holder).getView());
        ((GeneralViewHolder) holder).getTitle().setText(page.getTitle());
        ((GeneralViewHolder) holder).getView().setOnClickListener(this);
        ((GeneralViewHolder) holder).getView().setTag(position);
    }


    @Override
    public void onViewRecycled(RecyclerView.ViewHolder holder)
    {
        super.onViewRecycled(holder);
    }


    @Override
    public void onClick(View v)
    {
        int position = (int) v.getTag();
        this.listener.onRecyclerViewItemClick(this.items, position);
    }

    public class GeneralViewHolder extends RecyclerView.ViewHolder
    {

        View view;
        TextView title;

        public GeneralViewHolder(View itemView)
        {
            super(itemView);
            view = itemView;
            title = itemView.findViewById(R.id.title);
        }


        public View getView()
        {
            return view;
        }

        public TextView getTitle()
        {
            return title;
        }

    }

    public interface RecyclerViewItemClickListeners
    {
        void onRecyclerViewItemClick(List<Item> items, int position);
    }
}

Set the adapter like this:

public class MainActivity extends AppCompatActivity implements ResponsiveItemListAdapter.RecyclerViewItemClickListeners
{

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

        List<Item> items = new ArrayList<>();
        items.add(new Item("One"));
        items.add(new Item("Two"));
        items.add(new Item("Three"));
        items.add(new Item("Four"));
        items.add(new Item("Five"));
        items.add(new Item("Six"));
        items.add(new Item("Seven"));

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(new ResponsiveItemListAdapter(this, items, this, recyclerView, 3));
    }

    @Override
    public void onRecyclerViewItemClick(List<Item> items, int position)
    {
        Toast.makeText(this, items.get(position).getTitle(), Toast.LENGTH_LONG).show();

    }
}

And here is the output:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM