android 自定义view实现应用宝进度条下载效果

Android自定义View-矩形圆角进度条 参考 Android Canvas 绘制 剪切 clip 与 几何变换 Android Canvas绘图详解(图文) 阅读详情

这个有好多种做法,我就讲二种方法,第一种方法就是自定义一个view,通过canvas画线就可以,只要把paint的width改成view的高度就行:

package com.day01;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.math.BigDecimal;

/**
 * Created by zhouguizhijxhz on 2018/5/24.
 */
public class CustomProgress extends View implements View.OnClickListener {
    private Paint defaultPaint;
    private Paint rollPaint;
    private float percent = 0.0f;
    private Paint textPaint;
    private Handler mHandler = new Handler();
    private MyRunnable myRunnable;
    public CustomProgress(Context context) {
        this(context, null);
    }

    public CustomProgress(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        myRunnable = new MyRunnable();
        initPaint();
        setOnClickListener(this);
    }

    private void initPaint() {
        defaultPaint = new Paint();
        defaultPaint.setColor(Color.parseColor("#999999"));
        defaultPaint.setStyle(Paint.Style.STROKE);


        rollPaint = new Paint();
        rollPaint.setColor(Color.parseColor("#1C86EE"));
        rollPaint.setStyle(Paint.Style.STROKE);

        textPaint = new Paint();
        textPaint.setColor(Color.parseColor("#202020"));
        textPaint.setTextSize(sp2px(15));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int measureHeight(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.AT_MOST) {
            height = 320;
        }
        return height;
    }

    private int measureWidth(int widthMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        if (mode == MeasureSpec.AT_MOST) {
            width = 320;
        }
        return width;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawDefaultProgressButton(canvas);
        drawRollProgressButton(canvas);
        drawText(canvas);
    }

    private void drawText(Canvas canvas) {
        if (null == canvas) {
            return;
        }
        if (percent == 0) {
            String text = "下载";
            Paint.FontMetricsInt fm = textPaint.getFontMetricsInt();
            canvas.drawText(text, getWidth() / 2 - textPaint.measureText(text) / 2,
                    getHeight() / 2 - (fm.bottom + fm.top) / 2, textPaint);
        } else if(percent>0) {
            Log.e("percent","percent------------>"+percent);
            String text = percent*100+ "%";
            Paint.FontMetricsInt fm = textPaint.getFontMetricsInt();
            canvas.drawText(text, getWidth() / 2 - textPaint.measureText(text) / 2,
                    getHeight() / 2 - (fm.bottom + fm.top) / 2, textPaint);
            mHandler.postDelayed(myRunnable,500);
        }
    }

    private void drawRollProgressButton(Canvas canvas) {
        if (null == canvas) {
            return;
        }
        rollPaint.setStrokeWidth(dp2px(getMeasuredHeight()));
        canvas.drawLine(0, 0,  percent*getMeasuredWidth(), 0, rollPaint);
    }

    private void drawDefaultProgressButton(Canvas canvas) {
        if (null == canvas) {
            return;
        }
        defaultPaint.setStrokeWidth(dp2px(getMeasuredHeight()));
        canvas.drawLine(0, 0, getMeasuredWidth(), 0, defaultPaint);
    }

    private int dp2px(float dpValue) {
        float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * px转换成dp
     */
    private int px2dp(float pxValue) {
        float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    public int sp2px(float spValue) {
        final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    @Override
    public void onClick(View v) {
        percent+=0.1f;
        invalidate();
    }
    class MyRunnable implements Runnable{
        @Override
        public void run() {
            if(percent>=1.0){
                return;
            }
            BigDecimal bigDecimal = new BigDecimal(Float.toString(percent));
            BigDecimal bigDecimal1 = new BigDecimal(Float.toString(0.1f));
            percent=bigDecimal.add(bigDecimal1).floatValue();
            postInvalidate();
        }
    }
}

第二种做法:

这个就是绘制矩形,关键是要用到canvas的clipRect()方法,也就是画布裁剪:

package com.day01;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import java.math.BigDecimal;
/**
 * Created by zhouguizhijxhz on 2018/5/24.
 */
public class CustomProgress extends View implements View.OnClickListener {
    private Paint defaultPaint;
    private Paint rollPaint;
    private float percent = 0.0f;
    private Paint textPaint;
    private Handler mHandler = new Handler();
    private MyRunnable myRunnable;
    public CustomProgress(Context context) {
        this(context, null);
    }

    public CustomProgress(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        myRunnable = new MyRunnable();
        initPaint();
        setOnClickListener(this);
    }

    private void initPaint() {
        defaultPaint = new Paint();
        defaultPaint.setColor(Color.parseColor("#999999"));
        defaultPaint.setStyle(Paint.Style.FILL);


        rollPaint = new Paint();
        rollPaint.setColor(Color.parseColor("#1C86EE"));
        rollPaint.setStyle(Paint.Style.FILL);

        textPaint = new Paint();
        textPaint.setColor(Color.parseColor("#202020"));
        textPaint.setTextSize(sp2px(15));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int measureHeight(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.AT_MOST) {
            height = 320;
        }
        return height;
    }

    private int measureWidth(int widthMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        if (mode == MeasureSpec.AT_MOST) {
            width = 320;
        }
        return width;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawDefaultProgressButton(canvas);
        drawRollProgressButton(canvas);
        drawText(canvas);
    }

    private void drawText(Canvas canvas) {
        if (null == canvas) {
            return;
        }
        if (percent == 0) {
            String text = "下载";
            Paint.FontMetricsInt fm = textPaint.getFontMetricsInt();
            canvas.drawText(text, getWidth() / 2 - textPaint.measureText(text) / 2,
                    getHeight() / 2 - (fm.bottom + fm.top) / 2, textPaint);
        } else if(percent>0) {
            BigDecimal re1=new BigDecimal(Float.toString(percent));
            BigDecimal re2=new BigDecimal(Float.toString(100.0f));
            String text = re1.multiply(re2).floatValue()+"%";
            Paint.FontMetricsInt fm = textPaint.getFontMetricsInt();
            canvas.drawText(text, getWidth() / 2 - textPaint.measureText(text) / 2,
                    getHeight() / 2 - (fm.bottom + fm.top) / 2, textPaint);
            mHandler.postDelayed(myRunnable,500);
        }
    }

    private void drawRollProgressButton(Canvas canvas) {
        if (null == canvas) {
            return;
        }
        canvas.save();
        Rect rect = new Rect(0, 0, (int) (percent*getMeasuredWidth()), getMeasuredHeight());
        canvas.clipRect(rect);
        canvas.drawRect(rect,rollPaint);
        canvas.restore();
    }

    private void drawDefaultProgressButton(Canvas canvas) {
        if (null == canvas) {
            return;
        }
        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),defaultPaint);
    }

    private int dp2px(float dpValue) {
        float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * px转换成dp
     */
    private int px2dp(float pxValue) {
        float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    public int sp2px(float spValue) {
        final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    @Override
    public void onClick(View v) {
        percent+=0.1f;
        invalidate();
    }
    class MyRunnable implements Runnable{
        @Override
        public void run() {
            if(percent>=1.0){
                return;
            }
            BigDecimal bigDecimal = new BigDecimal(Float.toString(percent));
            BigDecimal bigDecimal1 = new BigDecimal(Float.toString(0.1f));
            percent=bigDecimal.add(bigDecimal1).floatValue();
            postInvalidate();
        }
    }
}

效果:


如果想要二边有圆形的,就使用第一种方式,而且paint上使用setStrokeCap(Paint.Cap.ROUND)这个方法加上线冒,如果是绘制矩形的这个方法是无效的.

Android 自定义View(四)实现股票自选列表滑动效果 自定义View一、前言二、开发准备工作1、先上效果图2、案例源码下载3、案例应用知识点4、案例思路分析三、代码实现1、自定义 TextView2、自定义 CustomizeScrollView3、主页面布局4、主列表 Adapter四、总结 一、前言 Android 开发过程中自定义 View 真的是无处不在,随随便便一个 UI 效果,都会用到自定义 View。前面三篇文章已经讲过自定义 View 的一些案例效果,相关类和 API,还有事件分发理论知识请自行充电。作者不喜欢讲一些原理性的东西,直接上效果和源 阅读详情

相关推荐

Android 自定义View(二)实现环形进度条

自定义View实现环形进度条一、前言二、实现效果1、源码下载:[点击下载](https://github.com/jaynm888/CustomizeView)2、效果图展示3、步骤分析三、代码实现1、自定义属性2、绘制圆环3、绘制圆弧4、更新进度条5、绘制文本总结 一、前言 Android 自定义 View 是高级进阶不可或缺的内容,日常工作中,经常会遇到产品、UI 设计出花里胡哨的界面。当系统自带的控件不能满足开发需求时,就只能自己动手撸一个效果。 本文就带自定义 View 初学者手动撸一个效果,通过自

一名互联网时代苟且偷生的 Android码农 1249

Android实现下载进度条图标效果

我们在开发中 有时候会遇到 点击一个图标然后进行下载 并且需要在图标上面加上进度条 像下面这样的效果 先说下这个效果的实现,首先我们使用自定义view,在onDraw()方法中使用画笔画出外面的进度条 mPaint.setAntiAlias(true); mPaint.setColor(Color.rgb(0xe9, 0xe9, 0xe9)); c

baidu_33853807的博客 1965

Android 自定义View制作随时间增长的平滑进度条

Android 自定义View制作随时间增长的平滑进度条

nickey_1314 3922

探索JProgressView:一款优雅的Android进度条控件

探索JProgressView:一款优雅的Android进度条控件 在Android应用开发中,进度条是不可或缺的组件,它能够向用户提供操作反馈和等待时的视觉提示。今天我们要介绍的是开发的一个开源项目——JProgressView(仓库链接:)。这个项目提供了一种高度可定制且美观的进度条控件,让开发者可以轻松地为自己的应用增添个性化元素。 项目简介 JProgressView是一个轻量级的库,它的...

gitblog_00098的博客 491

Android自定义ProgressBar实现漂亮的进度提示框

在android智能平板设备应用中,一项耗时的操作总要有个提示进度的框来提高用户的操作体验,操作进度提示框就显得很常用了。系统自带的有进度条ProgressBar,一般用于显示一个过程,例如数据加载过程,文件下载进度,音乐播放进度等。但是样式太单一不好看,因此有必要自定义一个方便使用。以下记录下封装的进度展示对话框ProgressDialog。先来展示下效果图:需要准备好素材。如上图中的那个旋转的圈圈,素材图是一张png图片,分辨率114x114:如何实现自动旋转的效果呢,使用android的Rotate动

shengyin714959的博客 1170

实现安卓360波浪效果进度条的设计与实践

进度条是一种常见的用户界面元素,用于显示操作进度的完成情况,它在应用和系统中扮演着至关重要的角色。本质上,进度条的主要功能是通过视觉反馈减少用户的等待焦虑,增强体验感。具体作用可以细分为以下几点:提供进度反馈:当用户发起一个可能需要较长时间才能完成的操作(如文件下载、数据加载等),进度条能够显示从0%到100%的完成进度,让用户知道何时可以使用或继续下一步。心理暗示:进度条能够通过不断更新的进度视觉效果,暗示用户系统仍在工作,减少用户因长时间等待而产生的焦虑感。引导注意力。

weixin_32098457的博客 1255

StofDoctrineExtensionsBundle的Uploadable扩展:文件上传管理的终极指南

StofDoctrineExtensionsBundle是Symfony框架中集成DoctrineExtensions的强大工具,其中Uploadable扩展为文件上传管理提供了完整解决方案。本文将详细介绍如何利用这一扩展实现高效、安全的文件上传功能,帮助开发者轻松处理Symfony项目中的文件管理需求。 ## 什么是Uploadable扩展? Uploadable扩展是StofDoctrin

gitblog_00026的博客 550

Android自定义View教程:模拟滴滴打车等车动画效果

本文还有配套的精品资源,点击获取 简介:本教程旨在介绍如何创建一个自定义的Android View,以模拟类似于滴滴打车应用中的等车加载动画效果。我们将通过继承View类、实现onDraw()方法和动画逻辑,以及进行性能优化和适配多分辨率等步骤,来构建一个动态且用户友好的进度视图。教程涵盖了动画实现、绘制逻辑、性能优化、交互设计以及兼容性测试等关键内容,帮助开发者提升应用的...

weixin_35757191的博客 1533

java安卓开发进度条_Android实现百分比下载进度条效果

现在很多APP中都会集成下载功能,所以有一个方便好看又实用的进度条来展示下载进度很有必要,也能提高用户体验,在这里我就把项目里的下载进度条抽取出来分享给大家,话不多说,先看效果图:这个进度条是自定义的一个View,其中有一个自定义属性就是百分比文字的大小(也可以把那两条显示颜色的进度条自定义属性,这里就没有实现,在代码里面写的)。先说说实现原理:1:由于自定义了属性,所以先获取属性的值。2:绘制底...

weixin_39854867的博客 573

Android自定义横向、圆形进度条带数字

非常有用的自定义横向圆形进度条,可以自己设置进度条的宽度、总长以及数字等

android 仿应用宝的带进度的按钮

这个是一个android的仿应用宝的带进度的加载按钮,我对界面优化过,性能也比较好,有兴趣的可以下载

Android 仿应用宝下载进度条

一、介绍 一个横向进度条 下载完成区域有一个滑块不断从左往右滑动(最开始就是被这个吸引的,就想着这个怎么实现的) 进度条中间显示当前进度,值得注意的是,进度条文本包含在下载区域中的部分显示为白色 点击暂停,进度条颜色改变,进度文本改变 二、分析根据以上简单介绍,可以抓住要实现的重难点是上面的第2、3点。 1. 进度条文本包含在下载区域中的部分显示为白色怎么实现? 这个和歌词变色的效果是一样的,所以实

FlowLeaf 1万+

华为擎云W515 PGUV-WBY0安装银河麒麟V10全流程解析

本文详细解析了华为擎云W515 PGUV-WBY0安装银河麒麟V10系统的全流程,包括准备工作、镜像下载与校验、启动盘制作、BIOS设置、安装过程关键选择、系统初始化及常见问题排查。特别针对ARM架构设备提供了实用技巧,帮助用户顺利完成国产化系统的部署与优化。

weixin_28725949的博客 701

FlickerProgressBar核心API完整教程:仿应用宝下载进度条setProgress、setStop、toggle、reset一网打尽

在 Android 开发中,FlickerProgressBar 是一款仿应用宝下载进度条的开源控件,它用左右流动的高光滑块让下载进度展示得生动直观。这篇 FlickerProgressBar 核心API完整教程专为新手准备,无需啃复杂源码,就能掌握 setProgress、setStop、toggle、reset 四个核心方法的正确用法,快速打造属于自己的下载进度条。 [![FlickerPr

gitblog_00476的博客 422

Pentaho安装与配置

Pentaho安装与配置前言一、下载二、配置1.JDK环境2.添加mysql-jdbc驱动三、启动 前言 Pentaho Data Integration (PDI):前身是Kettle。Pentaho提供了提取、转换和加载(ETL)功能,该功能使用统一且与最终用户和物联网技术相关且可访问的格式简化了捕获、清理和存储数据的过程。 功能:提供报表的制作、分析、仪表板、数据集成、数据采集、商业智能平台等强大功能。 一、下载 官网地址:http://www.pentaho.com/ 不过已经访问不到了

小太阳DENGJIE的博客 3613

ARM架构UOS实战:从源码编译Qt 5.15.2到定制Qt Creator的全流程解析

本文详细解析了在ARM架构统信UOS系统上,从源码编译Qt 5.15.2到定制Qt Creator开发环境的完整流程。内容涵盖环境准备、依赖部署、源码配置、编译优化、错误处理及IDE集成,旨在帮助开发者在国产化平台上构建自主可控的高性能Qt开发环境,解决特定ARM平台的兼容性与性能优化问题。

mango的博客 411

FlickerProgressBar:仿应用宝下载进度条的Android开源库完整指南

你打开应用宝,看到那个会"流动"的蓝色下载进度条,是不是觉得很酷?现在,一个名为 **FlickerProgressBar** 的轻量级 Android 开源库,让你**仿应用宝下载进度条**的愿望轻松实现。本文将为新手提供一份完整指南:从项目介绍、效果展示、集成步骤到核心 API 与自定义属性,手把手教你把它用在自己的 App 里,快速做出极具质感的下载进度体验。 [![FlickerProg

gitblog_00997的博客 429

BIDS数据存储格式介绍与dcm2bids安装与使用

BIDS格式&dcm2bids安装与使用

machinelearning_er的博客 7318

手写仿应用宝下载进度条:从零实现一个属于自己的FlickerProgressBar

如果你是 Android 开发者,一定见过应用宝那种"高光流动、点击暂停、再次点击继续"的酷炫下载进度条。今天推荐的开源项目 **FlickerProgressBar**,就是一个纯手写的**仿应用宝下载进度条**,它用自定义 View 的方式完整还原了这一效果,而且支持圆角、自定义颜色、暂停继续与重置,代码量小、上手极快。无论你是想学习 **Android 自定义 View** 的绘图原理,还是

gitblog_00223的博客 397

[深入研究4G/5G/6G专题-31]: 5G NR开机流程5.2 - UE Attach流程(Registeration Request/Accept/Complete)

目录前言:前置条件:第1章 5G NR UE attach流程(从UE log的视角看)1.0 NAS消息解析器1.1 消息交互流程1.2 UE Registeration Request消息(AMF->基站->UE)1.3 AMF Registeration Accept消息(AMF->基站->UE)1.4 UE Register complete消息(UE->基站->AMF)第2章 UE Register...............

文火冰糖(王文兵)的博客 7万+

【YOLO目标检测全栈实战】98 YOLO模型在低光照环境下的自适应增强策略

你有没有遇到过这种情况?深夜加班调试产线检测模型,车间灯光昏暗,摄像头采集的图片黑乎乎一片,YOLO模型直接“罢工”——漏检率飙升到40%以上。上个月我在一个汽车零部件质检项目里就栽了跟头:白天模型跑得飞起,mAP@0.5达到0.92,可一到夜班,同样的产线、同样的零件,mAP直接掉到0.63。客户拍着桌子问我:“你这模型怎么还分白天黑夜?”

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 286

Android自定义View——带数字的进度条

最近看到高德地图下载离线地图包的进度条效果,作为程序猿的本能就是想着怎样实现它 刚好在学习自定义控件,这个应该不需要处理事件消息,应该还是比较简单的。废话少说直接上效果图

小码农大梦想 1984

9.6华为OD机试真题 新系统 - 仓储货物有序出库 (Java/Py/C/C++/Js/Go)

9.6华为OD机试真题 新系统 - 仓储货物有序出库 (Java/Py/C/C++/Js/Go)

算法大师! 1202

3分钟快速上手FlickerProgressBar:Android应用宝风格下载进度条接入教程

FlickerProgressBar 是一个轻量级的 Android 下载进度条开源控件,专门复刻应用宝下载进度条的经典光影闪烁效果。如果你正在开发应用市场、下载管理类 App,想要一个自带呼吸感的 Android 下载进度条,那么这个控件绝对值得一试。本教程将用 3 分钟带你完成 FlickerProgressBar 的接入、配置和调用,全程零基础友好。 [![FlickerProgressB

gitblog_00794的博客 332

杰理JL701N内置flash录音配置教程

本文详细介绍了内置Flash录音功能的配置方法。主要内容包括:1) 基础模式配置(开启音乐/录音模式、Flash录音宏定义);2) 录音参数设置(格式基准值、存储区域定义、容量配置);3) MP3编码特殊处理;4) 下载时的Flash格式化操作;5) 录音开关和播放接口的使用说明。配置过程涉及多个关键文件的修改,并强调存储容量的精确分配。

qq_42014563的博客 598

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: android 自定义view实现仿QQ运动步数进度效果
下一篇: android 自定义view仿今日头条加载文字变色的效果
zhoushenxian
博客等级 码龄12年 453粉丝 549原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值