仿美团下拉刷新效果(大众点评下拉刷新吃包子的效果也可以这么实现)
仿美团下拉刷新效果(大众点评下拉刷新吃包子的效果也可以这么实现)
虽然现在有很多的下拉刷新的开源框架可以使用,并且使用起来也都是很方便。但是如果想要修改下拉刷新的显示效果,可能用那些开源框架实现起来就不是那么方便。
并且在出去面试的时候,如果被人问道下拉刷新你是怎么做的,如果你告诉别人你是用的第三方的框架,那么对你的面试并没有什么好处,而且不利于你找到高薪的 工作,但是如果,你说是自己写的,那你找工作成功的几率就会大很多,而且找到高薪的工作的可能性也会更大。
所以本文就采用自己实现的方式,实现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;
- }
- });
- }
- }