【问题标题】:Android - scrolling large number of items without Scrollview/Listview/GridviewAndroid - 在没有 Scrollview/Listview/Gridview 的情况下滚动大量项目
【发布时间】:2015-10-18 23:16:23
【问题描述】:

我正在尝试实现一个特殊的自定义视图,它有很多子视图,我需要实现垂直滚动。

基于 ScrollView 的方法太慢,因为要绘制的孩子太多。我无法启用硬件层,因为滚动内容的长度太长,无法适应 HWUI 的纹理大小。软件层也因内存不足而无法创建如此大的层。

我不能将 Listview 和 Gridview 用于与项目相关的事务。 所以,我想我要自己创建类似listview 的功能。

我知道为此,我必须重用视图。 这是我对如何进行感到困惑的地方。 随着内容滚动,我可以从顶部查看视图并将其移动到底部。 我认为有 3 种方法可以做到这一点。
1]setTranslateY
2]offsetTopAndBottom
3]更改layoutparams上下边距并调用requestLayout

但是,我不确定有什么不同,尤其是 [1] 和 [2]。 谁能告诉我 [1] 和 [2] 有何不同,并指导我在这里实现 listview 的正确方法,如滚动,用于大量项目。

谢谢, 安德罗比恩。

【问题讨论】:

  • "I know that for this, I have to re-use views" 所以使用RecyclerView。 docs:“类概述一种灵活的视图,用于为大型数据集提供有限的窗口。”
  • 我认为 Recyclerview 也不能使用,因为子项不完全是垂直列表。我将子视图排列为交错网格。 :(
  • 比较 [1] 和 [3] 方法请看这个:stackoverflow.com/q/33085311/5247331
  • @pskink 这可能很有希望,我会在这里查看更新。

标签: android android-view


【解决方案1】:

RecyclerView.LayoutManager 似乎是一个可能的解决方案。但是此时要更改我的设计以与RecyclerView.LayoutManager 方法保持一致是非常困难的。

所以,我制定了一个适合我的方法。滚动非常流畅,我不必更改很多代码。 把它贴在这里供我自己和其他人参考。

基本上我会创建所有子视图并将它们添加到我的自定义视图组中。但随后我重写了dispatchDraw 方法以将绘图限制为仅可见的那些。

这里没有使用回收方法。它只是一个巨大的 Viewgroup 包裹在 Scrollview 中。

@Override
protected void dispatchDraw(Canvas canvas) {
    int clipSaveCount = canvas.save();
    canvas.clipRect(getScrollX() + getPaddingLeft(), getScrollY() + getPaddingTop(),
            getScrollX() + getRight() - getLeft() - getPaddingRight(),
            getScrollY() + getBottom() - getTop() - getPaddingBottom());

    int rowHeightNoGap = (getHeight() - getPaddingTop() - getPaddingBottom())/mDataScreen.getRowCount();
    int startIndex = Math.max(0, (mScrollPosY - getPaddingTop())/rowHeightNoGap * mDataScreen.getColumnCount()-1);
    int endIndex = Math.min(getChildCount()-1, startIndex + (mDataScreen.getVisibleRowCount()+1) * mDataScreen.getColumnCount());

    final long drawingTime = getDrawingTime();
    for (int i = startIndex; i <= endIndex; i++) {
        drawChild(canvas, getChildAt(i), drawingTime);
    }

    canvas.restoreToCount(clipSaveCount);
}

int mScrollPosY;
public void setScrollPosition(int scrollPosY){
    mScrollPosY = scrollPosY;
    invalidate();
}

【讨论】:

  • 你在这里修改哪个类?
  • @ataulm 这是 ViewGroup 的子类,包裹在 Scrollview 中。
  • 所以这不会做任何视图回收?如果您可以更新您的答案以明确这一点,那就太好了,因为您提到您希望在您的问题中查看回收。
  • @ataulm 好的,我将在答案中添加其他信息。我认为问题的标题仍然有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
  • 2017-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多