Android自定义之高仿淘宝下拉刷新

简介: Android自定义之高仿淘宝下拉刷新

概述

目前下拉刷新的样式是多饰多样,今天我们一起来自定义淘宝下拉刷新,其实淘宝下拉刷新比较的简单就是一个圆环和一个小箭头的显示和隐藏,那么先看看我们的实现的效果。

是不是和淘宝有点像呢?那么现在我们来看看如何实现这个效果。我们这里为了省事,提供了2张照片  第一是“随时随地,想淘就淘”的照片,第二种就是小箭头照片,这里就自己画了,主要就是实现那个圆弧的绘制和旋转动画了。首先说这里的下拉刷新我用的是比较有名的 https://github.com/chrisbanes/Android-PullToRefresh 这个大家肯定很熟悉了,这里我修改了这个库可以自定义头部和底部,如果有兴趣的可以看下直通车链接 https://github.com/dalong982242260/AndroidPullToRefresh

步骤:

1、自定义一个view。(包含圆弧的绘制和箭头的显示和隐藏)

2、自定义头部。


  1、创建attrs文件

 <declare-styleable name="TaoBaoView">
        <attr name="ringProgressColor" format="color" />
        <attr name="ringWidth" format="dimension" />
        <attr name="ringImage" format="reference" />
        <attr name="ringmax" format="integer" />
    </declare-styleable>

2、 创建一个类 TaoBaoView.class

public class TaoBaoView extends View{
 
 
    //圆环进度颜色
    private int ringProgressColor;
 
    //圆环的宽度
    private float ringWidth;
 
    //最大值
    private int ringMax;
 
    //中间的icon
    private Bitmap ringImage;
 
    //中间X坐标
    private int  centerX;
 
    //中间Y坐标
    private int  centerY;
 
    //画笔
    private Paint mPaint;
 
    //View宽度
    private int width;
 
    //View高度
    private int height;
 
    //进度
    private int progress;
 
    //半径
    private int radius;
 
    //是否显示图标
    private boolean isShowIcon=true;
 
 
    public TaoBaoView(Context context) {
        this(context,null);
    }
 
    public TaoBaoView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
 
    public TaoBaoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.TaoBaoView);
        ringProgressColor=typedArray.getColor(R.styleable.TaoBaoView_ringProgressColor, Color.GRAY);
        ringWidth=typedArray.getDimension(R.styleable.TaoBaoView_ringWidth, 5);
        ringMax=typedArray.getInteger(R.styleable.TaoBaoView_ringmax, 50);
        ringImage= BitmapFactory.decodeResource(getResources(),
                typedArray.getResourceId(R.styleable.TaoBaoView_ringImage,R.mipmap.jiantou));
        init();
 
    }
 
    private void init() {
        mPaint=new Paint();
    }
 
 
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);
        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int heightSize=MeasureSpec.getSize(heightMeasureSpec);
 
        if(widthMode==MeasureSpec.AT_MOST)width=dp2px(30);
        else width=widthSize;
        if(heightMode==MeasureSpec.AT_MOST)height=dp2px(30);
        else height=heightSize;
        setMeasuredDimension(width,height);
    }
 
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        //获取中心点的位置
        centerX=getWidth()/2;
        centerY=getHeight()/2;
        radius=(int) (centerX - ringWidth / 2);
    }
 
 
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //确定View的宽高
        width = w;
        height = h;
    }
 
    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
 
        drawProgress(canvas);
        drawImage(canvas);
    }
 
    /**
     * 绘制图片
     * @param canvas
     */
    private void drawImage(Canvas canvas) {
        if(isShowIcon)
        canvas.drawBitmap(ringImage,centerX-ringImage.getWidth()/2,centerY-ringImage.getHeight()/2,mPaint);
    }
 
    /**
     * 绘制进度条
     * @param canvas
     */
    private void drawProgress(Canvas canvas) {
 
        mPaint.setAntiAlias(true);
        mPaint.setColor(ringProgressColor);
        mPaint.setStrokeWidth(ringWidth);
        //设置画笔样式
        mPaint.setStyle(Paint.Style.STROKE);
        RectF rectF=new RectF(centerX-radius,centerY-radius,centerX+radius,centerY+radius);
        //绘制圆弧
        canvas.drawArc(rectF,-110,-360*progress/ringMax,false,mPaint);
    }
 
 
    /**
     * dp转px
     * @param dp
     * @return
     */
    public int dp2px(int dp){
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dp * density + 0.5f);
    }
 
 
    /**
     * 设置进度
     * @param progress
     */
    public  synchronized  void setProgress(int progress){
        if(progress<0){
            progress=0;
        }
        if(progress>=ringMax){
            progress=ringMax;
        }
        this.progress=progress;
        postInvalidate();
    }
 
 
    /**
     * 设置是否显示图标
     * @param isShow
     */
    public  synchronized  void setIsShowIcon(boolean isShow){
        this.isShowIcon=isShow;
    }
}

3、创建一个headerLayout  下拉刷新头部

public class HeaderLayout extends LoadingLayoutBase {
 
    private  Context mContext;
    private  RotateAnimation refreshingAnimation;
    private  TextView ring_refresh_status;
    private  TaoBaoView mTaoBaoView;
    private  LinearLayout header_base;
    private LinearLayout header_layout;
 
    public HeaderLayout(Context context) {
        this(context, PullToRefreshBase.Mode.PULL_FROM_START);
    }
 
    public HeaderLayout(Context context, PullToRefreshBase.Mode mode) {
        super(context);
        init(context,mode);
    }
 
    private void init(Context mContext,PullToRefreshBase.Mode mode) {
        this.mContext=mContext;
        LayoutInflater.from(mContext).inflate(R.layout.taobao_view, this);
        header_base=(LinearLayout)findViewById(R.id.header_base);
        header_layout=(LinearLayout)findViewById(R.id.refresh_header_content);
        mTaoBaoView=(TaoBaoView)findViewById(R.id.taobao_view);
        ring_refresh_status=(TextView)findViewById(R.id.taobao_tv);
        refreshingAnimation = (RotateAnimation) AnimationUtils.loadAnimation(mContext, R.anim.rotating);
        LinearInterpolator lir = new LinearInterpolator();
        refreshingAnimation.setInterpolator(lir);
        mTaoBaoView.setProgress(90);
        LayoutParams lp = (LayoutParams) header_base.getLayoutParams();
        lp.gravity = mode == PullToRefreshBase.Mode.PULL_FROM_END ? Gravity.TOP : Gravity.BOTTOM;
        reset();
    }
 
    @Override
    public int getContentSize() {
        return header_layout.getHeight();
    }
 
    /**
     * 下拉可以刷新
     */
    @Override
    public void pullToRefresh() {
        ring_refresh_status.setText("下拉刷新");
        mTaoBaoView.setIsShowIcon(true);
    }
 
    /**
     * 松开后刷新
     */
    @Override
    public void releaseToRefresh() {
        ring_refresh_status.setText("松开刷新");
        mTaoBaoView.setIsShowIcon(false);
    }
 
    /**
     * 下拉中
     * @param scaleOfLayout scaleOfLayout
     */
    @Override
    public void onPull(float scaleOfLayout) {
        scaleOfLayout = scaleOfLayout > 1.0f ? 1.0f : scaleOfLayout;
        int progress=(int) ((scaleOfLayout)*100);
        mTaoBaoView.setProgress(progress>90?90:progress);
 
    }
 
    /**
     * 正在刷新
     */
    @Override
    public void refreshing() {
        mTaoBaoView.setIsShowIcon(false);
        ring_refresh_status.setText("正在刷新");
        mTaoBaoView.startAnimation(refreshingAnimation);
    }
 
    @Override
    public void reset() {
        mTaoBaoView.clearAnimation();
    }
 
    @Override
    public void setPullLabel(CharSequence pullLabel) {
 
    }
 
    @Override
    public void setRefreshingLabel(CharSequence refreshingLabel) {
 
    }
 
    @Override
    public void setReleaseLabel(CharSequence releaseLabel) {
 
    }
}

4、在mainactivity中:

 mPullToRefreshListView=(PullToRefreshListView)findViewById(R.id.list);
 mPullToRefreshListView.setHeaderLayout(new HeaderLayout(this));

附上github:https://github.com/dalong982242260/TaoBaoRefresh2

相关文章
|
29天前
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
26 1
|
2月前
|
Android开发 开发者
安卓应用开发中的自定义视图
【9月更文挑战第37天】在安卓开发的海洋中,自定义视图犹如一座座小岛,等待着勇敢的探索者去发现其独特之处。本文将带领你踏上这段旅程,从浅滩走向深海,逐步揭开自定义视图的神秘面纱。
44 3
|
4月前
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
87 2
基于Android P,自定义Android开机动画的方法
|
2月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
95 0
|
4月前
|
供应链 物联网 区块链
未来触手可及:探索新兴技术的趋势与应用安卓开发中的自定义视图:从基础到进阶
【8月更文挑战第30天】随着科技的飞速发展,新兴技术如区块链、物联网和虚拟现实正在重塑我们的世界。本文将深入探讨这些技术的发展趋势和应用场景,带你领略未来的可能性。
|
4月前
|
测试技术 Android开发 Python
探索软件测试的艺术:从基础到高级安卓应用开发中的自定义视图
【8月更文挑战第29天】在软件开发的世界中,测试是不可或缺的一环。它如同艺术一般,需要精细的技巧和深厚的知识。本文旨在通过浅显易懂的语言,引领读者从软件测试的基础出发,逐步深入到更复杂的测试策略和工具的使用,最终达到能够独立进行高效测试的水平。我们将一起探索如何通过不同的测试方法来确保软件的质量和性能,就像艺术家通过不同的色彩和笔触来完成一幅画作一样。
|
1月前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
1月前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
37 5
|
2月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
3月前
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
69 10