Android-在没有Scrollview/Listview/Gridview的情况下滚动大量项目

Android-在没有Scrollview/Listview/Gridview的情况下滚动大量项目,android,android-view,Android,Android View,我正在尝试实现一个特殊的自定义视图,它有很多子视图,我需要实现垂直滚动 基于ScrollView的方法速度太慢,因为要绘制的子对象太多。我无法启用硬件层,因为滚动内容的长度太长,不适合HWUI的纹理大小。软件层也因内存不足而无法创建如此大的层 我不能将Listview和Gridview用于项目相关事宜。 因此,我想我将自己创建类似于listview的功能 我知道为此,我必须重新使用视图。 这就是我对如何进行感到困惑的地方。 当内容滚动时,我可以从顶部查看并将其移动到底部。 我认为有三种方法可以做

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

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

我不能将Listview和Gridview用于项目相关事宜。 因此,我想我将自己创建类似于
listview
的功能

我知道为此,我必须重新使用视图。 这就是我对如何进行感到困惑的地方。 当内容滚动时,我可以从顶部查看并将其移动到底部。 我认为有三种方法可以做到这一点。
1]
setTranslateY

2]
offsetTopAndBottom

3] 更改
layoutparams
上下页边距并调用
requestLayout

但是,我不知道有什么不同,特别是[1]和[2]。 有人能告诉我[1]和[2]有什么不同吗?还有人能告诉我,对于大量的项目,在这里实现
listview
的正确方法是什么吗

谢谢, 雄豆。

似乎是一个可能的解决方案。但是现在很难改变我的设计,使之与
RecyclerView.LayoutManager
方法保持一致

所以,我想出了一个适合我的方法。滚动非常平滑,我不需要更改很多代码。 把它贴在这里供我和其他人参考

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

本项目不采用回收方法。它只是一个巨大的
视图组
,包装在一个滚动视图中

@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();
}
@覆盖
受保护的void dispatchDraw(画布){
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());
最终长绘图时间=getDrawingTime();
for(int i=startIndex;i似乎是一个可能的解决方案。但目前很难更改我的设计以与
RecyclerView.LayoutManager
方法保持一致

所以,我想出了一个适合我的方法。滚动非常流畅,我不需要修改很多代码。 把它贴在这里供我和其他人参考

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

这里没有使用回收方法。它只是一个巨大的
Viewgroup
包装在滚动视图中

@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();
}
@覆盖
受保护的void dispatchDraw(画布){
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());
最终长绘图时间=getDrawingTime();

对于(int i=startIndex;i
“我知道为此,我必须重新使用视图”
,因此请使用
RecyclerView
。docs:“类概述一个灵活的视图,用于为大型数据集提供有限的窗口。”我认为Recyclerview也不能使用,因为子项不完全是一个垂直列表。我将子视图排列为交错的网格。:(请参阅以比较[1]和[3]方法,请参见:@pskink这可能很有希望,我将在此处检查更新。
“我知道为此,我必须重新使用视图”
因此,请使用
RecyclerView
.docs:“类概述一个灵活的视图,用于提供进入大型数据集的有限窗口。”我认为RecyclerView也不能使用,因为子项不完全是一个垂直列表。我将子视图排列为交错的网格。:(请参见[1]和[3]的比较)方法请参见:@pskink这可能很有希望,我将在此处检查更新。您在此处修改的是哪个类?@ataulm这是包装在Scrollview中的ViewGroup的子类。因此这不会进行任何视图循环?如果您可以更新您的答案以使其显式,这将是一件好事,正如您提到的,您希望查看recy保留您的问题。@ataulm好的,我将在答案中添加其他信息。我认为问题的标题仍然有效。您在此处修改的是哪个类?@ataulm这是包装在Scrollview中的ViewGroup的子类。因此这不会进行任何视图循环?如果您可以更新您的答案以使其明确,则更好您在问题中提到希望查看回收。@ataulm好的,我将在回答中添加其他信息。我认为问题的标题仍然有效。