经过前几篇的listview下拉刷新上拉加载讲解,相信你对其实现机制有了一个深刻的认识了吧,那么这篇文章我们来实现一个高级的listview下拉刷新上拉加载-仿新版美团外卖的袋鼠动画:

项目结构:

是不是灰常简单!!

headview的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="match_parent"
    android:gravity="center"
    android:orientation="horizontal">

    <com.baiyuliang.listviewrefreshdemo.RefreshAnimView
        android:id="@+id/refreshAnimView"
        android:layout_width="59dp"
        android:layout_height="70dp"
        android:layout_margin="10dp"/>

    <ProgressBar
        android:id="@+id/pb"
        android:layout_width="59dp"
        android:layout_height="70dp"
        android:layout_margin="10dp"
        android:indeterminateDrawable="@drawable/loading"
        android:visibility="gone"/>

</LinearLayout>

自定义可缩放的View:

package com.baiyuliang.listviewrefreshdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class RefreshAnimView extends View{

    private Bitmap daishu;
    private int measuredWidth;
    private int measuredHeight;
    private float mCurrentProgress;
    private int mCurrentAlpha;
    private Paint mPaint;
    private Bitmap scaleDaishu;

    public RefreshAnimView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

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

    public RefreshAnimView(Context context) {
        super(context);
        init();
    }
    private void init(){
        //袋鼠bitmap
        daishu = BitmapFactory.decodeResource(getResources(), R.mipmap.takeout_img_list_loading_pic1);
        //mPaint.setAlpha来实现渐变效果
        mPaint = new Paint();
        //首先设置为完全透明
        mPaint.setAlpha(0);
    }

    /**
     * 测量方法
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }
    //测量宽度
    private int measureWidth(int widthMeasureSpec){
        int result = 0;
        int size = MeasureSpec.getSize(widthMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        if (MeasureSpec.EXACTLY == mode) {
            result = size;
        }else {
            result = daishu.getWidth();
            if (MeasureSpec.AT_MOST == mode) {
                result = Math.min(result, size);
            }
        }
        return result;
    }
    //测量高度
    private int measureHeight(int heightMeasureSpec){
        int result = 0;
        int size = MeasureSpec.getSize(heightMeasureSpec);
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        if (MeasureSpec.EXACTLY == mode) {
            result = size;
        }else {
            result = daishu.getHeight();
            if (MeasureSpec.AT_MOST == mode) {
                result = Math.min(result, size);
            }
        }
        return result;
    }
    //在这里面拿到测量后的宽和高,w就是测量后的宽,h是测量后的高
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        measuredWidth = w;
        measuredHeight = h;
        //根据测量后的宽高来对袋鼠做一个缩放
        scaleDaishu = Bitmap.createScaledBitmap(daishu,measuredWidth,measuredHeight,true);
    }

    /**
     * 绘制方法
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.scale(mCurrentProgress, mCurrentProgress, measuredWidth/2, measuredHeight);
        mPaint.setAlpha(mCurrentAlpha);
        canvas.drawBitmap(scaleDaishu, 0, 0, mPaint);
    }

    /**
     * 根据进度对袋鼠进行缩放
     * @param currentProgress
     */
    public void setCurrentProgress(float currentProgress){
        this.mCurrentProgress = currentProgress;
        this.mCurrentAlpha = (int) (currentProgress*255);
    }
}

在listview中的onTouch事件中将手指下拉滑动距离与headview的高度比传递给RefreshAnimView 重绘,以实现图片根据手指移动来缩放图片:

 case MotionEvent.ACTION_MOVE:
                offsetY = ev.getY() - startY;
                /**
                 * 下拉刷新
                 */
                if (isRefreshable &&offsetY > 0 && loadstate == LOAD_DONE && isScrollFirst && refreshstate != REFRESHING) {
                    float headerViewShowHeight = offsetY / REFRESH_RATIO;
                    float scaleProgress=headerViewShowHeight/headerViewHeight;//图片放大缩小比例
                    if(scaleProgress>1){
                        scaleProgress=1;
                    }
......

     if (refreshstate == PULL_TO_REFRESH || refreshstate == RELEASE_TO_REFRESH) {
                        headerView.setPadding(0, (int) (headerViewShowHeight - headerViewHeight), 0, 0);
                        refreshAnimView.setCurrentProgress(scaleProgress);//设置refreshAnimView的缩放进度
                        refreshAnimView.invalidate();//重绘
                    }

根据刷新状态实时更新headview:

 private void changeHeaderByState(int state) {
        switch (state) {
            case REFRESH_DONE:
                headerView.setPadding(0, -headerViewHeight, 0, 0);
                refreshAnimView.setVisibility(View.VISIBLE);
                pb.setVisibility(View.GONE);
                break;
            case RELEASE_TO_REFRESH:
                break;
            case PULL_TO_REFRESH:
                break;
            case REFRESHING:
                headerView.setPadding(0, 0, 0, 0);
                refreshAnimView.setVisibility(View.GONE);
                pb.setVisibility(View.VISIBLE);
                break;
            default:
                break;
        }
    }

PS:如何快速简单的实现一个帧动画?

利用ProgressBar的indeterminateDrawable属性,定义一个animation-list,也是灰常简单:

    <ProgressBar
        android:id="@+id/pb"
        android:layout_width="59dp"
        android:layout_height="70dp"
        android:layout_margin="10dp"
        android:indeterminateDrawable="@drawable/loading"
        android:visibility="gone"/>

loadding.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">

    <item android:duration="50">
        <clip
            android:clipOrientation="horizontal"
            android:drawable="@mipmap/takeout_img_list_loading_pic1"
            android:gravity="left" />
    </item>
    <item android:duration="50">
        <clip
            android:clipOrientation="horizontal"
            android:drawable="@mipmap/takeout_img_list_loading_pic2"
            android:gravity="left" />
    </item>

</animation-list>

好了,如果你还是那么懒,不想动手,demo给你:http://download.csdn.net/detail/baiyuliang2013/9344831

listview下拉刷新上拉加载扩展(二)-仿美团外卖的更多相关文章

  1. Android 下拉刷新上啦加载SmartRefreshLayout + RecyclerView

    在弄android刷新的时候,可算是耗费了一番功夫,最后发觉有现成的控件,并且非常好用,这里记录一下. 原文是 https://blog.csdn.net/huangxin112/article/de ...

  2. SwipeRefreshLayout实现下拉刷新上滑加载

    1. 效果图 2.RefreshLayout.java package myapplication.com.myapplication; import android.content.Context; ...

  3. 移动端下拉刷新上拉加载-mescroll.js插件

    最近无意间看到有这么一个上拉刷新下拉加载的插件 -- mescroll.js,个人感觉挺好用的,官网地址是:http://www.mescroll.com 然后我就看了一下文档,简单的写了一个小dem ...

  4. ListView实现Item上下拖动交换位置 并且实现下拉刷新 上拉加载更多

    ListView实现Item上下拖动交换位置  并且实现下拉刷新  上拉加载更多 package com.example.ListViewDragItem; import android.app.Ac ...

  5. ListView下拉刷新上拉加载更多实现

    这篇文章将带大家了解listview下拉刷新和上拉加载更多的实现过程,先看效果(注:图片中listview中的阴影可以加上属性android:fadingEdge="none"去掉 ...

  6. listview下拉刷新上拉加载扩展(三)-仿最新版美团外卖

    本篇是基于上篇listview下拉刷新上拉加载扩展(二)-仿美团外卖改造而来,主要调整了headview的布局,并加了两个背景动画,看似高大上,其实很简单: as源码地址:http://downloa ...

  7. MaterialRefreshLayout+ListView 下拉刷新 上拉加载

    效果图是这样的,有入侵式的,非入侵式的,带波浪效果的......就那几个属性,都给出来了,自己去试就行. 下拉刷新 上拉加载 关于下拉刷新-上拉加载的效果,有许许多多的实现方式,百度了一下竟然有几十种 ...

  8. react-native-page-listview使用方法(自定义FlatList/ListView下拉刷新,上拉加载更多,方便的实现分页)

    react-native-page-listview 对ListView/FlatList的封装,可以很方便的分页加载网络数据,还支持自定义下拉刷新View和上拉加载更多的View.兼容高版本Flat ...

  9. 自定义ListView下拉刷新上拉加载更多

    自定义ListView下拉刷新上拉加载更多 自定义RecyclerView下拉刷新上拉加载更多 Listview现在用的很少了,基本都是使用Recycleview,但是不得不说Listview具有划时 ...

随机推荐

  1. 在Spring Boot中使用Spring Security实现权限控制

    丢代码地址 https://gitee.com/a247292980/spring-security 再丢pom.xml <properties> <project.build.so ...

  2. js原生获取元素的css属性

    习惯了用jQuery的css()的方法获取元素的css属性,突然不用jquery了,当要获得元素的css时候,我瞬间停顿了一下,咦?咋获取元素的css值?比如获取元素的width.是这样么?docum ...

  3. 58. Length of Last Word(easy, 字符串问题)

    Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...

  4. API说明书规范

    目录 1       前言 1.1         编写目的 1.2        预期读者 1.3         关于API设计开发 2       API公共说明 3       文档API索引 ...

  5. vue--"卡片层叠" 组件 开发小记

    背景:影城移动点餐web App增加会员卡支付功能 需求:确认订单页点击会员卡项弹出会员卡列表,多张会员卡依次叠加覆盖上一张80%的高度,点击任意卡片则改卡片置为当前卡片,只有当前卡片显示全部卡片信息 ...

  6. Pickle模块数据对象持久化操作

    Pickle模块的作用是持久化(序列化)的储存数据.因此我先解释下:什么是序列化与反序列化.什么是对象序列化和对象反序列化.通俗地讲,它们的定义如下:序列化: 把一个对象保存到一个文件或数据库字段中去 ...

  7. 转:rabbitMQ 安装与管理

    安装环境 虚拟机:VMware® Workstation 10.0.1 build Linux系统:CentOS6.5 官方安装:http://www.rabbitmq.com/install-rpm ...

  8. 利用JAVA多线程来提高数据处理效率

    肿瘤大数据挖掘中经常需要处理上百亿行的文本文件,这些文件往往高达数百GB,假如文件结构简单统一,那么用sed和awk 处理是非常方便和快速的.但有时候会遇到逻辑较为复杂的处理流程,这样我一般会用JAV ...

  9. Go 语言条件语句

    条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句. 下图展示了程序语言中条件语句的结构: Go 语言提供 ...

  10. Unity3D开发注意事项

    最近给组里定Unity开发注意事项,参考了@陆泽西在群里分享的[前端开发规范],结合自己工作中的经验,整理一下,下面不少条款都是我们要求在开发中必须遵守的. 资源: 图片统一为png格式,纹理属性:T ...