为什么listview初次显示时没滚动却自动调用onscroll 滚动方向方法

android 从源码分析为什么Listview初次显示时没滚动却自动调用onScroll方法的原因
我们做Listview的分批加载时,需要为Listview调用setOnScrollListener(具体代码可见我上一篇博客)
可是,我们会发现,当运行程序时,listview明明没有滚动,那为什么会调用onScroll方法呢?(补充:此时onScrollStateChanged并不会调用)
我们先看setOnScrollListener:
public void setOnScrollListener(OnScrollListener l) {
mOnScrollListener =
invokeOnItemScrollListener();
}setOnScrollListener里面调用了invokeOnItemScrollListener()方法,接着看该方法源码:
invokeOnItemScrollListener() {
if (mFastScroller != null) {
mFastScroller.onScroll(mFirstPosition, getChildCount(), mItemCount);
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount);//这里调用onScroll,一切真相大白了。
onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'查看: 6469|回复: 19
重写的listview不走onScroll和onScrollStateChanged方法
该用户从未签到主题帖子e币
只是在实现了onScrollListener接口的自定的listview中提供了一个接口供外部实现
但是我发现listview滚动的时候onScroll和onScrollStateChanged方法都不走是怎么回事
[mw_shl_code=java,true]listView.setOnScrollListener(OnScrollListener listener);[/mw_shl_code]
应该是这样的。而不是你那样的
该用户从未签到主题帖子e币
[mw_shl_code=java,true]listView.setOnScrollListener(OnScrollListener listener);[/mw_shl_code]
应该是这样的。而不是你那样的
虽然我认为是一样的,我试试看把&
该用户从未签到主题帖子e币
[mw_shl_code=java,true]public class CustomListView extends ListView implements OnScrollListener {
& & & & private OnScrollAtPointL
& & & & public CustomListView(Context context, AttributeSet attrs, int defStyle) {
& & & & & & & & super(context, attrs, defStyle);
& & & & public CustomListView(Context context, AttributeSet attrs) {
& & & & & & & & super(context, attrs);
& & & & public CustomListView(Context context) {
& & & & & & & & super(context);
& & & & @Override
& & & & public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
& & & & & & & & System.out.println(&111111&);
& & & & @Override
& & & & public void onScrollStateChanged(AbsListView view, int scrollState) {
& & & & & & & & System.out.println(&2222222&);
& & & & public interface OnScrollAtPointListener {
& & & & & & & & public void onScrollAtPoint();
& & & & public OnScrollAtPointListener getListener() {
& & & & & & & &
& & & & public void setOnScrollAtPointListener(OnScrollAtPointListener listener) {
& & & & & & & & this.listener =
}[/mw_shl_code]
签到天数: 1 天连续签到: 1 天[LV.1]初来乍到主题帖子e币
是不是你没有注册这个监听器到listview中??
关键是,都不出来&
签到天数: 1 天连续签到: 1 天[LV.1]初来乍到主题帖子e币
我知道了,你最好把实现的onScrollListener接口放到你要调用的activity中,然后让你自定义的listview对象注册一下监听器为this,就好了吧
该用户从未签到主题帖子e币
sk. 发表于
虽然我认为是一样的,我试试看把
该用户从未签到主题帖子e币
是不是你没有注册这个监听器到listview中??
关键是,都不出来
我的意思就是跟楼上的那位一样的,的手动注册&
该用户从未签到主题帖子e币
按文档说明的话应该是走的,你用system out是不是打到console去了,又或者是没调用setOnScrollListener?
该用户从未签到主题帖子e币
[mw_shl_code=java,true] public void setOnScrollListener(OnScrollListener l) {
& && &&&mOnScrollListener =
& && &&&invokeOnItemScrollListener();
& &&&* Notify our scroll listener (if there is one) of a change in scroll state
& & void invokeOnItemScrollListener() {
& && &&&if (mFastScroller != null) {
& && && && &mFastScroller.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
& && &&&if (mOnScrollListener != null) {
& && && && &mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
void reportScrollStateChange(int newState) {
& && &&&if (newState != mLastScrollState) {
& && && && &if (mOnScrollListener != null) {
& && && && && & mOnScrollListener.onScrollStateChanged(this, newState);
& && && && && & mLastScrollState = newS
& && && && &}
[/mw_shl_code]
你可以看下这个源码。。AbsListView
你这个就是木有调用list.setonScrollListener();导致的,调用一下就好了,绝对行的,记得把我的设置为最佳答案喔&
谢谢回复!!
签到天数: 1 天连续签到: 1 天[LV.1]初来乍到主题帖子e币
、PromiSe_蛋 发表于
关键是,都不出来
我的意思就是跟楼上的那位一样的,的手动注册
签到天数: 1 天连续签到: 1 天[LV.1]初来乍到主题帖子e币
sk. 发表于
[mw_shl_code=java,true] public void setOnScrollListener(OnScrollListener l) {
& && &&&mOnScrollListe ...
你这个就是木有调用list.setonScrollListener();导致的,调用一下就好了,绝对行的,记得把我的设置为最佳答案喔
你这个是回复我的?
坑爹啊。。。&
该用户从未签到主题帖子e币
你这个就是木有调用list.setonScrollListener();导致的,调用一下就好了,绝对行的,记得把我的设置为最 ...
你这个是回复我的?&&
坑爹啊。。。
bushi,回复完了我也纳闷了,怎么回复你了&
该用户从未签到主题帖子e币
好吧 貌似是这个问题..
但是为什么会这样呢,我另外还有一个重写过的listview.同样是在内部实现onscrolllistener.就可以..
签到天数: 1 天连续签到: 1 天[LV.1]初来乍到主题帖子e币
sk. 发表于
你这个是回复我的?&&
坑爹啊。。。
bushi,回复完了我也纳闷了,怎么回复你了
该用户从未签到主题帖子e币
本帖最后由 oyk0731 于
12:00 编辑
我顶 原来我也有这个问题,,,在真机上就好了,,,估计模拟器有问题
圣诞限量勋章
圣诞限量勋章
社区认证会员
社区认证会员
QQ已认证,此人靠谱
社区贡献者
eoeAndriod社区贡献网友
推荐阅读热门话题
61882418416379326279279260257251226218210206715
1&小时前2&小时前2&小时前4&小时前昨天&23:59昨天&20:35昨天&20:33昨天&17:47昨天&17:01昨天&17:01昨天&16:34昨天&15:14昨天&14:50昨天&11:59前天&23:57前天&23:24
Powered byAndroid应用中ListView利用OnScrollListener分页加载数据
作者:神神的蜗牛
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了Android应用中ListView利用OnScrollListener分页加载数据的方法,包括对OnScrollListener事件顺序次数的分析,需要的朋友可以参考下
当用户从网络上读取微薄的时候,如果一下子全部加载用户未读的微薄这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容。这时候,我们就需要用到另一个功能,那就是listview的分页了。通过分页分次加载数据,用户看多少就去加载多少。
通常这也分为两种方式,一种是设置一个按钮,用户点击即加载。另一种是当用户滑动到底部时自动加载。今天我就和大家分享一下这个功能的实现。
首先,写一个xml文件,moredata.xml,该文件即定义了放在listview底部的视图:
&?xml version="1.0" encoding="utf-8"?&
&LinearLayout xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" &
android:id="@+id/bt_load"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="加载更多数据" /&
&ProgressBar
android:id="@+id/pg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:visibility="gone"
&/LinearLayout&
可以看到是一个按钮和一个进度条。因为只做一个演示,这里简单处理,通过设置控件的visibility,未加载时显示按钮,加载时就显示进度条。
写一个item.xml,大家应该很熟悉了。用来定义listview的每个item的视图。
&?xml version="1.0" encoding="utf-8"?&
&LinearLayout xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" &
android:id="@+id/tv_title"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="12sp"
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
&/LinearLayout&
main.xml就不贴了,整个主界面就一个listview。
直接先看下Activity的代码,在里面实现分页效果。
package com.notice.
import java.util.ArrayL
import java.util.HashM
import android.app.A
import android.os.B
import android.os.H
import android.view.V
import android.view.View.OnClickL
import android.widget.AbsListV
import android.widget.AbsListView.OnScrollL
import android.widget.B
import android.widget.ListV
import android.widget.ProgressB
import android.widget.SimpleA
import android.widget.T
public class MoreDateListActivity extends Activity implements OnScrollListener {
// ListView的Adapter
private SimpleAdapter mSimpleA
private ListV
private ProgressB
private ArrayList&HashMap&String,String&&
// ListView底部View
private View moreV
// 设置一个最大的数据条数,超过即不再加载
private int MaxDateN
// 最后可见条目的索引
private int lastVisibleI
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MaxDateNum = 22; // 设置最大数据条数
lv = (ListView) findViewById(R.id.lv);
// 实例化底部布局
moreView = getLayoutInflater().inflate(R.layout.moredate, null);
bt = (Button) moreView.findViewById(R.id.bt_load);
pg = (ProgressBar) moreView.findViewById(R.id.pg);
handler = new Handler();
// 用map来装载数据,初始化10条数据
list = new ArrayList&HashMap&String,String&&();
for (int i = 0; i & 10; i++) {
HashMap&String, String& map = new HashMap&String, String&();
map.put("ItemTitle", "第" + i + "行标题");
map.put("ItemText", "第" + i + "行内容");
list.add(map);
// 实例化SimpleAdapter
mSimpleAdapter = new SimpleAdapter(this, list, R.layout.item,
new String[] { "ItemTitle", "ItemText" },
new int[] { R.id.tv_title, R.id.tv_content });
// 加上底部View,注意要放在setAdapter方法前
lv.addFooterView(moreView);
lv.setAdapter(mSimpleAdapter);
// 绑定监听器
lv.setOnScrollListener(this);
bt.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
pg.setVisibility(View.VISIBLE);// 将进度条可见
bt.setVisibility(View.GONE);// 按钮不可见
handler.postDelayed(new Runnable() {
public void run() {
loadMoreDate();// 加载更多数据
bt.setVisibility(View.VISIBLE);
pg.setVisibility(View.GONE);
mSimpleAdapter.notifyDataSetChanged();// 通知listView刷新数据
private void loadMoreDate() {
int count = mSimpleAdapter.getCount();
if (count + 5 & MaxDateNum) {
// 每次加载5条
for (int i = i & count + 5; i++) {
HashMap&String, String& map = new HashMap&String, String&();
map.put("ItemTitle", "新增第" + i + "行标题");
map.put("ItemText", "新增第" + i + "行内容");
list.add(map);
// 数据已经不足5条
for (int i = i & MaxDateN i++) {
HashMap&String, String& map = new HashMap&String, String&();
map.put("ItemTitle", "新增第" + i + "行标题");
map.put("ItemText", "新增第" + i + "行内容");
list.add(map);
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// 计算最后可见条目的索引
lastVisibleIndex = firstVisibleItem + visibleItemCount - 1;
// 所有的条目已经和最大条数相等,则移除底部的View
if (totalItemCount == MaxDateNum + 1) {
lv.removeFooterView(moreView);
Toast.makeText(this, "数据全部加载完成,没有更多数据!", Toast.LENGTH_LONG).show();
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 滑到底部后自动加载,判断listview已经停止滚动并且最后可视的条目等于adapter的条目
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
&& lastVisibleIndex == mSimpleAdapter.getCount()) {
// 当滑到底部时自动加载
// pg.setVisibility(View.VISIBLE);
// bt.setVisibility(View.GONE);
// handler.postDelayed(new Runnable() {
// @Override
// public void run() {
// loadMoreDate();
// bt.setVisibility(View.VISIBLE);
// pg.setVisibility(View.GONE);
// mSimpleAdapter.notifyDataSetChanged();
// }, 2000);
通过注释,大家应该很容易理解了。这里做下简单的解析。首先要注意的是,addFootView方法一定要在setAdapter方法之前,否则会无效。addFootView方法为listview底部加入一个视图,在本例中就是那个Button加progressbar的视图。当用户点击按钮时,调用loadmoreDate方法,为listview绑定更多的数据,通过adapter的notifyDataSetChanged方法通知listview刷新,显示刚加入的数据。
这里用handler异步延迟2秒操作,模仿加载过程。同时listview绑定了onScrollListener监听器,并且实现了onScroll和onScrollStateChanged方法。在后者方法中,我们通过判断listview已经停止滚动并且最后可视的条目等于adapter的条目,可以知道用户已经滑动到底部并且自动加载,代码中将这部分代码注释掉了,大家可以自己试下。
代码中还加入了一个MaxDateNum变量,用来记录最大的数据数量。也就是说网络或者其他地方一共的数据。通过onScroll方法判断用户加载完这些数据后,移除listview底部视图,不让继续加载。同时在loadmoreDate方法中也对最大数据量做相应的操作来判断加载数量。(默认加载5条,不足5条时加载剩余的)。
看下效果图:
关于OnScrollListener事件顺序次数的简要分析
在 Android 的 OnScrollListener 整个事件我主要分析下他的执行顺序:
实现滚动事件的监听接口
new AbsListView.OnScrollListener(){
public void onScrollStateChanged(AbsListView absListView, int scrollState)
switch (scrollState) {
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
// 手指触屏拉动准备滚动,只触发一次
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
// 持续滚动开始,只触发一次
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
// 整个滚动事件结束,只触发一次
public void onScroll(AbsListView absListView, int i, int i1, int i2)
// 一直在滚动中,多次触发
顺序: 1、3、5
之前一直很迷糊,后来仔细测试后得出上面代码注释中的结论。
另外对于 ListView 图片列表的滚动,应该在SCROLL_STATE_FLING时让图片不显示,提高滚动性能让滚动更平滑,SCROLL_STATE_IDLE时显示当前屏幕可见的图片,对于onScroll()接口方法基本上不用他。
1. 当手指只轻触屏幕不拉动只会触发一次onScroll方法,不会触发其他滚动事件;
2. 如果手指触碰屏幕后停滞一下再滑动则首先执行一次onScroll方法 然后才是SCROLL_STATE_TOUCH_SCROLL事件;
3. 如果手指碰到屏幕后直接滑动则第一次就执行SCROLL_STATE_TOUCH_SCROLL事件;
3. 触发SCROLL_STATE_TOUCH_SCROLL事件后还会继续多次触发onScroll事件,而不是直接触发SCROLL_STATE_FLING事件;
4. 滚动后不一定会触发 SCROLL_STATE_FLING事件,可能和手指滑动的距离有关系;
5. 滚动的过程中会多次调用onScroll方法;
6. 除了onScroll触发多次,其他事件在整个过程中只会触发一次。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具本帖子已过去太久远了,不再提供回复功能。}

我要回帖

更多关于 listview 去掉滚动条 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信