代码之家  ›  专栏  ›  技术社区  ›  Isaac Waller

安卓无限列表

  •  228
  • Isaac Waller  · 技术社区  · 17 年前

    如何创建一个列表,当您到达列表末尾时,我会收到通知,以便加载更多项目?

    9 回复  |  直到 9 年前
        1
  •  268
  •   Josef Pfleger    15 年前

    一种解决方案是实现 OnScrollListener 并对 ListAdapter 在方便的状态下 onScroll 方法。

    以下 ListActivity 显示整数列表,从40开始,当用户滚动到列表末尾时添加项。

    public class Test extends ListActivity implements OnScrollListener {
    
        Aleph0 adapter = new Aleph0();
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setListAdapter(adapter); 
            getListView().setOnScrollListener(this);
        }
    
        public void onScroll(AbsListView view,
            int firstVisible, int visibleCount, int totalCount) {
    
            boolean loadMore = /* maybe add a padding */
                firstVisible + visibleCount >= totalCount;
    
            if(loadMore) {
                adapter.count += visibleCount; // or any other amount
                adapter.notifyDataSetChanged();
            }
        }
    
        public void onScrollStateChanged(AbsListView v, int s) { }    
    
        class Aleph0 extends BaseAdapter {
            int count = 40; /* starting amount */
    
            public int getCount() { return count; }
            public Object getItem(int pos) { return pos; }
            public long getItemId(int pos) { return pos; }
    
            public View getView(int pos, View v, ViewGroup p) {
                    TextView view = new TextView(Test.this);
                    view.setText("entry " + pos);
                    return view;
            }
        }
    }
    

    显然,对于长时间运行的操作(如加载Web数据),您应该使用单独的线程,并且可能希望在最后一个列表项(如Market或Gmail应用程序)中指示进度。

        2
  •  93
  •   Richard Le Mesurier    12 年前

    只是想贡献一个我用于我的应用程序的解决方案。

    它也基于 OnScrollListener 但我发现它在低端设备上的滚动性能要好得多,因为在滚动操作期间没有进行任何可见/总计数计算。

    1. 让你 ListFragment ListActivity 实施 监听器
    2. 向该类添加以下方法:

      @Override
      public void onScroll(AbsListView view, int firstVisibleItem,
              int visibleItemCount, int totalItemCount) {
          //leave this empty
      }
      
      @Override
      public void onScrollStateChanged(AbsListView listView, int scrollState) {
          if (scrollState == SCROLL_STATE_IDLE) {
              if (listView.getLastVisiblePosition() >= listView.getCount() - 1 - threshold) {
                  currentPage++;
                  //load more list items:
                  loadElements(currentPage);
              }
          }
      }
      

      哪里 currentPage 是应该添加到列表中的数据源页面,以及 threshold 是应该(如果可见)触发加载过程的列表项数(从结尾算起)。如果你准备好了 门槛 0 例如,为了加载更多的项目,用户必须滚动到列表的最后。

    3. (可选) 如您所见,“加载更多检查”仅在用户停止滚动时调用。为了提高可用性,您可以通过以下方式将加载指示器充气并添加到列表末尾: listView.addFooterView(yourFooterView) . 这种页脚视图的一个示例:

      <?xml version="1.0" encoding="utf-8"?>
      
      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/footer_layout"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:padding="10dp" >
      
          <ProgressBar
              android:id="@+id/progressBar1"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_centerVertical="true"
              android:layout_gravity="center_vertical" />
      
          <TextView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_centerVertical="true"
              android:layout_toRightOf="@+id/progressBar1"
              android:padding="5dp"
              android:text="@string/loading_text" />
      
      </RelativeLayout>
      
    4. (可选) 最后,通过调用 listView.removeFooterView(yourFooterView) 如果没有更多的项目或页面。

        3
  •  20
  •   Dariusz Bacinski    15 年前

    您可以在以下帮助下检测列表的结尾: onScrollListener ,工作代码如下:

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (view.getAdapter() != null && ((firstVisibleItem + visibleItemCount) >= totalItemCount) && totalItemCount != mPrevTotalItemCount) {
            Log.v(TAG, "onListEnd, extending list");
            mPrevTotalItemCount = totalItemCount;
            mAdapter.addMoreData();
        }
    }
    

    另一种方法(在适配器内部)如下:

        public View getView(int pos, View v, ViewGroup p) {
                if(pos==getCount()-1){
                    addMoreData(); //should be asynctask or thread
                }
                return view;
        }
    

    请注意,此方法将被多次调用,因此需要添加另一个条件来阻止对 addMoreData() .

    当您将所有元素添加到列表中时,请调用 notifyDataSetChanged() 在适配器内部更新视图(它应该在UI线程上运行- runOnUiThread )

        4
  •  4
  •   oikonomopo    9 年前

    AT Ognyan Bankov GitHub 我找到了一个简单有效的解决方案!

    它利用了 Volley HTTP library 这使得Android应用程序的联网变得更简单,最重要的是速度更快。Volley通过开放的AOSP存储库提供。

    给定的代码演示:

    1. 由HTTP分页请求填充的ListView。
    2. 使用NetworkImageView。
    3. “无休止”的列表视图分页和预读。

    为了将来的一致性我 forked Bankov's repo .

        5
  •  2
  •   Fernando Camargo    13 年前

    这里有一个解决方案,它还可以在加载时轻松地在ListView的末尾显示加载视图。

    你可以在这里看到课程:

    https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java -帮助程序,使使用这些功能而不从SimpleListViewWithLoadingIndicator扩展成为可能。

    https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java -当用户即将到达ListView的底部时开始加载数据的侦听器。

    https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java -EndlessListView。您可以直接使用这个类,也可以从它进行扩展。

        6
  •  1
  •   tehcpu    10 年前

    可能有点晚了,但下面的解决方案在我的案例中非常有用。 在某种程度上,您所需要做的就是添加到ListView A Footer 为它而创造 addOnLayoutChangeListener .

    http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)

    例如:

    ListView listView1 = (ListView) v.findViewById(R.id.dialogsList); // Your listView
    View loadMoreView = getActivity().getLayoutInflater().inflate(R.layout.list_load_more, null); // Getting your layout of FooterView, which will always be at the bottom of your listview. E.g. you may place on it the ProgressBar or leave it empty-layout.
    listView1.addFooterView(loadMoreView); // Adding your View to your listview 
    
    ...
    
    loadMoreView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
             Log.d("Hey!", "Your list has reached bottom");
        }
    });
    

    此事件在页脚变为可见并具有魅力时触发一次。

        7
  •  0
  •   ProtossShuttle    10 年前

    这个问题的关键是检测LOADMORE事件,启动数据的异步请求,然后更新列表。还需要一个带有加载指示器和其他装饰器的适配器。事实上,这个问题在某些角落的案例中非常复杂。只是一个 OnScrollListener 实现是不够的,因为有时项目不会填满屏幕。

    我写了一个个人的包裹,支持无限的清单 RecyclerView ,还提供异步加载程序实现 AutoPagerFragment 这使得从多页源获取数据非常容易。它可以将您想要的任何页面加载到 回收视图 在自定义事件中,不仅仅是下一页。

    地址如下: https://github.com/SphiaTower/AutoPagerRecyclerManager

        8
  •  0
  •   Shubham Chaudhary    10 年前

    迄今为止我所看到的最佳解决方案是 FastAdapter 回收站视图库。它有一个 EndlessRecyclerOnScrollListener .

    下面是一个示例用法: EndlessScrollListActivity

    一旦我把它用于无休止的滚动列表,我就意识到这个设置非常强大。我绝对会推荐它。

        9
  •  0
  •   V-rund Puro-hit    9 年前

    我一直在研究另一种类似的解决方案,但是,我正在使用 footerView 要给用户提供下载更多元素的可能性,请单击 脚注视图 ,我正在使用上面显示的“菜单” ListView 在父视图的底部,这个“菜单”隐藏了 列表视图 所以,当 listView 是滚动菜单消失,当滚动状态为空闲时,菜单再次出现,但当用户滚动到 列表框 ,我“询问”是否 脚注视图 在这种情况下,不会显示菜单,用户可以看到 脚注视图 加载更多内容。这里的代码:

    当做。

    listView.setOnScrollListener(new OnScrollListener() {
    
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // TODO Auto-generated method stub
            if(scrollState == SCROLL_STATE_IDLE) {
                if(footerView.isShown()) {
                    bottomView.setVisibility(LinearLayout.INVISIBLE);
                } else {
                    bottomView.setVisibility(LinearLayout.VISIBLE);
                } else {
                    bottomView.setVisibility(LinearLayout.INVISIBLE);
                }
            }
        }
    
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
    
        }
    });
    
    推荐文章