【问题标题】:How to set the height of an item row in GridLayoutManager如何在 GridLayoutManager 中设置项目行的高度
【发布时间】:2016-05-15 06:39:54
【问题描述】:

我的回收站项目在 onCreateViewHolder 中膨胀

<?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:gravity="center"
    android:orientation="vertical"
    android:padding="16dp">

    <ImageView
        android:id="@+id/gridListImageView"
        android:layout_width="96dp"
        android:layout_height="96dp"
        android:src="@drawable/a" />

    <TextView
        android:id="@+id/gridListView_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>

I want to display something like this 哪一排的高度是回收站视图的一半? 并为其余空间添加填充? 我可以通过 GridLayoutManager 做到这一点吗?

这是我的 GridLayoutManager

        GridLayoutManager glm = new GridLayoutManager(getActivity(), 2);
        recyclerView.setLayoutManager(glm);

【问题讨论】:

  • 如果您为RecyclerView 设置了一个特定的高度,您可以将其一半设置为LinearLayout 的高度。如果不是,例如,如果您希望一项为屏幕高度的一半,则必须以编程方式进行,获取屏幕高度,进行一些计算并设置 LayoutParams。
  • 你必须计算屏幕高度 - 减去导航栏高度,然后除以 2 以获得行高
  • 为什么不尝试使用 LinearLayout,使用 weightSum 会很容易
  • @AmitVaghela 我必须添加更多项目,所以我必须使用回收站视图!
  • @Amy,我得到 view.getLayoutParams().height 为 -1 和 view.getMeasuredHeight() 为 0。怎么办?

标签: android android-recyclerview gridlayoutmanager


【解决方案1】:

在适配器中为视图扩展布局时,您可以通过编程方式设置它们的高度。为了评估要使用的正确高度,您可以依赖父 ViewGroup(即 RecyclerView 本身)。这是一个示例:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = mLayoutInflater.inflate(R.layout.view_item, parent, false);
    // work here if you need to control height of your items
    // keep in mind that parent is RecyclerView in this case
    int height = parent.getMeasuredHeight() / 4;
    itemView.setMinimumHeight(height);
    return new ItemViewHolder(itemView);        
}

希望这会有所帮助。

【讨论】:

  • 您好@thetonrifles,我已经尝试了您的示例代码,但在(this case)[stackoverflow.com/questions/41338627/… 中似乎没有帮助我,我不知道为什么。请帮我看看。谢谢,
  • 似乎从版本 recyclerview-v7:25.1.1 现在不支持或行为不端。通过调用parent.getMeasuredHeight(),返回值始终为零。
  • 我刚刚进行了测试以确保这一点,并在您的项目使用版本 23.1.1 时切换回来,现在它可以工作了。
  • @drindt 感谢您提出这个问题。我会看看这个并提供答案的更新!
  • 您是否找到了使用新的 recyclerview api 处理此问题的方法? parent.getMeasuredHeight() 仍然是 0
【解决方案2】:

从支持库 25.1.0 开始,以上答案不起作用。我建议进行以下修改:

    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
        GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) v.getLayoutParams();
        lp.height = parent.getMeasuredHeight() / 4;
        v.setLayoutParams(lp);
        return new ViewHolder(v);
    }

【讨论】:

  • 为什么要除以4?
  • @GopalSinghSirvi 如果这个人想要 4 行,除以 6,如果需要 6 行。
  • 如果每行需要不同的高度怎么办?我发布了一个问题,但没有得到回答link
【解决方案3】:

您不需要设置项目的高度。这里的问题是图像试图填满所有空间。只需添加 android:adjustViewBounds="true" 到您的 ImageView 中,它不会添加空格

【讨论】:

  • 谢谢,如果有人需要在 RecyclerView 中使用 FrameLayoutImageView 产生前景涟漪效果,这就是要走的路。
【解决方案4】:
v.getLayoutParams().width = parent.getMeasuredWidth() / 2;

v.getLayoutParams().height = parent.getMeasuredWidth() / 2;

【讨论】:

  • 请在您的答案中添加更多信息,例如为什么它是正确的或与其他答案有什么不同
  • 以上都不适合我,但是这个可以。告诉你还需要什么信息?你想让我在这里发布完整的功能吗?
  • 喜欢您的解决方案与其他解决方案的不同之处,或者为什么这是正确的,或者您做了什么以及为什么会出现这样的问题
  • @PranavGoswami 我刚刚格式化了你的答案没有编辑请再次检查
【解决方案5】:

kotlin 版本

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val binding = ItemBinding.inflate(
        LayoutInflater.from(parent.context),
        parent,
        false
    )
    binding.root.post {
        binding.root.layoutParams.height = parent.width/3
        binding.root.requestLayout()
    }
    return ViewHolder(binding)
}

这里 3 是您的GridLayoutManager 的跨度计数 .如果您不使用数据绑定,则可以将 binding.root 替换为 itemView

【讨论】:

    【解决方案6】:

    有时,在适配器中获取膨胀视图的大小返回 0 或负数。另一种方法是从适配器外部获取所需的大小,对其进行操作并将其设置为视图。就我而言,另一个问题是尺寸设置无效。所以我使用布局参数设置大小

    这是在活动中设置我的适配器:

    Display display = MainActivity.this.getWindowManager().getDefaultDisplay();
                        Point size = new Point();
                        display.getSize(size);
                        int  y = size.y;
                        y=(int)y/2;
     GridLayoutManager linearLayoutManager = new GridLayoutManager(MainActivity.this,2);
                        recyclerView.setLayoutManager(linearLayoutManager);
                        NewOrderAdapter newOrderAdapter=new NewOrderAdapter(MainActivity.this,arrayListname,arrayListimage,y);
                        recyclerView.setAdapter(newOrderAdapter);
    

    我这样设置视图大小:

    @Override
        public myviewholder onCreateViewHolder(ViewGroup viewGroup, int i) {
            View view = inflator.inflate(R.layout.new_order_row, viewGroup, false);
            GridLayoutManager.LayoutParams params = (GridLayoutManager.LayoutParams) view.getLayoutParams();
            params.height = ysize;
            view.setLayoutParams(params);
            myviewholder holder = new myviewholder(view);
            return holder;
        }
    

    并且不要忘记在布局中为布局设置高度以进行初始化

    【讨论】:

      【解决方案7】:

      在最近的 API 级别上,当前 25 与 onCreateViewHolder 中的回收器的高度 总是空的。这个sn-p是在recycler view的onMeasure之后设置hight 被调用并为膨胀的列表视图设置正确的高度。

      @Override
      public DataBindingViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
          // You may inflate your view here.
          parent.post(new Runnable() {
      
              @Override
              public void run() {
                  int height = parent.getMeasuredHeight() / rows;
                  View view = holder.getBinding().getRoot();
                  view.getLayoutParams().height = height;
              }
          });
          return holder;
      }
      

      【讨论】:

      • 不错的解决方案,但有两个问题:1)如何确定在可运行对象运行时调用了 onMeasure? 2)什么是DataBindingViewHolder?
      【解决方案8】:

      这是我根据实际所需的纵横比调整回收视图元素高度的代码。

      @Override
      public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.adapter_offers, parent, false);
      
          int width =  parent.getMeasuredWidth();
          float height = (float) width / Config.ASPECT_RATIO;//(Width/Height)
          RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) itemView.getLayoutParams();
          params.height = Math.round(height);
          itemView.setLayoutParams(params);
          return new MyViewHolder(itemView);
      }
      

      【讨论】:

        【解决方案9】:

        我有一个类似的要求,它需要网格中每一行的动态高度,并且还能够从 RecyclerView 添加和删除项目。在onCreateViewHolder 中设置高度布局参数的问题是这里很少有答案表明,当从 RecyclerView 添加/删除项目时,视图会被回收,onCreateViewHolder 不会再次调用,而是视图池内被重复使用(如果可用)并且布局管理器将执行一次计算以计算项目的高度/宽度,我们将丢失在 onCreateViewHolder 中设置的原始预期高度/宽度。

        下面的这种方法可能会对面临类似问题的人有所帮助。

        这里的关键步骤是扩展GridLayoutManager并覆盖以下内容-

        1. generateDefaultLayoutParams
        2. generateLayoutParams
        3. checkLayoutParams

        布局管理器看起来像这样 -

        SpanGridLayoutManager : GridLayoutManager {
        
        constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) :
                super(context, attrs, defStyleAttr, defStyleRes)
        
        constructor(context: Context, spanCount: Int) : super(context, spanCount)
        constructor(context: Context, spanCount: Int, orientation: Int, reverseLayout: Boolean) :
                super(context, spanCount, orientation, reverseLayout)
        
        override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
            return spanLayoutSize(super.generateDefaultLayoutParams())
        }
        
        override fun generateLayoutParams(c: Context, attrs: AttributeSet): RecyclerView.LayoutParams {
            return spanLayoutSize(super.generateLayoutParams(c, attrs))
        }
        
        override fun generateLayoutParams(lp: ViewGroup.LayoutParams): RecyclerView.LayoutParams {
            return spanLayoutSize(super.generateLayoutParams(lp))
        }
        
        override fun checkLayoutParams(lp: RecyclerView.LayoutParams): Boolean {
            val layoutParams = generateDefaultLayoutParams()
            return super.checkLayoutParams(lp) &&
                    layoutParams.width == lp.width &&
                    layoutParams.height == lp.height
        }
        
        private fun spanLayoutSize(layoutParams: RecyclerView.LayoutParams): RecyclerView.LayoutParams {
            layoutParams.height = if (some_condition) x else y
            return layoutParams
        }
        

        这里的xy 可以是您需要提供的像素高度。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多