android - 具有可变项目高度的水平 RecyclerView 未正确包装

标签 android android-recyclerview horizontallist

我打算实现什么

enter image description here

项目 View 应该占据项目的整个高度

enter image description here

可能是项目高度小于 recyclerview 中最高项目的高度,在这种情况下,它应该像上面的屏幕截图一样粘在顶部。

我遇到的错误

enter image description here

如上面的屏幕截图所示, View 被截断了。

到目前为止我尝试了什么

最初我在 recyclerview 上使用 wrap_content,现在它已受支持。当当时屏幕上可见的 View 都不是最高时,它不起作用。这在 View 层次结构的布局方式上是有意义的。 如果高度依赖于数据,如何计算甚至还没有绑定(bind)到任何数据的东西的高度?

解决时间:S

我没有尝试自定义布局管理器,而是首先进行了我认为需要完成的工作 - 在开始时布置所有项目 View 以确定它们的高度。

屏幕上部有一个进度条和一个动画来吸引用户的注意力,而所有这一切都是在 recyclerview 可见性设置为不可见的情况下发生的。我使用了两个东西,一个还不够——我在适配器的 onViewAttached() 调用中附加了一个观察器,我还使用了一个滚动更改监听器。有一个 LinearSnapHelper 附加到回收器 View 以捕捉到滚动上的相邻(下一个或上一个,取决于滚动方向)位置。

在这个设置中,

  1. 我将使用 layoutManager.smoothScrollToPosition()
  2. 转到 recyclerview 中的每个位置
  3. 使用获取 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());
    }
}
  1. 存储一个 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/

相关文章:

android - 滚动 RecyclerView 也会更改其他数据

java - 在我的适配器中,我无法更改 onClickListener 中的定义值

ios - 全屏 View 在 HStack 和水平 ScrollView 中不起作用

java - 是否有可用于使用三星电视网络远程控制功能的 API?

使用 SimpleCursorAdapter 更新 Android ListView

android - 如何防止 droid VNC 服务器上的键盘缓冲

android - 同时播放多个视频 ExoPlayer

android - RecyclerView 的 getItemViewType() 返回 String

Android 像 Duolingo App 一样水平滑动项目