您的位置:首页 > 移动开发 > Android开发

Android实战简易教程<五十四>(通过实现OnScrollListener接口实现下拉刷新功能)

2015-09-26 11:18 906 查看
在上一篇的基础上实现下拉刷新功能。主要通过对滚动状态和手势监听实现这一功能,下面我们看一下代码:

1.header.xml:

[html] view
plaincopy

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical" >



<RelativeLayout

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:paddingBottom="10dip"

android:paddingTop="10dip" >



<LinearLayout

android:id="@+id/layout"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:gravity="center"

android:orientation="vertical" >



<TextView

android:id="@+id/tip"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="下拉可以刷新!" />



<TextView

android:id="@+id/lastupdate_time"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

</LinearLayout>



<ImageView

android:id="@+id/arrow"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_toLeftOf="@id/layout"

android:layout_marginRight="20dip"

android:src="@drawable/pull_to_refresh_arrow" />



<ProgressBar

android:id="@+id/progress"

style="?android:attr/progressBarStyleSmall"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_toLeftOf="@id/layout"

android:layout_marginRight="20dip"

android:visibility="gone" />

</RelativeLayout>



</LinearLayout>

2.LoadListView.java:

[java] view
plaincopy

package com.example.listviewscrolldemo;



import java.text.SimpleDateFormat;

import java.util.Date;



import android.content.Context;

import android.util.AttributeSet;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.view.animation.RotateAnimation;

import android.widget.AbsListView;

import android.widget.AbsListView.OnScrollListener;

import android.widget.ImageView;

import android.widget.ListView;

import android.widget.ProgressBar;

import android.widget.TextView;



public class LoadListView extends ListView implements OnScrollListener {

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

private int totalItems;// 所有项

private int firstVisibleItem;// 第一可见项

private View footer, header;// 底部布局

private Boolean isLoading = false;

private Boolean isRemark = false;// 判断在当前页面的最顶端并下滑;

private int startY;// Y坐标值

private ILoadListener iListener;

private RLoadListener rListener;

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;// 判断当前状态



public LoadListView(Context context) {

super(context);

initView(context);

}



public LoadListView(Context context, AttributeSet attrs) {

super(context, attrs);

initView(context);

}



public LoadListView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

initView(context);

}



/**

* 添加底部加载提示到布局Listview

*

* @param context

*/

private void initView(Context context) {

LayoutInflater inflater = LayoutInflater.from(context);

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

header = inflater.inflate(R.layout.header_layout, null);

footer.findViewById(R.id.ll_footer).setVisibility(View.GONE);// 首先设置加载提示不可见

measureView(header);

headerHeight = header.getMeasuredHeight();

Log.i("tag", "headerHeight = " + headerHeight);

topPadding(-headerHeight);

this.addFooterView(footer);

this.addHeaderView(header);

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



}



/**

* 通知父布局,占用的宽,高;

*

* @param view

*/

private void measureView(View view) {

ViewGroup.LayoutParams p = view.getLayoutParams();

if (p == null) {

p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

}

int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);

int height;

int tempHeight = p.height;

if (tempHeight > 0) {

height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);

} else {

height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);

}

view.measure(width, height);

}



/**

* 设置header 布局 上边距;

*

* @param topPadding

*/

private void topPadding(int topPadding) {

header.setPadding(header.getPaddingLeft(), topPadding, header.getPaddingRight(), header.getPaddingBottom());

header.invalidate();

}



@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

this.scrollState = scrollState;

if (lastVisibleItem == totalItems && scrollState == SCROLL_STATE_IDLE) {



if (!isLoading) {// 判断不是正在加载!

footer.findViewById(R.id.ll_footer).setVisibility(View.VISIBLE);// 首先设置加载提示可见

iListener.onLoad();

isLoading = true;

}



}



}



@Override

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

this.lastVisibleItem = firstVisibleItem + visibleItemCount;

this.totalItems = totalItemCount;

this.firstVisibleItem = firstVisibleItem;

}



// 传递

public void setInterface(ILoadListener iListener) {

this.iListener = iListener;

}



public void setRefreshInterface(RLoadListener rListener) {

this.rListener = rListener;

}



/**

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

*

* @author Administrator

*

*/

public interface ILoadListener {

public void onLoad();

}



/**

* 下拉刷新回调接口

*

* @author Administrator

*

*/

public interface RLoadListener {

public void onRefresh();

}



// 加载完毕

public void loadCompleted() {

isLoading = false;

footer.findViewById(R.id.ll_footer).setVisibility(View.GONE);

}



@Override

public boolean onTouchEvent(MotionEvent ev) {

// TODO Auto-generated method stub

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN://下拉

if (firstVisibleItem == 0) {

isRemark = true;

startY = (int) ev.getY();

}

break;



case MotionEvent.ACTION_MOVE://移动

onMove(ev);

break;

case MotionEvent.ACTION_UP://上拉

if (state == RELESE) {

state = REFLASHING;

// 加载最新数据;

reflashViewByState();

rListener.onRefresh();

} else if (state == PULL) {

state = NONE;

isRemark = false;

reflashViewByState();

}

break;

}

return super.onTouchEvent(ev);

}



/**

* 判断移动过程操作;

*

* @param ev

*/

private void onMove(MotionEvent ev) {

if (!isRemark) {

return;

}

int tempY = (int) ev.getY();

int space = tempY - startY;

int topPadding = space - headerHeight;

switch (state) {

case NONE:

if (space > 0) {// 向下滑动

state = PULL;

reflashViewByState();

}

break;

case PULL:

topPadding(topPadding);

if (space > headerHeight + 30 && scrollState == SCROLL_STATE_TOUCH_SCROLL) {// 如果正在滚动切超过30

state = RELESE;

reflashViewByState();

}

break;

case RELESE:

topPadding(topPadding);

if (space < headerHeight + 30) {

state = PULL;

reflashViewByState();

} else if (space <= 0) {

state = NONE;

isRemark = false;

reflashViewByState();

}

break;

}

}



/**

* 根据当前状态,改变界面显示;

*/

private void reflashViewByState() {

TextView tip = (TextView) header.findViewById(R.id.tip);

ImageView arrow = (ImageView) header.findViewById(R.id.arrow);

ProgressBar progress = (ProgressBar) header.findViewById(R.id.progress);

RotateAnimation anim = new RotateAnimation(0, 180, RotateAnimation.RELATIVE_TO_SELF, 0.5f,

RotateAnimation.RELATIVE_TO_SELF, 0.5f);

anim.setDuration(500);

anim.setFillAfter(true);

RotateAnimation anim1 = new RotateAnimation(180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f,

RotateAnimation.RELATIVE_TO_SELF, 0.5f);

anim1.setDuration(500);

anim1.setFillAfter(true);

/**

* 四种状态

*/

switch (state) {

case NONE:

arrow.clearAnimation();

topPadding(-headerHeight);

break;



case PULL:

arrow.setVisibility(View.VISIBLE);

progress.setVisibility(View.GONE);

tip.setText("下拉可以刷新!");

arrow.clearAnimation();

arrow.setAnimation(anim1);

break;

case RELESE:

arrow.setVisibility(View.VISIBLE);

progress.setVisibility(View.GONE);

tip.setText("松开可以刷新!");

arrow.clearAnimation();

arrow.setAnimation(anim);

break;

case REFLASHING:

topPadding(50);

arrow.setVisibility(View.GONE);

progress.setVisibility(View.VISIBLE);

tip.setText("正在刷新...");

arrow.clearAnimation();

break;

}

}



/**

* 获取完数据;

*/

public void reflashComplete() {

state = NONE;

isRemark = false;

reflashViewByState();

TextView lastupdatetime = (TextView) header.findViewById(R.id.lastupdate_time);

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

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

String time = format.format(date);

lastupdatetime.setText(time);

}

}

这里我们定义了四种状态:

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

final int PULL = 1;// 提示下拉状态;(下拉距离比较短,此时松开不刷新)

final int RELESE = 2;// 提示释放状态;(下拉距离较长,此时松开刷新)

final int REFLASHING = 3;// 刷新状态;(松开状态,正在刷新)

这四种状态决定了header布局的不同展示效果,具体由reflashViewByState()方法实现。

onMove()方法通过判断移动过程,实现四种状态之间的转换。

[java] view
plaincopy

package com.example.listviewscrolldemo;



import java.util.ArrayList;

import java.util.List;



import com.example.listviewscrolldemo.LoadListView.ILoadListener;

import com.example.listviewscrolldemo.LoadListView.RLoadListener;



import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.widget.ArrayAdapter;



public class MainActivity extends Activity implements ILoadListener, RLoadListener {

private LoadListView mListView;

private ArrayAdapter<String> adapter;

private List<String> datas;



@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initViews();

initDatas();

}



private void initDatas() {

for (int i = 1; i < 21; i++) {

datas.add("数据" + i + "");

}



}



private void initMoreDatas() {

for (int i = 1; i < 3; i++) {

datas.add("新数据" + i + "");

}



}



private void initViews() {

mListView = (LoadListView) findViewById(R.id.lv_main);

mListView.setInterface(this);

mListView.setRefreshInterface(this);

datas = new ArrayList<String>();

adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, datas);

// adapter=new

// ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1);

mListView.setAdapter(adapter);

}



@Override

public void onLoad() {

// 添加延时效果

Handler handler = new Handler();

handler.postDelayed(new Runnable() {

public void run() {



initMoreDatas();// 获取更多数据

adapter.notifyDataSetChanged();// 刷新ListView

mListView.loadCompleted();// 隐藏加载提示

}

}, 2000);



}



@Override

public void onRefresh() {

// 添加延时效果

Handler handler = new Handler();

handler.postDelayed(new Runnable() {

public void run() {



initRefreshDatas();// 获取更多数据

adapter.notifyDataSetChanged();// 刷新ListView

mListView.reflashComplete();// 隐藏刷新提示

}



}, 2000);

}



private void initRefreshDatas() {

// datas.add("新数据" + i + "");

datas.add(0, "下拉刷新数据" + 1 + "");//此方法插入表头

datas.add(0, "下拉刷新数据" + 2 + "");

}



}

运行本实例如下:



源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: