虽然现在有很多的下拉刷新的开源框架可以使用,并且使用起来也都是很方便。但是如果想要修改下拉刷新的显示效果,可能用那些开源框架实现起来就不是那么方便。
并且在出去面试的时候,如果被人问道下拉刷新你是怎么做的,如果你告诉别人你是用的第三方的框架,那么对你的面试并没有什么好处,而且不利于你找到高薪的工作,但是如果,你说是自己写的,那你找工作成功的几率就会大很多,而且找到高薪的工作的可能性也会更大。
所以本文就采用自己实现的方式,实现ListView的下拉刷新,并且添加仿美团的刷新展示效果,先上效果图:
实现原理:
布局
整体的容器时使用相对布局,下层是放置了一个ImageView用于显示美团的小人,上层是放置了一个ListView(其实也可以放置别的View,看你的需要了)。下面看一下布局文件内容:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/con"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--顶部拉出来的视图-->
<ImageView
android:id="@+id/refresh_img"
android:src="@mipmap/pull_image"
android:layout_marginTop="10dp"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/list"
android:background="@android:color/white"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="@array/content" />
</RelativeLayout>
然后是代码,代码里注释比较详细,这里就不在用文字进行描述了,直接看代码吧,如果看不懂可以留言。代码:
package com.libin.lbrefresh;
import android.graphics.drawable.AnimationDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;
/**
* MotionEvent
* 1、getY() 换算过后基于View的Y坐标
* 2、getRawY() 不经处理基于屏幕的Y坐标
*/
public class MainActivity extends AppCompatActivity {
private ListView listView;
private float startPX;//触摸的开始点坐标
private int startTopMargin;//ListView的原始上边距
private RelativeLayout.LayoutParams params;
private ImageView refreshImg;
private int topMargin;//随手指滑动计算的上边距(即下拉的距离)
private AnimationDrawable drawable;
private static final int PULL_DISTANCE = 400;//下拉刷新的触发距离
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int what = msg.what;
//刷新结束后,复原ListView
if(what == 100){
drawable.stop();
params.topMargin = startTopMargin;
listView.setLayoutParams(params);
refreshImg.setImageResource(R.mipmap.pull_image);
Toast.makeText(MainActivity.this,"刷新成功",Toast.LENGTH_SHORT).show();
/*
这里有一段更新ListView数据的代码,就是notifyDatasetChanged()等等
*/
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list);
refreshImg = (ImageView) findViewById(R.id.refresh_img);
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
//记录手指初始触摸点的坐标
startPX = event.getRawY();
//记录ListView初始的上边距
params = (RelativeLayout.LayoutParams) listView.getLayoutParams();
startTopMargin = params.topMargin;
break;
case MotionEvent.ACTION_MOVE:
//计算手指在屏幕上滑动过的距离
topMargin = (int) (event.getRawY() - startPX);
//判断是否达到触发刷新的距离
if(topMargin < PULL_DISTANCE && topMargin > 0){
params.topMargin = topMargin;
listView.setLayoutParams(params);
}
if(Build.VERSION.SDK_INT >= 11){
float fraction = topMargin * 1.0f / PULL_DISTANCE;
//缩放下拉提示小人
if(fraction <= 1){
refreshImg.setScaleX(fraction);
refreshImg.setScaleY(fraction);
}
//放出小人
else if(fraction > 1 && fraction <=1.1){
refreshImg.setImageResource(R.mipmap.pull_end_image_frame_01);
}else if(fraction > 1.1 && fraction <=1.2){
refreshImg.setImageResource(R.mipmap.pull_end_image_frame_02);
}else if(fraction > 1.2 && fraction <= 1.3){
refreshImg.setImageResource(R.mipmap.pull_end_image_frame_03);
}else if(fraction > 1.3 && fraction <= 1.4){
refreshImg.setImageResource(R.mipmap.pull_end_image_frame_04);
}else{
refreshImg.setImageResource(R.mipmap.pull_end_image_frame_05);
}
}
break;
case MotionEvent.ACTION_UP:
//未触发刷新
if(topMargin < PULL_DISTANCE){
refreshImg.setImageResource(R.mipmap.pull_image);
params.topMargin = startTopMargin;
listView.setLayoutParams(params);
}
//触发刷新(这是关键点)
else{
refreshImg.setImageResource(R.drawable.refresh);
drawable = (AnimationDrawable) refreshImg.getDrawable();
drawable.start();
//执行刷新功能,一般是网络请求
new Thread(
new Runnable() {
@Override
public void run() {
//这里添加网络请求的代码,不过因为这不是刷新的关键,故用阻塞线程模拟网络请求用了3秒
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//请求完毕,处理小人
handler.sendEmptyMessage(100);
}
}
).start();
}
//提示刷新
float deltaY = event.getRawY() - startPX;
if (deltaY > PULL_DISTANCE){
Toast.makeText(MainActivity.this,"正在刷新...",Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
return false;
}
});
}
}