水平RecyclerView与可变项目高度没有正确包装

时间:2017-01-11 07:44:38

标签: android android-recyclerview horizontallist

我打算实现的目标

enter image description here

项目视图应占据项目的整个高度

enter image description here

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

我遇到的错误

enter image description here

如上面的屏幕截图所示,视图会被截断。

到目前为止我尝试了什么

最初我在recyclerview上使用了wrap_content,现在它已得到支持。当当时在屏幕上看不到的任何视图都是最高的时候,它不起作用。这对视图层次结构的布局有意义。 如果高度取决于该数据,如何计算尚未绑定到任何数据的东西的高度?

解决方法时间:S

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

在屏幕的上半部分有一个进度条和一个动画,以吸引用户的注意力,而所有这些都发生在recyclelerview可见性被设置为不可见的情况下。我使用了两件事,一件是不够的 - 我在适配器的onViewAttached()调用中附加了一个观察者,我也使用了滚动更改监听器。有一个LinearSnapHelper附加到回收器视图,以便在滚动时捕捉到相邻(下一个或上一个,取决于滚动方向)的位置。

在此设置中,

  1. 我将使用layoutManager.smoothScrollToPosition()
  2. 访问recyclerview中的每个位置
  3. 使用

    获取子视图高度
            View currentChildView = binding.nextRv.getChildAt(layoutManager.findFirstCompletelyVisibleItemPosition());
            if (currentChildView != null) {
                currentChildHeight = currentChildView.getHeight();
            }
    
  4. RecyclerView.SCROLL_STATE_IDLE上的滚动更改侦听器中,或者通过将高度传递给适配器的onViewAttachedToWindow()上面提到的附加观察者视图

    @Override
    public void onViewAttachedToWindow(BindingViewHolder holder) {
        if (mObserver != null) {
            mObserver.onViewAttached(holder.binding.getRoot().getHeight());
        }
    }
    
    1. 存储更改为maxHeight和新子高度最大值的maxHeight
    2. 很明显,这很难看。另外它并没有给我当前视图的高度 - onAttached意味着它只是附加,而不是测量和布局。它是循环视图,而不是绑定到当前数据项的视图。这会出现如上所示的截断视图等问题。

      我还在回收器视图上尝试了wrap_content高度,并从回收器的父进程中失效,直到回收器和滚动子进入SCROLL_STATE_IDLE。不起作用。

      我不确定自定义布局管理器如何在这里提供帮助。

      有人可以指导我朝正确的方向发展吗?

3 个答案:

答案 0 :(得分:4)

我无法接受@Pradeep Kumar Kushwaha的回答,因为针对一个解决方案,我不希望列表中有不同的字体大小。一致性是设计中的关键因素。他给出的第二个替代方案无法工作,因为使用ellipsize我需要提供某种“更多”按钮,以便用户阅读整个内容,我的文本视图已经采取了点击操作。将更多放在其他地方也不是好设计。

当最高的截断项目成为焦点时,通过简单地重新调整recyclelerview的大小来改变设计,它变成了notifyItemChanged()的简单用例。即使我使用视图附加的观察者和滚动状态监听器进行的尝试,也可以使用notifyItemChanged,但这种方法太过于hacky。我可以在代码和设计中使用它。这是需要的代码。

@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调用单个元素,并在角落(文字)情况下检查并调用适当的元素。

答案 1 :(得分:1)

在适配器内部,我可以找到两张卡在顶部,另一张在底部

我如何定义我的布局是这样的:

Cardview1

    LinearLayout1 --> orientation vertical

    cardview2 (Top card where text is written)

    Linearlayout2 (where I can see icons such as like etc)-->orientation horizontal

现在通过设置它来包装内容来修复Linearlayout2的高度。

cardview2的高度应该是0dp并且加权= 1

现在在cardview2里面,在高度和宽度上添加一个TextView1到matchparent。

更好的内部textview1添加ellipsize结束并添加最大行

如果你想显示所有行试图找到autoresizetextview库,可以在这里建立 - > AutoResizeTextView

希望它有所帮助。

答案 2 :(得分:0)

我认为recyclerview可以设置为高度wrap_content。项目的高度可以设为match_parent

<androidx.recyclerview.widget.RecyclerView
    android:layout_width="match_parent"
    android:layput_height="wrap_content"/>

项目为:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

   // your coode

</androidx.constraintlayout.widget.ConstraintLayout>

除了这个问题,我没有其他要求。甚至我的问题也解决了。

记住我正在使用:

  

androidx.recyclerview:recyclerview:1.0.0-beta01

项目的依赖性