我打算实现什么
项目 View 应该占据项目的整个高度
可能是项目高度小于 recyclerview 中最高项目的高度,在这种情况下,它应该像上面的屏幕截图一样粘在顶部。
我遇到的错误
如上面的屏幕截图所示, View 被截断了。
到目前为止我尝试了什么
最初我在 recyclerview 上使用 wrap_content,现在它已受支持。当当时屏幕上可见的 View 都不是最高时,它不起作用。这在 View 层次结构的布局方式上是有意义的。 如果高度依赖于数据,如何计算甚至还没有绑定(bind)到任何数据的东西的高度?
解决时间:S
我没有尝试自定义布局管理器,而是首先进行了我认为需要完成的工作 - 在开始时布置所有项目 View 以确定它们的高度。
屏幕上部有一个进度条和一个动画来吸引用户的注意力,而所有这一切都是在 recyclerview 可见性设置为不可见的情况下发生的。我使用了两个东西,一个还不够——我在适配器的 onViewAttached()
调用中附加了一个观察器,我还使用了一个滚动更改监听器。有一个 LinearSnapHelper 附加到回收器 View 以捕捉到滚动上的相邻(下一个或上一个,取决于滚动方向)位置。
在这个设置中,
- 我将使用
layoutManager.smoothScrollToPosition()
转到 recyclerview 中的每个位置
使用获取 subview 高度
View currentChildView = binding.nextRv.getChildAt(layoutManager.findFirstCompletelyVisibleItemPosition()); if (currentChildView != null) { currentChildHeight = currentChildView.getHeight(); }
在 RecyclerView.SCROLL_STATE_IDLE
上的滚动更改监听器中,或者通过将高度传递给上述适配器的 onViewAttachedToWindow() 中的 View 附加观察器
@Override
public void onViewAttachedToWindow(BindingViewHolder holder) {
if (mObserver != null) {
mObserver.onViewAttached(holder.binding.getRoot().getHeight());
}
}
- 存储一个
maxHeight
,它会更改为 maxHeight 和新 child 高度的最大值。
很明显,这很丑陋。另外它没有给我当前 View 的高度 - onAttached 意味着它只是附加,而不是测量和布局。它是回收 View ,而不是绑定(bind)到当前数据项的 View 。这会带来如上图所示的 View 截断等问题。
我还尝试在回收器 View 上使用 wrap_content 高度,并从回收器的父级无效,直到回收器和滚动的子级进入 SCROLL_STATE_IDLE。不起作用。
我不确定自定义布局管理器如何提供帮助。
有人能指导我正确的方向吗?
最佳答案
我无法接受@Pradeep Kumar Kushwaha 的回答,因为针对一种解决方案,我不希望列表中出现不同的字体大小。一致性是设计中的关键要素。他给出的第二个替代方案无法工作,因为使用 ellipsize 我需要提供某种“更多”按钮供用户阅读全部内容,而我的 TextView 已经采取了点击操作。将更多放在其他地方也不是好的设计。
当最高的、被截断的项目成为焦点时,通过调整 recyclerview 大小的简单折衷来更改设计,它变成了 notifyItemChanged() 的简单用例。即使对于我使用 View 附加观察器和滚动状态监听器所做的尝试,也可以使用 notifyItemChanged,但这种方法太老套了。我可以在代码和设计中接受这一点。这是所需的代码。
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
int position = ((LinearLayoutManager) binding.nextRv.getLayoutManager())
.findFirstVisibleItemPosition();
if (position != nextSnippetAdapter.getItemCount() - 1) {
binding.nextRv.getAdapter().notifyItemRangeChanged(position, 2);
} else {
binding.nextRv.getAdapter().notifyItemChanged(position);
}
}
}
对于我的特定设置,仅调用这两个元素即可。它可以进一步优化,以便在大多数情况下调用 position + 1
处的单个元素,并在角落(文字)情况下检查和调用适当的元素。
关于android - 具有可变项目高度的水平 RecyclerView 未正确包装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41585286/