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

开源RefreshListView下拉刷新效果

2016-05-23 17:11 561 查看
1、AnimationDrawable

java.lang.Object
   ↳android.graphics.drawable.Drawable
    ↳android.graphics.drawable.DrawableContainer
     ↳android.graphics.drawable.AnimationDrawable
文档概述:
An object used to create frame-by-frame animations, defined by a series of Drawable objects, which can be used as a View object's background.

An AnimationDrawable defined in XML consists of a single
<animation-list>
element, and a series of nested
<item>
tags. Each item defines a frame of the animation. See the example below. 

<!-- Animation frames are wheel0.png -- wheel5.png files inside the
res/drawable/ folder -->
<animation-list android:id="@+id/selected" android:oneshot="false">
<item android:drawable="@drawable/wheel0" android:duration="50" />
<item android:drawable="@drawable/wheel1" android:duration="50" />
<item android:drawable="@drawable/wheel2" android:duration="50" />
<item android:drawable="@drawable/wheel3" android:duration="50" />
<item android:drawable="@drawable/wheel4" android:duration="50" />
<item android:drawable="@drawable/wheel5" android:duration="50" />
</animation-list>

Here is the code to load and play this animation.
// Load the ImageView that will host the animation and
// set its background to our AnimationDrawable XML resource.
ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
img.setBackgroundResource(R.drawable.spin_animation);

// Get the background, which has been compiled to an AnimationDrawable object.
AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();

// Start the animation (looped playback by default).
frameAnimation.start();

https://github.com/FlyRecker/FlyMukeRefreshListView GitHub开源项目:仿慕课下拉刷新



RefreshListView.java 

package com.example.openrefreshlistview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
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.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

/**
* Created by recker on 16/5/13.
*/
public class RefreshListView extends ListView implements AbsListView.OnScrollListener {

private final int NONE = 0;//正常状态
private final int PULL = 1;//提示下拉刷新状态
private final int RELESE = 2;//提示释放状态
private final int REFLASHING = 3;//正在刷新状态
private final int RATIO = 3;//比值

private View headerView;//顶部刷新视图
private int headerViewHeight;//顶部布局文件的高度
private int firstVisibleItem;//当前第一个可见的item的位置

private boolean isEnd;//是否结束刷新
private boolean isRefreable;//是否可以刷新
private boolean isRemark;//标记,当前是在ListView是否是在第一个
private float startY;
private float offsetY;
private int state;//当前的状态

private TextView tip;
private ImageView img;
private AnimationDrawable drawableAnim;

public RefreshListView(Context context) {
super(context);
init(context);
}

public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}

@SuppressLint("NewApi")
private void init(Context context) {
headerView = LayoutInflater.from(context).inflate(R.layout.header_layout, null);

/*void android.widget.ListView.addHeaderView(View v)
Add a fixed view to appear at the top of the list.
*/
addHeaderView(headerView);
measureView(headerView);
headerViewHeight = headerView.getMeasuredHeight();
topPadding(-headerViewHeight);

//添加动画
tip = (TextView) headerView.findViewById(R.id.tip);
img = (ImageView) headerView.findViewById(R.id.img);
img.setBackgroundResource(R.drawable.c);
drawableAnim = (AnimationDrawable) img.getBackground();

//关闭view的OverScroll
setOverScrollMode(OVER_SCROLL_NEVER);
setOnScrollListener(this);
state = NONE;
isEnd = true;
isRefreable = false;

}

/**
* 通知父布局,占用的宽,高
* @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);
}

private void topPadding(int topPadding) {
headerView.setPadding(headerView.getPaddingLeft(), topPadding,
headerView.getPaddingRight(), headerView.getPaddingBottom());
headerView.invalidate();
}

@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {

}

@Override
public void onScroll(AbsListView absListView, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.firstVisibleItem = firstVisibleItem;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {

if (isEnd) {//如果现在时结束的状态,即刷新完毕了,可以再次刷新了,在refreshComplete中设置
if (isRefreable) {//如果现在是可刷新状态   在setOnRefreshListener中设置为true
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
if (firstVisibleItem == 0 && !isRemark) {
isRemark = true;
startY = ev.getY();
}
break;
case MotionEvent.ACTION_MOVE:
onMove(ev);
break;
case MotionEvent.ACTION_UP:
if (state == RELESE) {
state = REFLASHING;
//加载最新数据
refreshViewByState();
onRefreshListener.onRefresh();
} else if (state == PULL) {
state = NONE;
refreshViewByState();
setSelection(0);
}
isRemark = false;
break;
}
}
}

return super.onTouchEvent(ev);
}

/**
* 判断移动过程操作
* @param ev
*/
private void onMove(MotionEvent ev) {

//再次得到y坐标,用来和startY相减来计算offsetY位移值
float tempY = ev.getY();
//再起判断一下是否为listview顶部并且没有记录y坐标
if (firstVisibleItem == 0 && !isRemark) {
isRemark = true;
startY = tempY;
}

if (state != REFLASHING && isRemark) {
//计算y的偏移量
offsetY = tempY - startY;
//计算当前滑动的高度
float currentHeight = (-headerViewHeight+offsetY/3);

//如果当前的状态是释放刷新,并且已经记录y坐标
if (state == RELESE && isRemark) {
setSelection(0);
//如果当前滑动的距离小于headerView的总高度
if (-headerViewHeight+offsetY/RATIO<0) {
//状态改为下拉刷新
state = PULL;
refreshViewByState();
} else if (offsetY <= 0) {//如果当前y的位移值小于0,即为headerView隐藏了
//状态改为正常状态
state = NONE;
refreshViewByState();
}
}
//如果当前状态为下拉刷新并且已经记录y坐标
if (state == PULL &&a
b6ab
mp; isRemark) {
setSelection(0);
//如果下拉距离大于等于headerView的总高度
if (-headerViewHeight+offsetY/RATIO>=0) {
//状态改为释放刷新
state = RELESE;
refreshViewByState();
} else if (offsetY <= 0) {//如果当前y的位移值小于0,即为headerView隐藏了
//状态改为正常状态
state = NONE;
refreshViewByState();
}
}
//如果当前状态为正常并且已经记录y坐标
if (state == NONE && isRemark) {
//如果位移值大于0
if (offsetY>=0) {
//将状态改为释放刷新状态
state = PULL;
refreshViewByState();
}
}
//如果为下拉刷新状态
if (state == PULL) {
topPadding((int)(-headerViewHeight+offsetY/RATIO));
}
//如果为释放刷新状态
if (state == RELESE) {
topPadding((int)(-headerViewHeight+offsetY/RATIO));
}

}
}

/**
* 根据当前状态,改变界面显示
*/
private void refreshViewByState() {
switch (state) {
case NONE:
topPadding(-headerViewHeight);
drawableAnim.stop();
break;
case PULL:
drawableAnim.stop();
tip.setText("下拉刷新");
break;
case RELESE:
drawableAnim.stop();
tip.setText("释放刷新");
break;
case REFLASHING:
drawableAnim.start();
tip.setText("正在刷新");
break;
}
}

/**
* 获取完数据
*/
public void refreshComplete() {
isEnd = true;
state = NONE;

refreshViewByState();
}

private OnRefreshListener onRefreshListener;

public void setOnRefreshListener(OnRefreshListener listener) {
this.onRefreshListener = listener;
isRefreable = true;
}

public interface OnRefreshListener {
void onRefresh();
}

private void debug(String str) {
Log.d(RefreshListView.class.getSimpleName(), str);
}
}


header_layout.xml
<?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"
android:background="@android:color/white">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal"
android:paddingBottom="20dp"
android:paddingTop="12dp">
<ImageView
android:id="@+id/img"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/head_image_0"
android:layout_marginRight="5dp"/>

<TextView
android:id="@+id/tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="下拉刷新"
android:textSize="12sp"
android:layout_marginTop="5dp"
android:layout_marginLeft="5dp"
android:layout_gravity="center_vertical"/>
</LinearLayout>

</LinearLayout>


activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.example.openrefreshlistview.RefreshListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"/>
</RelativeLayout>


MainActivity.java
package com.example.openrefreshlistview;

import android.os.Handler;
//import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.ArrayAdapter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MainActivity extends ActionBarActivity
implements RefreshListView.OnRefreshListener  {

private RefreshListView mListView;
private List<String> mDatas;
private ArrayAdapter<String> mAdapter;

private final static int REFRESH_COMPLETE = 0;

private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case REFRESH_COMPLETE:
mListView.refreshComplete();
mAdapter.notifyDataSetChanged();
break;

default:
break;
}
};
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mListView = (RefreshListView) findViewById(R.id.listview);
String[] data = new String[]{"a","b","c","d",
"e","f","g","h","i",
"j","k","l","m","n","o","p","q","r","s"};
mDatas = new ArrayList<String>(Arrays.asList(data));
/*Open Declaration android.widget.ArrayAdapter.ArrayAdapter<String>(Context context,
int textViewResourceId, List<String> objects)*/
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,mDatas);
mListView.setAdapter(mAdapter);
mListView.setOnRefreshListener(this);

}

@Override
public void onRefresh() {
new Thread(new Runnable() {

@Override
public void run() {
try {
Thread.sleep(3000);
mDatas.add(0, "new data");
mHandler.sendEmptyMessage(REFRESH_COMPLETE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}

}


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