实现onScrollListener以检测ListView中滚动的结束

如何解决实现onScrollListener以检测ListView中滚动的结束

| 我有一个显示某些项目的
ListView
。我想对
ListView
可见部分中当前显示的项目执行一些操作,具体取决于
ListView
的滚动方式;因此我想实现implement0的
OnScrollListener
。 根据Android api参考,onScroll方法“滚动完成后将调用”。在我看来这似乎是我所需要的,因为滚动完成后,我在
ListView
上执行我的操作(onScroll方法返回显示的第一个项目的索引和显示的项目数)。 但是一旦实现,就可以从ѭ6中看到onScroll方法不仅在滚动完成后被触发,而且还从滚动的开始到结束为进入显示视图的每个新项都触发。这不是我所期望的行为,也不是我所需要的。侦听器的另一种方法(onScrollStateChanged)则不提供有关当前显示在“ 0”中的项目的信息。 那么,有谁知道如何使用这两种方法来检测滚动的结束并获得有关所显示项目的信息? api引用与方法的实际行为之间的不一致使我有些困惑。 提前致谢。 附注:我看到了一些类似的话题,但是没有什么可以帮助我理解整个过程。     

解决方法

        最终,我找到了一个不太优雅的解决方案,但是对我有用。弄清楚onScroll方法是在滚动的每个步骤中调用的,而不仅仅是在滚动端被调用,并且onScrollStateChanged实际上仅在滚动完成时才被调用,我这样做是:
public void onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount) {
    this.currentFirstVisibleItem = firstVisibleItem;
    this.currentVisibleItemCount = visibleItemCount;
}

public void onScrollStateChanged(AbsListView view,int scrollState) {
    this.currentScrollState = scrollState;
    this.isScrollCompleted();
 }

private void isScrollCompleted() {
    if (this.currentVisibleItemCount > 0 && this.currentScrollState == SCROLL_STATE_IDLE) {
        /*** In this way I detect if there\'s been a scroll which has completed ***/
        /*** do the work! ***/
    }
}
实际上,每次滚动ListView时,我都会保存有关第一个可见项和可见项计数的数据(onScroll方法);当滚动状态更改(onScrollStateChanged)时,我保存状态并调用另一个方法,该方法实际上了解滚动是否完成以及滚动是否完成。这样,我也可以获得有关所需可见项目的数据。 也许不干净,但是行得通! 问候     ,        
@Override
public void onScroll(AbsListView view,int totalItemCount) {

  if (list.getLastVisiblePosition() == list.getAdapter().getCount() - 1
      && list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) {
    // Scroll end reached
    // Write your code here
  }
}
    ,        
@Override
        public void onScroll(AbsListView view,int totalItemCount) {

            if((firstVisibleItem + visibleItemCount) ==  totalItemCount)
            {
                Log.i(\"Info\",\"Scroll Bottom\" );
            }
        }});
    ,        降低这种行为是很棘手的,花了我相当长的时间才能使它完美。问题的根源在于,据我所知,滚动侦听器本身实际上还不足以检测到“滚动停止”(包括方向按钮/轨迹球)。我最终做了一些符合我期望的工作。 我认为我能做到的最好方法是扩展ListView并重写一些方法:
  ....
  @Override
  public boolean onKeyUp(int keyCode,KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP) {
      startWait();
    }
    return super.onKeyUp(keyCode,event);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
      stopWait();
    }
    if (event.getAction() == MotionEvent.ACTION_UP ||
        event.getAction() == MotionEvent.ACTION_CANCEL) {
      startWait();
    }
    return super.onTouchEvent(event);
  }

  private OnScrollListener customScrollListener = new OnScrollListener() {
    @Override
    public void onScroll(AbsListView view,int totalItemCount) {
      stopWait();
    }

    @Override
    public void onScrollStateChanged(AbsListView view,int scrollState) {
      if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
        startWait();
      } else {
        stopWait();
      }
    }
  };

  //All this waiting could be improved,but that\'s the idea
  private Thread waitThread = null;
  private int waitCount  = Integer.MIN_VALUE;

  public void stopWait() {
    waitCount = Integer.MIN_VALUE;
  }

  public synchronized void startWait() {
    waitCount = 0;

    if (waitThread != null) {
      return;
    }

    waitThread = new Thread(new Runnable() {
    @Override
    public void run() {
    try {
      for (; waitCount.get() < 10; waitCount++) {
        Thread.sleep(50);
      }

        //Kick it back to the UI thread.
        view.post(theRunnableWithYourOnScrollStopCode); // HERE IS WHERE YOU DO WHATEVER YOU WANTED TO DO ON STOP
      } catch (InterruptedException e) {
      } finally  {
        waitThread = null;
      }
    }
  });
  waitThread.start();
}
请注意,您还必须在构造函数中绑定ѭ12。我认为这种实现很好,因为它不会立即触发“事件”,因此会稍等一会,直到它完全停止滚动为止。     ,        试试这个...
@Override
public void onScroll(AbsListView view,int totalItemCount) {

    int position = firstVisibleItem+visibleItemCount;
    int limit = totalItemCount;

    // Check if bottom has been reached
    if (position >= limit && totalItemCount > 0) {
         //scroll end reached
          //Write your code here
    }
}
    ,        电子考证答案的更有用的表示 侦听器实现:
public abstract class OnScrollFinishListener implements AbsListView.OnScrollListener {

    int mCurrentScrollState;
    int mCurrentVisibleItemCount;

    @Override
    public void onScrollStateChanged(AbsListView view,int scrollState) {
        mCurrentScrollState = scrollState;
        if (isScrollCompleted()) {
            onScrollFinished();
        }
    }

    @Override
    public void onScroll(AbsListView view,int totalItemCount) {
        mCurrentVisibleItemCount = visibleItemCount;
    }

    private boolean isScrollCompleted() {
        return mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE;
    }

    protected abstract void onScrollFinished();
}
用法:
    listView.setOnScrollListener(new OnScrollFinishListener() {
         @Override
         protected void onScrollFinished() {
             // do whatever you need here!
         }
    });
    ,        分析先前的答案,发现自己的答案: 在onViewCreated,onCreate或任何获取列表视图的位置:
ListView list = (ListView) view.findViewById(R.id.[your id]);
    list.setOnScrollListener(this);
然后填写侦听器方法:
public void onScroll(AbsListView view,int totalItemCount) {
 // yes,just leave it empty
}

public void onScrollStateChanged(AbsListView view,int scrollState) {
    this.isScrollCompleted(view,scrollState);
 }

private void isScrollCompleted(AbsListView view,int scrollState) {
    if (!view.canScrollVertically(1) && this.currentScrollState == SCROLL_STATE_IDLE) {
        // do work
    }
}
似乎做了它应该做的事情:无需大量代码和适配器修改即可检测列表结尾。     ,        还有另一种简单的解决方案。将侦听器置于listview的适配器中,并在getview中检查if(position == totalItemCount要显示的数组中的项目),如果是,则从适配器中调用侦听器,然后在侦听器中运行您的操作     ,        在尝试确定列表是否位于OnScrollListener的底部时,我遇到了很多问题,我发现的最佳解决方案是检查 如果我当前显示最后一行,则从适配器的getView方法中获取:
@Override
    public View getView(int position,View convertView,ViewGroup parent) {
        ActivityView view;
        if (convertView==null)
            view = (ActivityView)inflater.inflate(R.layout.activity_item,null);
        else
            view = (ActivityView)convertView;

       view.showRow(activitiesList.get(position),position,controller,this);
        if(position == activitiesList.size() - 1)
        {
            Log.i(\"BOTTOM\",\"reached\");
        }
        return view;
    }
在这里,我可以轻松地创建一个接口,以通知片段/活动到达底部。 干杯。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res