【问题标题】:How to check if a my ListView has scrollable number of items?如何检查我的 ListView 是否有可滚动的项目数?
【发布时间】:2012-06-23 22:09:11
【问题描述】:

您如何知道您的 ListView 是否有足够数量的项目以便它可以滚动?

例如,如果我的 ListView 上有 5 个项目,所有项目都将显示在一个屏幕上。但如果我有 7 个或更多,我的 ListView 开始滚动。我如何知道我的列表是否可以通过编程方式滚动?

【问题讨论】:

  • 为什么你需要知道这个?毕竟,答案可能会随着方向的变化而变化,并且答案可能会根据行中的内容而变化(不同的行布局,wrap_content 高度会根据散文而变化)。你想达到什么目的?
  • 5 个项目可能无法在 hdpi 800x480 上滚动,但可以在 ldpi 240x320 上滚动,让 android 为您处理滚动!事实上,CommonsWare 的想法,我的意思是, - 你为什么要这样做?
  • @CommonsWare,我完全理解。我想在活动底部显示页脚。如果 ListView 滚动,我想将页脚图像作为 ListView 的页脚视图。否则,我可以设置放置在活动布局末尾的另一个页脚的可见性。
  • @t0mm13b,是的,我遇到了不同屏幕尺寸的问题,这就是我想知道的原因。此外,列表中的项目数量可能会有所不同,我需要根据滚动显示页脚视图。
  • 为什么人们质疑这个问题背后的动机,这是一个很好的问题!我也想知道,因为如果 ListView 的内容比屏幕长,我想在列表视图的底部添加一些东西(屏幕外)。

标签: android android-listview


【解决方案1】:

当最后一个项目在屏幕上部分可见时,Diegosan 的答案无法区分。这是该问题的解决方案。

首先,ListView 必须先呈现在屏幕上,然后我们才能检查其内容是否可滚动。这可以通过 ViewTreeObserver 完成:

ViewTreeObserver observer = listView.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            if (willMyListScroll()) {
                 // Do something
            } 
        }
    });

这里是willMyListScroll()

boolean willMyListScroll() {   
    int pos = listView.getLastVisiblePosition();
    if (listView.getChildAt(pos).getBottom() > listView.getHeight()) {
        return true;
    } else {
        return false;
    }
}

【讨论】:

  • 优秀的解决方案 - 需要在 getChildAt(pos) 的 willMyListScroll() 方法中添加空检查。如果列表为空,它将崩溃:D
  • 我认为这是错误的。 getChildAt() 只计算屏幕上可见的孩子。同时,getLastVisiblePosition 根据 Adapter 返回索引。因此,如果 lastVisiblePosition 是 8,因为它是列表中的第 9 个项目,并且屏幕上只有 4 个可见项目,那么您将会崩溃。通过调用 getChildCount() 来验证它并查看。 getChildAt 的索引与数据集的索引不同。看看这个:stackoverflow.com/questions/6766625/…
  • 在 listView.getChildAt(pos).getBottom() 中崩溃
【解决方案2】:

根据我对 Mike Ortiz 回答的评论,我认为他的回答是错误的:

getChildAt() 只计算在屏幕上可见的孩子。同时,getLastVisiblePosition 根据 Adapter 返回索引。因此,如果 lastVisiblePosition 是 8,因为它是列表中的第 9 个项目,并且屏幕上只有 4 个可见项目,那么您将会崩溃。通过调用 getChildCount() 来验证它并查看。 getChildAt 的索引与数据集的索引不同。看看这个:ListView getChildAt returning null for visible children

这是我的解决方案:

public boolean isScrollable() {
        int last = listView.getChildCount()-1; //last visible listitem view
        if (listView.getChildAt(last).getBottom()>listView.getHeight() || listView.getChildAt(0).getTop()<0) { //either the first visible list item is cutoff or the last is cutoff
                return true;
        }
        else{
            if (listView.getChildCount()==listView.getCount()) { //all visible listitem views are all the items there are (nowhere to scroll)
                return false;
            }
            else{ //no listitem views are cut off but there are other listitem views to scroll to
                return true;
            }
        }
    }

【讨论】:

  • 即使您滚动到列表中的某个点或旋转手机后,此解决方案也可以使用。它不限于在列表初始加载后立即调用
【解决方案3】:

在 android 使用 listView 渲染屏幕之前,您无法检测到这一点。但是,您绝对可以检测到这种后期渲染。

boolean willMyListScroll() {        
   if(listView.getLastVisiblePosition() + 1 == listView.getCount()) {
      return false;
   }

   return true;             
}

它的作用是检查listView 可见窗口是否包含您的所有列表视图项。如果可以,那么listView 将永远不会滚动并且getLastVisiblePosition() 将始终等于列表的dataAdapter 中的项目总数。

【讨论】:

  • 您好,谢谢。但是如果最后一项在屏幕上是半可见的,那么列表视图也会滚动。
  • 会删除 Diegosan 答案中的“+1”部分吗?
  • 不,这不会使他的答案起作用。在下面检查我的答案。
【解决方案4】:

这是我为在列表视图的最后一行之后显示图片而编写的代码:

public class ShowTheEndListview
{
    private ImageView the_end_view;
    private TabbedFragRootLayout main_layout;
    private ListView listView;
    private float pas;
    private float the_end_img_height;
    private int has_scroll = -1;

    public ShowTheEndListview(float height)
    {
        the_end_img_height = height;
        pas = 100 / the_end_img_height;
    }

    public void setData(ImageView the_end_view, TabbedFragRootLayout main_layout, ListView listView)
    {
        this.the_end_view = the_end_view;
        this.main_layout = main_layout;
        this.listView = listView;
    }

    public void onScroll(int totalItemCount)
    {
        if(totalItemCount - 1 == listView.getLastVisiblePosition())
        {
            int pos = totalItemCount - listView.getFirstVisiblePosition() - 1;
            View last_item = listView.getChildAt(pos);

            if (last_item != null)
            {
                if(listHasScroll(last_item))
                {
//                        Log.e(TAG, "listHasScroll TRUE");
                }
                else
                {
//                        Log.e(TAG, "listHasScroll FALSE");
                }
            }
        }
    }

    private boolean listHasScroll(View last_item)
    {
        if(-1 == has_scroll)
        {
            has_scroll = last_item.getBottom() > (main_layout.getBottom() - the_end_img_height - 5) ? 1 : 0;
        }

        return has_scroll == 1;
    }

    public void resetHasScroll()
    {
        has_scroll = -1;
    }
}

【讨论】:

    【解决方案5】:

    AbsListView 包括:

    /**
     * Check if the items in the list can be scrolled in a certain direction.
     *
     * @param direction Negative to check scrolling up, positive to check scrolling down.
     * @return true if the list can be scrolled in the specified direction, false otherwise.
     * @see #scrollListBy(int)
     */
    public boolean canScrollList(int direction);
    

    您需要覆盖 layoutChildren() 并在其中使用它:

    @Override
    protected void layoutChildren() {
        super.layoutChildren();
        isAtBottom = !canScrollList(1);
        isAtTop = !canScrollList(-1);
    }
    

    【讨论】:

      【解决方案6】:

      这是我以前检查的方式

      if (listView.getAdapter() != null
                          && listView.getLastVisiblePosition() == listView.getAdapter().getCount() - 1
                          && listView.getChildAt(listView.getChildCount() - 1).getBottom() == listView.getBottom())
      

      如果为真,则列表在底部

      【讨论】:

        【解决方案7】:

        使用setOnScrollListener,通过将回调应用到OnScrollListener,您可以使用预定义的常量确定是否正在发生滚动并相应地处理这种情况。

        【讨论】:

        • 只有当事件发生时我才会收到回调,不是吗?但布局必须在用户尝试滚动列表之前更改。
        【解决方案8】:
         boolean listBiggerThanWindow = appHeight - 50 <= mListView.getHeight();
        
                    Toast.makeText(HomeActivity.this, "list view bigger that window? " + listBiggerThanWindow, Toast.LENGTH_LONG)
                            .show();
        
                    if (listBiggerThanWindow) {
                        // do your thing here...
                       }
        

        您可以通过在 View 上调用 post(Runnable) 在 onCreate() 中获取维度。

        【讨论】:

        • 您使用 appHeight - 50。什么是 appHeight ,它的度量是什么(px、dp、dip.. 等?)。请添加更多信息。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-02
        • 1970-01-01
        • 1970-01-01
        • 2020-11-25
        • 1970-01-01
        相关资源
        最近更新 更多