编辑:澄清一下,因为很多解决方案建议限制RecyclerView的高度,但这并不是本意。RecyclerView仍应填满屏幕。这是我用屏幕宽度(而不是高度)来说明的:
这个想法是使卡片的宽度为屏幕宽度的33%,同时在RecyclerView水平滚动时保持其宽度不变。
这个想法是使卡片的宽度为屏幕宽度的33%,同时在RecyclerView水平滚动时保持其宽度不变。
您可以重写一个LayoutManager
方法,以强制指定RecyclerView
的特定大小:
recyclerView.setLayoutManager(new LinearLayoutManager(this){
@Override
public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
// force height of viewHolder here, this will override layout_height from xml
lp.height = getHeight() / 3;
return true;
}
});
假设您的RecyclerView
适合屏幕。
如果您想要更复杂的解决方案(使用自定义布局管理器,可以控制每个项目和来自XML的百分比膨胀),请查看此答案。
据我所知,XML 中没有这样做的方法。但是,在 Java 中可以完成此操作(无需任何Runnable
等),只需在适配器的onCreateViewHolder()
方法中返回ViewHolder
之前设置您的ViewHolder
的itemView
的LayoutParams
:
@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);
}
parent.getHeight()
或者 parent.getWidth()
会返回0
,尤其是当你把 RecyclerView
放在 ConstraintLayout
里面时: <androidx.recyclerview.widget.RecyclerView android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/>
- user924layout_width="0dp"
,然后设置约束来定义宽度,将导致getWidth()
返回一个实际值,而不是0。 - Ben P.onCreateViewHolder
被调用时,它将为0,但稍后它将成为一个真正的值。 - user924您可以使用显示度量
在构造函数中定义显示度量,或使用任何其他静态方法初始化。
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
//setting the height programmatically
itemView.getLayoutParams().height = metrics.heightPixels/3;
itemView.requestLayout();
private int height = 0; // declared height globally in Adapter class to reuse it.
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
if (height == 0)
height = (int) (parent.getMeasuredHeight() * .3);
itemView.setMinimumHeight(height);
return new ItemViewHolder(itemView);
}
第二个技巧是使用SDP库。
在XML中使用sdp
的项目高度,例如_160sdp
。它可能无法精确地给出30%的结果,但可以根据屏幕进行调整。
measuredHeight
,那么你可以将第一个保存在全局变量中。然后重复使用它。 - Khemraj Sharmaparent.getContext()
的问题。 - Khemraj Sharma DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int devicewidth = (int) (displayMetrics.widthPixels * 0.8);
view.getLayoutParams().width = devicewidth;
return new YourAdapter.ViewHolder(view);
我通过在自定义的 RecyclerView 项布局中执行以下操作来实现这一点:
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val newMeasuredWidth =
(MeasureSpec.getSize(widthMeasureSpec) * WIDTH_ADJUSTMENT_RATIO).toInt()
super.onMeasure(
MeasureSpec.makeMeasureSpec(newMeasuredWidth, MeasureSpec.EXACTLY),
heightMeasureSpec
)
}
如果您不介意精确的百分比,您可以通过设置 android:paddingLeft
和 android:paddingRight
,并将 android:clipToPadding
设置为 false
来实现所需的视图。
这还使得第一个和最后一个项目居中对齐。
试一下这个方式。仅仅一次
inner class MyFeatureProductViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
val tvName = v.findViewById<TextView>(R.id.tvName)
val tvPrice = v.findViewById<TextView>(R.id.tvPrice)
val tvItemUploadTime = v.findViewById<TextView>(R.id.tvItemUploadTime)
val ivItem = v.findViewById<ImageView>(R.id.ivItem)
init {
v.layoutParams.width = itemView.measuredWidth - 20
v.requestLayout()
}
}
我刚试图解决你遇到的问题。 我尝试了几个方法,步骤如下:
那里发生了什么?
recyclerHolder
在那里确实有屏幕高度的30%,毫无疑问。
在recyclerHolder
内部,我们有一个RecyclerView
,它占据了所有父级的30%高度并占据了整个宽度。
ListItem Layout
占据父级的全高和全宽,其中父级是具有屏幕高度的30%的RecyclerView
。
我尝试了这个方法,它完美地运行了。你可以找到两个空视图来测试它们是否完美地适配在顶部和底部,结果是肯定的。无论在列表项中放置什么内容,它都会占据屏幕高度的30%。