ListView实现上拉加载&下拉刷新

上拉加载&下拉刷新

思路详解:

自定义的带有下拉刷新和上拉加载的ListView开始时,跟系统的ListView一样。不过多了个header和footer只不过这两个布局以不同的方式隐藏起来了而已。(header是在手机屏幕外的上面,footer是直接隐藏起来了。因为下拉和上拉加载不同,下拉加载有手势判断,要出现动画效果,根据下拉的各种手势,来设置具体的操作。如果直接跟footer一样首先默认header的View.setVisibility(GONE),当有下拉手势时再设置View.setVisibility(View.VISIBLE)就会没有良好的动画效果。)

如下图所示:

上拉加载:

上拉加载适用于需要加载的数据量很大时,如果一下子加载完。会使ListView出现卡顿。这时候,如果利用上拉加载。先加载一部分数据。当上拉时,再加载其他的一部分数据。这样就会有很好的用户体验。

接下来看上拉加载逻辑:上拉加载我们利用的是AbsListView.OnScrollListener这个接口。 它有两个方法需要重写:

1.publicvoid onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount) {};

//滚动时一直回调,直到停止滚动时才停止回调。单击时回调一次。

//firstVisibleItem:当前能看见的第一个列表项ID(从0开始)

//visibleItemCount:当前能看见的列表项个数(小半个也算)

//totalItemCount:列表项共数
2.publicvoid onScrollStateChanged(AbsListView view,int scrollState) {};

//正在滚动时回调,回调2-3次,手指没抛则回调2次。scrollState = 2的这次不回调

//回调顺序如下

//第1次:scrollState = SCROLL_STATE_TOUCH_SCROLL(1) 正在滚动

//第2次:scrollState = SCROLL_STATE_FLING(2) 手指做了抛的动作(手指离开屏幕前,用力滑了一下)

//第3次:scrollState = SCROLL_STATE_IDLE(0) 停止滚动

//当屏幕停止滚动时为0;当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1;

//由于用户的操作,屏幕产生惯性滑动时为2

//当滚到最后一行且停止滚动时,执行加载

自定义LoadListView

1.定义变量

private int lastVisibleItem; //最后一个可见项

private int totalItems; //总的item

private View footer; //底部View+头部View;

private boolean isLoading = false;//是否正在加载

private ILoadListener iListener;//自定义的一个加载接口。暴露给MainActivity让它实现具体加载操作。可以根据需求不同而改写。

2.加载布局文件及设置监听

private void initViews(Context context) {

//获得footer+header布局文件

LayoutInflater inflater =LayoutInflater.from(context);

footer = inflater.inflate(R.layout.footer,null);

footer.findViewById(R.id.ll_footer).setVisibility(GONE);//初始化时设置footer不可见

this.addFooterView(footer);

this.setOnScrollListener(this);//设置滚动监

}

3.重写OnScrollListener的两个方法

4.完成接口设置

/**

* 加载更多数据的回调接口

*/

public interface ILoadListener {

    public void onLoad();

}

//上拉加载完毕

public void loadCompleted(){

    isLoading =false;
    
    footer.findViewById(R.id.ll_footer).setVisibility(GONE);

}


public void setInterface(ILoadListener iListener){

    this.iListener=iListener;

}

5.在MainActivity中实现LoadListView暴露的接口中的onLoad方法

//实现onLoad()方法。

@Override

public void onLoad() {

    //添加延时效果模拟数据加载

    Handler handler= new Handler() ;

    handler.postDelayed(new Runnable() {

        @Override

        public void run() {
    
        initNewDatas();//得到新数据

        arrayAdapter.notifyDataSetChanged();//刷新ListView;

        mListView.loadCompleted();

        }

    }, 2000);

}

上拉加载数据完成。

下拉刷新:

1.header布局文件

2.在LoadListView中定义变量

private boolean isRemark = false;//判断是否在当前页的最顶端并下滑

private int startY; //Y坐标 记录手指开始按下的坐标

private RLoadListener rLoadListener;//自定义的一个加载接口。暴露给MainActivity让它实现具体加载操作。可以根据需求不同而改写。

private int scrollState;//当前滚动的 状态

private int headerHeight;//顶部布局文件的高度

final int NONE= 0;//正常状态

final int PULL =1;//下拉

final int RELESE =2;//释放

final int REFLASHING =3; //刷新

private int state=0;//判断当前状态,默认为正常状态

private int firstVisibleItem;//第一个可见项

private View header; //头部View;

3.添加头部到ListView中

这里添加头布局的时候需要计算header到底要移出屏幕多少的距离(移出的距离即为header的高),并且要告知父布局

4.在OnScrollListener的两个方法中记录一些状态量便于后面对OnTouch事件的操作

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

    this.scrollState =scrollState;

}

@Override

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int                 
            totalItemCount) {

    this.firstVisibleItem = firstVisibleItem;

}

5.利用OnTouchEvent对下拉手势操作进行监听:

先来说明下拉刷新会出现的情况:

1.下拉距离过短,不进行数据刷新。

2.下拉到一定距离刷新数据。

当进行下拉刷新的时候,手势有3种状态:

1.刚按下的时候;

2.手指下滑移动的时候;

3.手指抬起释放的时候。

这3种手指状态又对应了header不同的View状态,然后根据view的状态,再来改变header的显示。

6.下拉刷新接口,暴露给MainActivity来具体实现到底刷新出什么数据:

/**

* 下拉刷新接口

*/

public interface RLoadListener{

    public void onRefresh();

}

public void setReflashInterface(RLoadListener rLoadListener){

    this.rLoadListener =rLoadListener;

}

7.刷新完要做的工作

/**

* 获取完整数据

*

*/

public void reflashComplete(){

    state = NONE;

    isRemark = false;

    reflashViewByState();

    TextView lasetupdate_time = (TextView) header.findViewById(R.id.tv_lastupdate_time);

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");

    Date date = new Date(System.currentTimeMillis());

    String time = simpleDateFormat.format(date);

    lasetupdate_time.setText(time);


}

8.在MainActivity中应用LoadListView

SwipeRefreshLayout实现下拉刷新(仅效果)

  • isRefreshing()

判断当前的状态是否是刷新状态。

  • setColorSchemeResources(int... colorResIds)

设置下拉进度条的颜色主题,参数为可变参数,并且是资源id,可以设置多种不同的颜色,每转一圈就显示一种颜色。

  • setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)

设置监听,需要重写onRefresh()方法,顶部下拉时会调用这个方法,在里面实现请求数据的逻辑,设置下拉进度条消失等等。

  • setProgressBackgroundColorSchemeResource(int colorRes)

设置下拉进度条的背景颜色,默认白色。

  • setRefreshing(boolean refreshing)

设置刷新状态,true表示正在刷新,false表示取消刷新。

使用:

1.设置布局

<android.support.v4.widget.SwipeRefreshLayout         
                 xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/swipe_refresh"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    <ListView

        android:id="@+id/list_view"

        android:layout_width="match_parent"

        android:layout_height="match_parent">
    </ListView>

</android.support.v4.widget.SwipeRefreshLayout>

2.在代码中使用

在该布局文件对应的Activity或其他类中获取布局id,先设置ListView显示的适配器,然后再设置SwipeRefreshLayout。

注:不能在onCreate中设置,这个表示当前是刷新状态,如果一进来就是刷新状态,SwipeRefreshLayout会屏蔽掉下拉事件          //swipeRefreshLayout.setRefreshing(true);

//声明控件

private SwipeRefreshLayout swiper;

private ListView mListView;

//声明并初始化ListView的数据源

private List<String> list = new ArrayList<>();

//声明ListView的适配器

private ArrayAdapter adapter;

@Override

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.swipe_layout);

    //初始化SwipeRefreshLayout

    swiper = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);

    //为SwipeRefreshLayout设置监听事件

    swiper.setOnRefreshListener(this);
    
    //为SwipeRefreshLayout设置刷新时的颜色变化,最多可以设置4种

    swiper.setColorSchemeResources(android.R.color.holo_blue_bright,

    android.R.color.holo_green_light,

    android.R.color.holo_orange_light,

    android.R.color.holo_red_light);

    //初始化ListView

    mListView = (ListView) findViewById(R.id.list_view);

    //初始化适配器

    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getData());
    
    //设置适配器

    mListView.setAdapter(adapter);

}

//增加数据

private List<String> getData() {

    list.add("hello");

    list.add("this is johnsonHou");

    list.add("an android rookie developer");

    list.add("love android");

    return list;

}

//实现OnRefreshListener 的onRefresh()方法

@Override

public void onRefresh() {

    //刷新

    new Handler().postDelayed(new Runnable() {

        @Override

        public void run() {

        //结束后停止刷新

        swiper.setRefreshing(false);
    
        }

    }, 3000);

}

//简单示例,手动添加数据

private void refreshData() {

    list.add(0, String.valueOf((int) (Math.random() * 10)));

    adapter.notifyDataSetChanged();

}

猜你喜欢

转载自blog.csdn.net/qq_34149526/article/details/83019115