如何在“onBindViewHolder”中获取recyclerview项目的高度

Posted

技术标签:

【中文标题】如何在“onBindViewHolder”中获取recyclerview项目的高度【英文标题】:How to get the height of recyclerview item in "onBindViewHolder" 【发布时间】:2016-12-10 09:28:23 【问题描述】:

RecyclerView 项目的高度不固定,我需要为每个项目设置背景图像,所以我想获取 recyclerview 项目的高度来调整图像大小,但是itemView.getHeight()onBindViewHolder 中总是返回 0。

我已经尝试搜索了很多问题或文章,但我仍然无法找到一个好的解决方案。

【问题讨论】:

【参考方案1】:

手动测量视图

view.measure(
             View.MeasureSpec.makeMeasureSpec(recyclerViewWidth, View.MeasureSpec.EXACTLY),
             View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

并使用view.getMeasuredHeight()获取高度

背景

只有在测量之后,视图才会返回 View.getHeight() 的有效值。当视图即将显示在屏幕上时,系统会自动进行测量。

android想要显示布局时,它会为视图树中的每个视图递归调用view.layout()函数。每个父母都会告诉其孩子他们可能有的限制(宽度/高度)并要求他们自己view.measure()。因此,视图将BASED 存储指定成员(MeasuredHeight/Width)中约束的测量值。请注意,此时view.getMeasuredHeight() 将保留该值,而view.getHeight() 仍然无效。 view.getHeight() 只会在视图在 UI 层次结构中具有实际高度时返回有效值。

回顾

因此,要知道视图元素的高度,在系统测量和布局之前,我们需要手动调用view.measure() 函数。

measure 函数需要 2 个参数,这些参数来自视图 LayoutParams + 父约束。

在上面的代码示例中,我们正在测量视图,强制其宽度完全等于父级(RecycleView)的宽度,并且高度不受限制。

【讨论】:

第一次返回0。滚动时返回值。有什么办法吗? 你怎么知道onBindViewHolder中的recyclerViewWidth【参考方案2】:

我建议您定义多个具有预期高度的布局文件,并根据数据集中的某些标准对它们进行膨胀。

ViewHolder onCreateViewHolder (ViewGroup parent, int viewType)
  if(some condition)
    //inflate layout 1
  else
    //inflate layout 2
 

或回答here:您可以在初始化视图支架时获取测量值

itemView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int width = itemView.getMeasuredWidth();
int height = itemView.getMeasuredHeight();

【讨论】:

ViewHolder 没有getMeasuredHeight()getMeasuredWidth() 方法。 他可能是指viewholder.itemView【参考方案3】:

这个怎么样:

view.post(() -> 
   int width = view.getMeasuredWidth();
   int height = view.getMeasuredHeight();

【讨论】:

【参考方案4】:

使用此代码获取回收站视图的项目高度:

view.getViewTreeObserver().addOnGlobalLayoutListener(new 
         ViewTreeObserver.OnGlobalLayoutListener() 
    @Override
    public void onGlobalLayout() 
        //don't forget remove this listener
        view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        //get item height here
        int itemHeight = v.getHeight();
    
);

【讨论】:

【参考方案5】:

MyViewHolder.kt

使用addOnGlobalLayoutListener()方法,在绘制TextView之前获取高度值。然后将其保存在成员变量中。

关键是修改监听器实现内外的UI,这样就不会出现渲染问题(重绘视图时)。

也就是说,您应该在侦听器中使用 getter,并且;侦听器内部和外部的设置器。

companion object 

    var maxHeight: Int = 0
   
    fun create(mContext: Context): MyViewHolder 
        val view = LayoutInflater.from(mContext).inflate(R.layout.item_answer, null)

        updateLayout(view)

        view.viewTreeObserver.addOnGlobalLayoutListener 

            if (view.myTextView.height > maxHeight)
                maxHeight = view.myTextView.height

            updateLayout(view)

        

        return MyViewHolder(mContext, view).apply 
            setIsRecyclable(false)
        
    

    fun updateLayout(view: View) 
        if (maxHeight != 0 && view.myTextView.height != maxHeight) 
            view.myTextView.height = maxHeight
    
    


Source

【讨论】:

以上是关于如何在“onBindViewHolder”中获取recyclerview项目的高度的主要内容,如果未能解决你的问题,请参考以下文章

如何在 onBindViewHolder 中添加视图?

如何在回收站视图的 onBindViewHolder() 方法中调用 getString()?

如何刷新片段中的onBindViewHolder方法

未调用 RecyclerVIew onCreateViewHolder 和 onBindViewHolder

在 RecyclerView 适配器 notifyDataSetChanged() 之后未调用 onBindViewHolder

如何将 AsyncTask 从 Adapter onBindViewHolder() 移动到 Activity onChildEventListener