Android 如何将回收器高度设置为recyclerView中的最高项目?
我需要确保水平回收视图高度与最大项目的高度相同 项目可以具有不同的高度(项目=始终相同的图像+标题+副标题,标题和副标题可以具有无限长)。 当我为我的recyclerView设置wrap_内容时,它会根据可见项目的高度调整大小,这会使recyclerView下面的内容跳跃,这是我想要避免的 我想要达到的目标: 灰色区域在视口中可见 所以基本上我想得到最大的物品的高度,然后把recyclerView高度放到那个数字上Android 如何将回收器高度设置为recyclerView中的最高项目?,android,android-recyclerview,android-wrap-content,Android,Android Recyclerview,Android Wrap Content,我需要确保水平回收视图高度与最大项目的高度相同 项目可以具有不同的高度(项目=始终相同的图像+标题+副标题,标题和副标题可以具有无限长)。 当我为我的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()中的所有处理程序回调。我也遇到了这个问题。我的解决办法是:
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);