Android 自定义View ProgressBarHorizontal:横向进度条、支持圆角、渐变、图片_progressbar_horizontal-程序员宅基地

技术标签: 自定义控件  

背景:因系统的ProgressBar设置图片时,如果图片不够大,而在大分辨率的手机上时会出现无法填充满,所以自己写一个,既修复该问题,又可方便拓展,所以抛砖引玉


功能介绍:横向进度条,分为背景与封面两层,封面与背景均支持圆角矩形、渐变、图片。


效果图:



(上面仿微博加载图片进度条在另一篇博文中:http://blog.csdn.net/fy993912_chris/article/details/77370206)


<com.example.work.myapplication.widget.ProgressBarHorizontal
    android:layout_width="match_parent"
    android:layout_height="25dp"
    app:pbhBgColorEnd="#01978a"
    app:pbhBgColorStart="#00a2e9"
    app:pbhBgRadius="15dp"
    app:pbhBgSrc="@mipmap/ic_health_bg_2"
    app:pbhCoverColorEnd="@color/colorAccent"
    app:pbhCoverColorStart="@color/colorPrimary"
    app:pbhCoverSrc="@mipmap/ic_life_bg"
    app:pbhProgress="50"
    app:pbhScaleType="match_parent" />

<com.example.work.myapplication.widget.ProgressBarHorizontal
    android:layout_width="match_parent"
    android:layout_height="25dp"
    android:layout_marginTop="5dp"
    app:pbhBgColorEnd="#01978a"
    app:pbhBgColorStart="#00a2e9"
    app:pbhBgRadius="15dp"
    app:pbhCoverColorEnd="@color/colorAccent"
    app:pbhCoverColorStart="@color/colorPrimary"
    app:pbhCoverSrc="@mipmap/ic_life_bg"
    app:pbhProgress="50"
    app:pbhScaleType="match_parent" />

<com.example.work.myapplication.widget.ProgressBarHorizontal
    android:layout_width="match_parent"
    android:layout_height="25dp"
    android:layout_marginTop="5dp"
    app:pbhBgColorEnd="#01978a"
    app:pbhBgColorStart="#00a2e9"
    app:pbhBgLbRadius="14dp"
    app:pbhBgLtRadius="14dp"
    app:pbhBgRbRadius="0dp"
    app:pbhBgRtRadius="0dp"
    app:pbhCoverColorEnd="@color/colorAccent"
    app:pbhCoverColorStart="@color/colorPrimary"
    app:pbhCoverLbRadius="14dp"
    app:pbhCoverLtRadius="14dp"
    app:pbhCoverRbRadius="0dp"
    app:pbhCoverRtRadius="0dp"
    app:pbhProgress="50"
    app:pbhScaleType="match_parent" />


使用方法非常简单,只需要在xml中配置对应属性便可实时预览效果


需要注意的是控件会有一个优先级别显示:


依次为:


图片->圆角矩形


设置圆角时,radius会优于rt、rb、lt、lb属性


scaleType:

match_content:以控件大小为准

wrap_content:以封面图片大小为准


具体可以查看代码或者配置xml进行查看,这里就不多说啦。


以下是代码--------------------------------------------------------------------------------------------------


clss类文件源码


/**
 * Created by work on 2017/8/8.
 * 横向进度条
 *
 * @author chris zou
 * @mail [email protected]
 */

public class ProgressBarHorizontal extends View {
    public float maxProgress = 100;
    /*背景*/
    Bitmap bgBitmap;
    int bgColorStart;
    int bgColorEnd;
    int[] bgColors;
    int bgRadius;
    int bgLtRadius;
    int bgLbRadius;
    int bgRbRadius;
    int bgRtRadius;
    Paint bgPaint;
    /*end*/

    /*图片*/
    Bitmap coverBitmap;
    int coverColorStart;
    int coverColorEnd;
    int[] coverColors;
    int coverRadius;
    int coverLtRadius;
    int coverLbRadius;
    int coverRtRadius;
    int coverRbRadius;
    Paint coverPaint;
    /*end*/

    int w, h;
    int compareMinSize;//高与宽较小那个

    int scaleType;
    float progress;

    public ProgressBarHorizontal(Context context) {
        this(context, null);
    }

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

    public ProgressBarHorizontal(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context.obtainStyledAttributes(attrs, R.styleable.ProgressBarHorizontal));
    }

    public void init(TypedArray typedArray) {
        setupParams(typedArray);
        setupPaint();
    }

    /**
     * 设置参数
     */
    public void setupParams(TypedArray typedArray) {
        bgColorStart = typedArray.getColor(R.styleable.ProgressBarHorizontal_pbhBgColorStart, Color.DKGRAY);
        bgColorEnd = typedArray.getColor(R.styleable.ProgressBarHorizontal_pbhBgColorEnd, bgColorStart);
        bgColors = new int[]{
   bgColorStart, bgColorEnd};
        bgRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgRadius, 0);
        bgLtRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgLtRadius, 0);
        bgLbRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgLbRadius, 0);
        bgRbRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgRbRadius, 0);
        bgRtRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgRtRadius, 0);
        Drawable coverDrawable = typedArray.getDrawable(R.styleable.ProgressBarHorizontal_pbhBgSrc);
        bgBitmap = coverDrawable != null ? ((BitmapDrawable) coverDrawable).getBitmap() : null;

        coverColorStart = typedArray.getColor(R.styleable.ProgressBarHorizontal_pbhCoverColorStart, Color.GRAY);
        coverColorEnd = typedArray.getColor(R.styleable.ProgressBarHorizontal_pbhCoverColorEnd, coverColorStart);
        coverColors = new int[]{
   coverColorStart, coverColorEnd};
        coverRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverRadius, 0);
        coverLtRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverLtRadius, 0);
        coverLbRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverLbRadius, 0);
        coverRbRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverRbRadius, 0);
        coverRtRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverRtRadius, 0);
        Drawable bottomDrawable = typedArray.getDrawable(R.styleable.ProgressBarHorizontal_pbhCoverSrc);
        coverBitmap = bottomDrawable != null ? ((BitmapDrawable) bottomDrawable).getBitmap() : null;

        progress = typedArray.getInteger(R.styleable.ProgressBarHorizontal_pbhProgress, 0);
        scaleType = typedArray.getInteger(R.styleable.ProgressBarHorizontal_pbhScaleType, 0);
    }

    public void setupPaint() {
        bgPaint = new Paint();
        bgPaint.setColor(bgColorStart);
        bgPaint.setStyle(Paint.Style.FILL);
        bgPaint.setAntiAlias(true);

        coverPaint = new Paint();
        coverPaint.setColor(coverColorStart);
        coverPaint.setStyle(Paint.Style.FILL);
        coverPaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (scaleType == 0) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        } else {
            if (coverBitmap == null) {
                throw new NullPointerException("wrap_content must set image res");
            }
            setMeasuredDimension(coverBitmap.getWidth(), coverBitmap.getHeight());
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.w = w;
        this.h = h;

        compareMinSize = w > h ? h : w;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //bg
        bgPaint.setShader(new LinearGradient(0, h / 2, w, h / 2, bgColors, null, Shader.TileMode.MIRROR));
        if (bgBitmap != null) {
            canvas.drawBitmap(bgBitmap, null, new RectF(0, 0, w, h), null);
        } else if (bgRadius != 0) {
            RectF bgRec = new RectF(0, 0, w, h);
            canvas.drawRoundRect(bgRec, bgRadius, bgRadius, bgPaint);
        } else {
            drawPath(canvas, bgLtRadius, bgLbRadius, bgRbRadius, bgRtRadius, w, bgPaint);
        }
        //cover
        coverPaint.setShader(new LinearGradient(0, h / 2, w, h / 2, coverColors, null, Shader.TileMode.MIRROR));
        float progressWidth = w - w * ((maxProgress - progress) / maxProgress);
        if (coverBitmap != null) {
            RectF imgRect = new RectF(0, 0, progressWidth, h);
            Rect srcRect = new Rect(0, 0, (int) progressWidth, h);
            canvas.drawBitmap(coverBitmap, srcRect, imgRect, null);
        } else if (coverRadius != 0) {
            RectF coverRec = new RectF(0, 0, progressWidth, h);
            canvas.drawRoundRect(coverRec, coverRadius, coverRadius, coverPaint);
        } else {
            drawPath(canvas, coverLtRadius, coverLbRadius, coverRbRadius, coverRtRadius, progressWidth, coverPaint);
        }
    }

    /**
     * 做一阶贝塞尔曲线
     *
     * @param canvas
     * @param lt
     * @param lb
     * @param rb
     * @param rt
     * @param w
     * @param paint
     */
    private void drawPath(Canvas canvas, int lt, int lb, int rb, int rt, float w, Paint paint) {
        //左上角,逆时针开始
        Path path = new Path();
        //左上
        path.moveTo(lt, 0);
        path.quadTo(0, 0, 0, lt);
        //左下
        path.lineTo(0, h - lb);
        path.quadTo(0, h, lb, h);
        //右下
        path.lineTo(w - rb, h);
        path.quadTo(w, h, w, h - rb);
        //右上
        path.lineTo(w, rt);
        path.quadTo(w, 0, w - rt, 0);
        //回到左上角
        path.lineTo(lt, 0);
        canvas.drawPath(path, paint);
    }

    /**
     * @param progress 0-100
     */
    public void setProgress(float progress) {
        if (progress > maxProgress) {
            progress = maxProgress;
        }
        this.progress = progress;
        postInvalidate();
    }

    public void setBgColors(int[] colors) {
        this.bgColors = colors;
    }

    public void setCoverColors(int[] colors) {
        this.coverColors = colors;
    }
}


attrs属性内容


<declare-styleable name="ProgressBarHorizontal">
    <attr name="pbhBgSrc" format="reference" />
    <attr name="pbhBgColorStart" format="color" />
    <attr name="pbhBgColorEnd" format="color" />
    <attr name="pbhBgRadius" format="dimension" />
    <attr name="pbhBgLtRadius" format="dimension" />
    <attr name="pbhBgLbRadius" format="dimension" />
    <attr name="pbhBgRbRadius" format="dimension" />
    <attr name="pbhBgRtRadius" format="dimension" />

    <attr name="pbhCoverSrc" format="reference" />
    <attr name="pbhCoverColorStart" format="color" />
    <attr name="pbhCoverColorEnd" format="color" />
    <attr name="pbhCoverRadius" format="dimension" />
    <attr name="pbhCoverLtRadius" format="dimension" />
    <attr name="pbhCoverLbRadius" format="dimension" />
    <attr name="pbhCoverRbRadius" format="dimension" />
    <attr name="pbhCoverRtRadius" format="dimension" />

    <attr name="pbhProgress" format="integer" />
    <attr name="pbhScaleType">
        <enum name="match_parent" value="0" />
        <enum name="wrap_content" value="1" />
    </attr>
</declare-styleable>

将源码拷贝到自己的工程就可以啦。



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Fy993912_chris/article/details/77369643

智能推荐

GIT常用命令_ugit新增仓库-程序员宅基地

文章浏览阅读198次。文章目录git笔记安装配置新建仓库。提交、关联从现有仓库克隆从另一个仓库合并代码到本地更新本地分支远端标签导出问题解决回滚到任意版本提交代码时 无法直接 git pull 问题。因为 本地分支没有和远程分支进行关联当控制台提示本地版本 滞后 远程版本时, 使用强制提交 覆盖远程分支(慎用!慎用!慎用!)代码写错分支,怎么办?欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左_ugit新增仓库

ssh另一台机器时,报Password authentication is disabled to avoid man-in-the-middle attacks.-程序员宅基地

文章浏览阅读8k次。原文地址::http://www.blogjava.net/anchor110/articles/418195.html相关文章1、好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established.的问题----http://blog.csdn.net/kimsoft/article/detai_password authentication is disabled to avoid man-in-the-middle attacks

MATLAB mmseg,Unofficial Windows Binaries for Python Extensio...-程序员宅基地

文章浏览阅读80次。GNU Aspell (LyX fork).aspell_python-1.12.win-amd64-py2.6.‌exe [473KB] [Python 2.6] [64 bit] [Aug 14, 2012]aspell_python-1.12.win-amd64-py2.7.‌exe [473KB] [Python 2.7] [64 bit] [Aug 14, 2012]...

Unity Graphics (Unity 图形渲染 ) 官方教程文档笔记系列之一-程序员宅基地

文章浏览阅读1.6k次,点赞2次,收藏9次。Unity Graphics (Unity 图形渲染 ) - Everything for Lighting and Rendering in Unity - 主要涉及到光照与渲染方面的知识本文档主要是对Unity官方教程的个人理解与总结(其实以翻译记录为主:&amp;amp;amp;amp;gt;) 仅作为个人学习使用,不得作为商业用途,欢迎转载,并请注明出处。 ..._unity graphics

scau数据库数据下载——数据库系统概念第三章大学模式smallRelationsInsertFile.sql下载和使用_数据库系统概念大学模式数据库下载-程序员宅基地

文章浏览阅读457次。1.进入Database System Concepts - 7th edition (db-book.com)官网,选择sample tables2.选择箭头所指sql文件并下载3.保存largeRelationsInsertFile.sql文件并用记事本的方式打开4.删除方框内的代码5.删除部分改为以下代码create table classroom(building varchar(15),room_number varchar(7),capacity n._数据库系统概念大学模式数据库下载

使用fastdfs-client-java操作fastDFS-程序员宅基地

文章浏览阅读2.9k次。1.环境安装:参考:https://blog.csdn.net/cencfeng11/article/details/95977300fastDFS已经配置完成https://github.com/happyfish100/fastdfs-client-java下载源码命令:mvn clean installant clean package (先安装ant)mv..._fastdfs-client-java

随便推点

05FFMPEG的AVIOContext结构体分析_ffmpeg avio-程序员宅基地

文章浏览阅读216次。FFMPEG的AVIOContext结构体分析概述:该结构体位于libavformat库中的avio.h中。1 AVIOContext结构体typedef struct AVIOContext { /** * A class for private options. * * If this AVIOContext is created by avio_open2(), av_class is set and * passes the options d_ffmpeg avio

Top 100 Software Testing Blogs _top 100 cocktail blogs-程序员宅基地

文章浏览阅读695次。之前推荐了200开发人员blog列表Top 200 Blogs for Developers,在testingminded有人推荐了100测试blog,在这里摘录如下,希望对测试人员有所帮助!#SiteAuthor1James Bachs BlogJames Bach2Test_top 100 cocktail blogs

面向抽象编程总结_面向抽象开发-程序员宅基地

文章浏览阅读486次。在外部类中调用某一个实例的成员方法的方式:1.面向具体类:创建一个该类的实例对象,通过该实例对象调用其成员方法 优点:编写时简单 缺点:高耦合,后期h代码维护难,外部类严重依赖该类,当该类代码有变动时,除了改动该类的代码,在外部类所有使用了该类的代码都要改变,如A.a()要换成B.b()时,每一处与A相关的代码都要变动//面向具体类,C与A高耦合,当要维护代码时所有与A.a()相关的代码都要改动public class C { public stati..._面向抽象开发

winscp 怎么用私钥文件登录的,以.ppk结尾的密钥文件-程序员宅基地

文章浏览阅读1.1k次。Winscp默认用帐号密码登录,用私钥文件登录需要在高级选项里面的SSH--验证里面选择文件。Winscp使用的是putty作为SSH登录工具,而puttygen所生成的是以.ppk结尾的密钥文件。如果是pub类型的需要转换为putty类型的,文件类型里选择所有文件,选择密钥文件会提示你是否转换,按提示操作转换保存后就会自动选择转换后的.ppk密钥文件了。 WinSCP :: ..._winscp私钥方式登录

转:软件能够修复硬盘吗?―硬盘损坏全分析-程序员宅基地

文章浏览阅读135次。http://computer.mblogger.cn/jin0706/posts/30199.aspx原文出处:http://www.dostor.com/hdd/diy/2003-11-15/000246649.shtml收录时间:2005-03-16纷争的起点 一直以来,硬盘都是计算机系统中最主要的存储设备,同时也是计算机系统中最容易出故障的部件。十几年来,计算机CPU的运行速度已经..._软件可以损坏硬盘吗

Ubantu 18.04 apt-get update 无法更新,更新慢的问题_ubuntu 18 无法update-程序员宅基地

文章浏览阅读1.5w次,点赞5次,收藏15次。首先,备份一下Ubuntu 原来的源地址列表文件sudo cp /etc/apt/sources.list /etc/apt/sources.list.old在终端 cd /etc/apt 修改文件sources.list如果遇到只读问题的话 就用超级用户权限去打开修改sudo vim sources.list把文件的源替换成下面的源 我一直都在用阿里云的 效果还不错!..._ubuntu 18 无法update

推荐文章

热门文章

相关标签