自定義ProgressBar(自定義View和ClipDrawable)

開發中常常須要自定義ProgressBar,這裏用了自定義View和ClipDrawable實現簡單的ProgressBar
自定義View效果:圖片描述java

public class CustomProgressBar extends View {

    private Paint mBgtPaint;//底部背景畫筆
    private Paint mProgressPaint;//progress畫筆
    private int startX;//起始X座標,保持不變
    private int endX;//終點座標,保持不變
    private int currentX;//當前座標,progress換算而來,不斷增大

    private int mProgressBgHeight = 60;
    private int mProgressHeight = 50;
    private int mProgressBgColor = Color.BLACK;
    private int mProgressColor = Color.BLUE;

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

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

    }

    public CustomProgressBar(Context context,  @Nullable AttributeSet attrs, int defStyleAttr){
        super(context, attrs, defStyleAttr);

        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
                R.styleable.myProgressBar, defStyleAttr, 0);

        mProgressBgHeight = a.getInteger(R.styleable.myProgressBar_progress_background_height, mProgressBgHeight);
        mProgressHeight = a.getInteger(R.styleable.myProgressBar_progress_height,mProgressHeight);

        mProgressBgColor = a.getColor(R.styleable.myProgressBar_progress_background_color,mProgressBgColor);
        mProgressColor = a.getColor(R.styleable.myProgressBar_progress_color, mProgressColor);

        a.recycle();

        init();
    }


    private void init() {

        //初始化畫筆
        mBgtPaint = new Paint();
        mBgtPaint.setAntiAlias(true);//抗鋸齒
        mBgtPaint.setStyle(Paint.Style.STROKE);
        //注意:這是筆尖樣式的屬性,Paint.Cap.ROUND設置筆尖爲圓形,默認方形,
        mBgtPaint.setStrokeCap(Paint.Cap.ROUND);
        mBgtPaint.setColor(mProgressBgColor);
//        mBgtPaint.setColor(Color.parseColor("#1F1F26"));//設置畫筆顏色,這裏是深灰色
        mBgtPaint.setStrokeWidth(60);

        mProgressPaint = new Paint();
        mProgressPaint.setAntiAlias(true);
        mProgressPaint.setStyle(Paint.Style.STROKE);
        mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
        mProgressPaint.setColor(mProgressColor);
//        mProgressPaint.setColor(Color.parseColor("#54FC00"));
        mProgressPaint.setStrokeWidth(50);//這裏的線條寬度比背景線條窄一些。

    }


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        //這裏根據屏幕的寬高獲取座標,能夠設置成自定義屬性,讓用戶設置
        startX = getWidth()/2-getWidth()/3;
        endX = getWidth()/2 + getWidth()/3;
        currentX = startX;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //繪製底部背景線條(深灰色,區別於View背景色)
        canvas.drawLine(startX, getHeight() / 2, endX,
                getHeight() / 2, mBgtPaint);

        //繪製當前的progress
        canvas.drawLine(startX+1, getHeight() / 2, currentX,
                getHeight() / 2, mProgressPaint);

    }

    //更新進度
    public void updateProgress(int progress) {

        //這裏progress的長度分紅100個單位,再計算座標,其實progress能夠是實時的下載進度,
        //計算下載量百分比,而後再計算座標,會相對精確
        if (progress <= 100){
            currentX = startX + (int)((progress * 1.0)/100 * (endX - startX));
            invalidate();//從新繪製才能生效
        }
    }
}

使用到了自定義的屬性,能夠在values/下添加attrs.xml(文件能夠爲其餘名字),res/values/attrs.xmlandroid

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="myProgressBar">

        <attr name="progress_background_color" format="color"/>
        <attr name="progress_background_height" format="integer"/>
        <attr name="progress_color" format="color"/>
        <attr name="progress_height" format="integer"/>
    </declare-styleable>
</resources>

代碼中使用:canvas

public class CustomActivity extends AppCompatActivity {


    private CustomProgressBar mCustomProgressBar;

    private int mProgress=0;

    private Handler mHandler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom);

        mCustomProgressBar = (CustomProgressBar)findViewById(R.id.progress_bar_custom);

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {

                mCustomProgressBar.updateProgress(++mProgress);
                if (mProgress < 100) {
                    mHandler.postDelayed(this, 500);
                }
            }
        }, 500);

    }
}

這樣大部分的自定義的ProgressBar均可以畫出來,有些可能須要添加動畫。若是有些ProgressBar自己的樣式
太過複雜,使用自定義view畫出來有較大的難度,那麼還有更簡單的方法,讓ui切出ProgressBar完整的圖片,而後使用ClipDrawable根據
進度的更新不斷地顯示,使用起來其實挺簡單的,效果圖:app

圖片描述

先定義一個clipDrawableide

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@drawable/gakki_alone"
    android:gravity="left"/>

第一個屬性:裁剪方向,這裏是水平方向。第二個參數:圖片,第三個參數:開始裁剪的位置,這裏是從左開始佈局

xml佈局中使用,和普通的drawable使用方法同樣post

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"     
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.why.traing2.ClipDrawableActivity">

    <ImageView
        android:id="@+id/img_clip"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:scaleType="centerCrop"
        android:background="@color/colorAccent"
        android:src="@drawable/clip"
        android:layout_centerInParent="true"/>

</FrameLayout>

最後是代碼中的的引用動畫

public class ClipDrawableActivity extends AppCompatActivity {

    private Handler mHandler = new Handler();
    private int mLevel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_clip_drawable);

        ImageView imageView = (ImageView)findViewById(R.id.img_clip);

        final ClipDrawable clipDrawable = (ClipDrawable)imageView.getDrawable();

        //level取值:0-10000, 0:不可見,10000:徹底顯示
        mLevel = clipDrawable.getLevel();

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                clipDrawable.setLevel(mLevel);
                mLevel += 100;

                if (mLevel <= 10000) {
                    mHandler.postDelayed(this, 500);
                }
            }
        }, 500);

    }
}

這樣複雜的ProgressBar, 能夠直接使用圖片按比例顯示讀取進度,節省代碼量.ui

相關文章
相關標籤/搜索