Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/183.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何将回收器高度设置为recyclerView中的最高项目?_Android_Android Recyclerview_Android Wrap Content - Fatal编程技术网

Android 如何将回收器高度设置为recyclerView中的最高项目?

Android 如何将回收器高度设置为recyclerView中的最高项目?,android,android-recyclerview,android-wrap-content,Android,Android Recyclerview,Android Wrap Content,我需要确保水平回收视图高度与最大项目的高度相同 项目可以具有不同的高度(项目=始终相同的图像+标题+副标题,标题和副标题可以具有无限长)。 当我为我的recyclerView设置wrap_内容时,它会根据可见项目的高度调整大小,这会使recyclerView下面的内容跳跃,这是我想要避免的 我想要达到的目标: 灰色区域在视口中可见 所以基本上我想得到最大的物品的高度,然后把recyclerView高度放到那个数字上 我已经尝试过的是基于标题+副标题长度的项目近似值,但这是非常不准确的,因为例如,

我需要确保水平回收视图高度与最大项目的高度相同

项目可以具有不同的高度(项目=始终相同的图像+标题+副标题,标题和副标题可以具有无限长)。 当我为我的recyclerView设置wrap_内容时,它会根据可见项目的高度调整大小,这会使recyclerView下面的内容跳跃,这是我想要避免的

我想要达到的目标: 灰色区域在视口中可见

所以基本上我想得到最大的物品的高度,然后把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);        
    }
或者你也可以试试这个

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View itemView = inflater.inflate(R.layout.itemview, parent, false);

    ViewGroup.LayoutParams layoutParams = itemView.getLayoutParams();
    layoutParams.height = (int) (parent.getHeight() * 0.3);
    itemView.setLayoutParams(layoutParams);

    return new MyViewHolder(itemView);
   }

您还可以将itemView设置为固定高度。

我认为这是不可能的

让我们思考一下回收视图是如何工作的。为了节省内存,它重用相同的视图对象,并在用户滚动时将它们绑定到列表中的新数据。因此,例如,如果用户看到项目的0和1,那么系统只测量和布置了2个项目(可能还有一个或两个以上的项目以帮助滚动性能)

但假设您的高项目是列表中的第50个,当RecyclerView绑定前几个项目时,它根本不知道项目50是否存在,更不用说它会有多高了

然而,你可以做一些有点黑客的事情。例如,可以在绑定每个项目后测量其高度,跟踪最高的项目,然后手动将RecyclerView高度设置为该大小。使用该机制,您可以隐藏RecyclerView,然后手动滚动到列表的末尾,再滚动回列表的开头,然后显示RecyclerView

虽然不是最优雅的解决方案,但它应该可以工作。

您可以尝试以下方法:

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            final int newHeight = recyclerView.getMeasuredHeight();
            if (0 != newHeight && minHeight < newHeight) {
            // keep track the height and prevent recycler view optimizing by resizing
                minHeight = newHeight;
                recyclerView.setMinimumHeight(minHeight);
            }
        }
    });
mRecyclerView.addOnScrollListener(新的RecyclerView.OnScrollListener(){
@凌驾
CrollStateChanged上的公共void(@NonNull RecyclerView RecyclerView,int newState){
super.onScrollStateChanged(recyclerView、newState);
final int newHeight=recyclerView.getMeasuredHeight();
如果(0!=newHeight&&minHeight
现在回答问题已经太迟了,但这可能会对某些人有所帮助

我在同一个问题上苦苦挣扎,找不到一个可接受的解决方案

通过以下方式解决:

1) 首先,需要覆盖RecyclerView中的onMeasure以保存最大图元高度:

class CustomRecycleView(ctx:Context,attrs:AttributeSet):RecycleView(ctx,attrs){
私有变量biggestHeight:Int=0
覆盖测量的乐趣(宽度等级:Int,高度等级:Int){
for(在0中输入i,直到childCount){
val child=getChildAt(i)
子度量值(widthSpec,MeasureSpec.MakeMasureSpec(0,MeasureSpec.Unspected))
val h=儿童测量高度
如果(h>最大高度)最大高度=h
}
super.on测量(宽度规格,测量规格,makeMeasureSpec(最大高度,精确测量))
}
}
2) 在您的layput中,使用此CustomRecycleView替换RecycleView:

<CustomRecycleView
   android:layout_width="match_parent"
   android:layout_height="wrap_content" />

当列表中的新元素可见时调用onMeasure,如果该元素是最高的,则保存该值。例如:如果第一个元素的高度最低,但lates的高度最高,则在开始时,RecycleView将与第一个元素的高度匹配,但在滚动后,它将保持与最高元素的高度匹配。 如果您不需要在开始时使RecycleView高度与最高项目匹配,则可以在此处停止

3) 要在开始时执行此操作,您必须进行黑客攻击(基于@midslefko建议): 要初步了解最高元素的高度,需要在末尾和开头添加滚动机制。我是这样做的:

private fun initRecycleView(项目:ArrayList){
val adapter=适配器()
rv.visibility=View.INVISIBLE
rv.vadapter=适配器
rv.layoutManager=LinearLayoutManager(上下文,LinearLayoutManager.HORIZONTAL,false)
rv.setHasFixedSize(真)
rv.平滑滚动定位(钉柱尺寸)
Handler().postDelayed({
rv.位置(0)
}, 300)
Handler().postDelayed({
rv.visibility=View.visibility
}, 700)
}
将“回收”视图的可见性设置为“不可见”,并在700毫秒后将其设置为“可见”,以使此过程对用户不可见。此外,滚动启动的执行延迟为300毫秒,因为如果没有延迟,它可能无法正常工作。在我的例子中,这是一个包含3个元素的列表所需要的,这些延迟对我来说是最优的


还要记住删除onStop()中的所有处理程序回调。

我也遇到了这个问题。我的解决办法是:

  • 将RecyclerView包装在ConstraintLayout中
  • 将ConstraintLayout的布局高度设置为包裹内容
  • 将项目视图添加到ConstraintLayout中,并使用基于其标题的长度期望最高的项目的数据填充该项目,例如
  • 将项目视图的可见性设置为不可见
  • 将RecyclerView的布局高度设置为零,并使其顶部和底部约束与项目视图的约束匹配
  • 我和它解决了这个问题

    RecycleView.getRecycledViewPool().setMaxRecycledViews(类型为旋转木马,0)

    此解决方案可能有性能问题
     public static int getHeightOfLargestDescription(final Context context, final CharSequence text, TextView textView) {
        final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        final Point displaySize = new Point();
        wm.getDefaultDisplay().getSize(displaySize);
        final int deviceWidth = displaySize.x;
        textView.setTypeface(Typeface.DEFAULT);
        textView.setText(text, TextView.BufferType.SPANNABLE);
        int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        textView.measure(widthMeasureSpec, heightMeasureSpec);
        return textView.getMeasuredHeight();
    }
    
            MyViewHolder myViewHolder = new MyViewHolder(itemView);
        for (Model m : modelList) {
            currentItemHeight = getHeightOfLargestDescription(context, m.description, myViewHolder.description);
            if (currentItemHeight > highestHeight) {
                highestHeight = currentItemHeight;
            }
        }
    
     viewHolder.description.setHeight(highestHeight);