我正在努力使用RecyclerView。我使用recyclerview来显示我的模型类的详细信息。
//My model class
MyModel {
String name;
Double latitude;
Double longitude;
Boolean isOnline;
...
}
由于某些值可能不存在,我使用RecyclerView和自定义视图类型(一个代表我的模型的每个值)。
//Inside my custom adapter
public void setModel(T model) {
//Reset values
itemCount = 0;
deviceOfflineViewPosition = -1;
mapViewPosition = -1;
//If device is offline, add device offline item
if (device.isOnline() == null || !device.isOnline()) {
deviceOfflineViewPosition = itemCount;
itemCount++;
}
//Add additional items if necessary
...
//Always add the map as the last item
mapViewPosition = itemCount;
itemCount++;
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if (position == deviceOfflineViewPosition) {
return ITEM_VIEW_TYPE_OFFLINE;
} else if (position == mapViewPosition) {
return ITEM_VIEW_TYPE_MAP;
} else if (...) {
//Check for other view types
}
}
使用RecyclerView,我可以在运行时轻松确定哪些值可用,并将相应的项添加到RecyclerView数据源。我简化了代码,但我的模型有更多的值,我有更多的视图类型。
RecyclerView中的最后一项始终是地图,并且始终存在。即使我的模型中根本没有任何价值,也至少会有一个项目,即地图。
问题:如何让RecyclerView中的最后一项填充屏幕上的剩余空间并且还有最小高度。尺寸应该是更大的价值:剩余空间或最小高度。例如:
在布置最后一项后,您可以在RecyclerView中找到剩余空间,并将剩余空间添加到最后一项的minHeight
中。
val isLastItem = getItemCount() - 1 == position
if (isLastItem) {
val lastItemView = holder.itemView
lastItemView.doOnLayout {
val recyclerViewHeight = recyclerView.height
val lastItemBottom = lastItemView.bottom
val heightDifference = recyclerViewHeight - lastItemBottom
if (heightDifference > 0) {
lastItemView.minimumHeight = lastItemView.height + heightDifference
}
}
}
在onBindHolder
中,使用getItemCount() - 1 == position
检查项目是否为最后一项。如果它是最后一项,则通过使用lastItem底部减去recyclelerView高度来找到高度差(getBottom()
为您提供相对于其父级的视图的最底部像素。在这种情况下,我们的父级是RecyclerView
)。
如果差值大于0,则将其添加到上一个视图的当前高度并将其设置为minHeight
。我们将其设置为minHeight
而不是直接设置为height
以支持最后一个视图的动态内容更改。
注意:此代码为Kotlin,doOnLayout函数来自Android KTx。你的RecyclerView
高度应该是match_parent
这个工作(我想这是显而易见的)。
我使用muthuraj解决方案来解决类似的问题,如果以前的项目填满页面的高度或更高的高度,我希望最后一项显示在最后一项,但如果前一项没有填满高度,我希望最后一项显示在页面底部。
当前一项+ specialItem占据所有位置。 -------------- 项目 项目 项目 specialItem --------------
当前一项+ specialItem超过高度时 -------------- 项目 项目 项目 项目 项目 项目 specialItem --------------
当前一项+ specialItem小于高度时 -------------- specialItem -------------- 要么 -------------- 项目 specialItem --------------
存档这个我使用这个代码
val lastItemView = holder.itemView
//TODO use a better option instead of waiting for 200ms
Handler().postDelayed({
val lastItemTop = lastItemView.top
val remainingSpace = recyclerViewHeight() - lastItemTop
val heightToSet = Math.max(remainingSpace, minHeight)
if (lastItemView.height != heightToSet) {
val layoutParams = lastItemView.layoutParams
layoutParams.height = heightToSet
lastItemView.layoutParams = layoutParams
}
}, 200)
我使用Handler()。postDelayed的原因是doOnLayout永远不会被我调用,我无法弄清楚为什么这样,而是以200ms的延迟运行代码,直到找到更好的工作方式。