【问题标题】:How to show exact number of items in RecyclerView?如何在 RecyclerView 中显示确切的项目数量?
【发布时间】:2016-05-11 06:24:20
【问题描述】:

我试图在 RecyclerView 中显示准确的(例如 3 个项目)。我们的 Web 应用程序显示如下:

如果我移动物品:

然后松开鼠标,它会自动出现:

在 Android 中,我使用 RecyclerView 显示图像:

如何在 RecyclerView 的可视区域中精确显示 3 个项目?如何避免显示“一半”项目?这可能吗?

回收站视图:

        <android.support.v7.widget.RecyclerView
            android:layout_width="wrap_content"
            android:layout_height="130dp"
            android:id="@+id/rvProducts" />

回收站视图中的一项:

<?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="match_parent">

    <ImageView
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:id="@+id/ivProduct"
        android:src="@drawable/noimage"/>

</LinearLayout>

代码:

    LinearLayoutManager layoutManager
            = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
    RecyclerView productImageList = (RecyclerView) view.findViewById(R.id.rvProducts);
    productImageList.setLayoutManager(layoutManager);
    GalleryRecyclerAdapter adapter = new GalleryRecyclerAdapter(images);
    productImageList.setAdapter(adapter);

【问题讨论】:

    标签: android android-layout android-recyclerview


    【解决方案1】:

    一种解决方案是以编程方式设置每个孩子的width

    view.getLayoutParams().width = getScreenWidth() / VIEWS_COUNT_TO_DISPLAY;
    

    屏幕尺寸是这样的:

    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics).widthPixels;
    

    【讨论】:

    • 身高需要怎么做?我需要在recyclerview可见位置展示5个物品。
    • getDefaultDisplay().getMetrics(metrics).getMetrics(metrics) 在新 API 中返回 void。使用Resources.getSystem().displayMetrics.widthPixelscontext.getResources().getDisplayMetrics(). widthPixels
    • 太棒了,它可以让 kotlin nee 更改语法 context.resources.displayMetrics.widthPixels
    【解决方案2】:

    我已经按照以下方法完成了上述任务,请参考以下代码

    在我的 RecycleView AdapteronCreateViewHolder() 方法中,我找出了屏幕的宽度,然后分为 3 部分.请检查一次。

    @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.MY_ITEM_TO_INFALTE, parent, false);
    
            itemView.getLayoutParams().width = (int) (getScreenWidth() / NUMBERS_OF_ITEM_TO_DISPLAY); /// THIS LINE WILL DIVIDE OUR VIEW INTO NUMBERS OF PARTS
    
            return new MyCreationItemAdapter.MyViewHolder(itemView);
        }
    

    从上面的代码getScreenWidth()我们上面使用的方法如下,请检查一下。

    public int getScreenWidth() {
    
            WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
            Display display = wm.getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
    
            return size.x;
        }
    

    【讨论】:

    • 身高需要怎么做?我需要在recyclerview可见位置展示5个物品。
    • @kgandroid 你有解决办法吗?或者我会为你发布答案
    • 那太棒了。我需要在垂直的recyclerview列表的可见区域中显示5个项目,而不是水平的。
    • 好的,你有没有把问题贴在这里,所以我可以给出建议
    • 不,我没有发布任何单独的问题。你想要吗?或者你可以编辑这个。
    【解决方案3】:

    我在下面提供的解决方案有助于在屏幕上的 recyclerView 中显示预定义数量的子项目('numOfCardViewItemsOnScreen'),还计算这些项目之间的边距以 均匀间隔,通过考虑项目和 recyclerView 的结束边距之间提供的边距(即,'ma​​rginAtRecyclerViewsEnds')

    请注意,我已经在 5.0" 到 7.0" 英寸的设备上对此进行了测试,并获得了一致的结果。

    private fun configureCardViewLayoutParams(cardView: CardView, numOfCardViewItemsOnScreen: Int, marginAtRecyclerViewsEnds: Float, marginLeftParam: Float, marginRightParam: Float, marginTopParam: Float, marginBottomParam: Float): ViewGroup.MarginLayoutParams {
        val numOfGapsInBetweenItems = numOfCardViewItemsOnScreen - 1
        var combinedGapWidth = ((marginLeftParam + marginRightParam) * numOfGapsInBetweenItems) + (marginAtRecyclerViewsEnds * 2)
        //Provided approx. adjustment of 2dp to prevent the extreme edges of the card from being cut-off
        combinedGapWidth += 2
        val combinedGapWidthDp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, combinedGapWidth, cardView.resources.displayMetrics).toInt()
        //Since margins/gaps are provided in-between the items, these have to be taken to account & subtracted from the width in-order to obtain even spacing
        cardView.layoutParams.width = (getScreenWidth(cardView.context as MainActivity) - combinedGapWidthDp) / numOfCardViewItemsOnScreen
    
        //Margins in-between the items
        val marginLeftOfItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginLeftParam, cardView.resources.displayMetrics).toInt()
        val marginRightOfItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginRightParam, cardView.resources.displayMetrics).toInt()
        val marginTopOfItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginTopParam, cardView.resources.displayMetrics).toInt()
        val marginBottomOfItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginBottomParam, cardView.resources.displayMetrics).toInt()
    
        //Providing the above margins to the CardView
        val cardViewMarginParams: ViewGroup.MarginLayoutParams = cardView.layoutParams as ViewGroup.MarginLayoutParams
        cardViewMarginParams.setMargins(marginLeftOfItem, marginTopOfItem, marginRightOfItem, marginBottomOfItem)
        return cardViewMarginParams
    }
    

    顾名思义,下面的方法有助于计算屏幕宽度

    private fun getScreenWidth(activity: MainActivity): Int {
        var width: Int = 0
        val size = Point()
        val windowManager = activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        width = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val bounds = windowManager.currentWindowMetrics.bounds
            bounds.width()
        } else {
            val display: Display? = windowManager.defaultDisplay
            display?.getSize(size)
            size.x
        }
        return width
    }
    

    最后在 onCreateViewHolder 中,利用上面描述的 configureCardViewLayoutParams 方法并传入所需的参数

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRecyclerViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.row_item_layout, parent, false)
        view.layoutParams = configureCardViewLayoutParams(view as CardView, 4, 12f, 4f, 4f, 8f, 8f)
        return MyRecyclerViewHolder(view)
    }
    

    为了快速理解,我还提供了子item的xml布局(row_item_layout.xml)所以从下面的xml可以看出,我们的子item布局的根视图是一个CardView。

    <?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:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:elevation="5dp"
        android:foregroundGravity="center">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <ImageView
                android:id="@+id/imageView1"
                android:layout_width="30dp"
                android:layout_height="28dp"
                android:layout_marginTop="22dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:src="@tools:sample/avatars" />
    
            <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="7dp"
                android:layout_marginTop="18dp"
                android:layout_marginEnd="7dp"
                android:layout_marginBottom="16dp"
                android:ellipsize="end"
                android:gravity="center"
                android:maxLines="2"
                android:text="@{accountOptionsModel.title}"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/imageView1"
                tools:text="@tools:sample/full_names" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    
    
    </androidx.cardview.widget.CardView>
    

    getCount()内部没有特殊逻辑,只返回整个列表大小

    override fun getItemCount(): Int = myList.size
    

    以下截图分别来自5.0"、6.3"、7.02"的设备

    【讨论】:

      【解决方案4】:

      在实现这一点的一般方式中,回收者视图没有直接的属性。

      实现这一点的方法是将父宽度发送到适配器..

      以麂皮绒的方式..

          Parent width = parent container width;
      
          InitialiseRecyclerAdapter(parent width) {
               on create view holder {
                       Set the width of ur item layout with a width that divides ur parent width in equal parts;
                }
      }
      

      【讨论】:

        【解决方案5】:

        这个解决方案对我有用:

         private lateinit var productImageList: RecyclerView
        
         override fun onAttachedToRecyclerView(recyclerView: RecyclerView) 
          {
               super.onAttachedToRecyclerView(recyclerView)
        
                productImageList = recyclerView
          }
        
         override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
                val viewHolder = LayoutInflater.from(parent.context).inflate(R.layout.ITEM_TO_INFALTE, parent, false)
        
                viewHolder.layoutParams.width = productImageList.measuredWidth / NUMBERS_OF_ITEM_TO_DISPLAY
        
                return ProductViewHolder(viewHolder)
            }
        

        代码在kotlin,希望对你有帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-17
          • 1970-01-01
          • 1970-01-01
          • 2023-02-23
          • 1970-01-01
          • 2015-01-27
          相关资源
          最近更新 更多