1. 程式人生 > >自定義View,又一種進度條的呈現,CircleProgressView使用解析

自定義View,又一種進度條的呈現,CircleProgressView使用解析

話不多說,先上效果圖
這裡寫圖片描述 這裡寫圖片描述

迴圈旋轉的狀態
這裡寫圖片描述 這裡寫圖片描述

專案結構

這裡寫圖片描述
一個Sample包,一個Lib包。Lib包裡面其實只有一個累,很多內容都在素材檔案裡,比較建議把內容複製出來,貼到自己的專案中

主類:

public class MainActivity extends ActionBarActivity {


    CircleProgressView mCircleView;
    Switch mSwitchSpin;
    Switch mSwitchShowUnit;
    SeekBar mSeekBar;
    SeekBar mSeekBarSpinnerLength;

    @Override
protected void onCreate(Bundle savedInstanceState) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WebView.setWebContentsDebuggingEnabled(true); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mCircleView = (CircleProgressView) findViewById(R.id.circleView); mCircleView.setMaxValue(100
); mCircleView.setUnit("%"); mCircleView.setValue(0); //Setup Switch mSwitchSpin = (Switch) findViewById(R.id.switch1); mSwitchSpin.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged
(CompoundButton buttonView, boolean isChecked) { if (isChecked) { mCircleView.spin(); } else { mCircleView.stopSpinning(); } } }); mSwitchShowUnit = (Switch) findViewById(R.id.switch2); mSwitchShowUnit.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mCircleView.setShowUnit(isChecked); } }); //Setup SeekBar mSeekBar = (SeekBar) findViewById(R.id.seekBar); mSeekBar.setMax(100); mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { mCircleView.setValueAnimated(seekBar.getProgress(),1500); mSwitchSpin.setChecked(false); } }); mSeekBarSpinnerLength = (SeekBar) findViewById(R.id.seekBar2); mSeekBarSpinnerLength.setMax(360); mSeekBarSpinnerLength.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { mCircleView.setSpinningBarLength(seekBar.getProgress()); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. // getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. // int id = item.getItemId(); //noinspection SimplifiableIfStatement // if (id == R.id.action_settings) { // return true; // } return super.onOptionsItemSelected(item); } @Override protected void onStart() { super.onStart(); mCircleView.setValue(0); mCircleView.setValueAnimated(0); } }

分析:
一個CircleProgressView自定義控制元件,2個SeekBar來控制進度條的百分比,以及長度,2個Switch用於切換顯示內容,和一堆顯示的TextView

可以在OnStart()呼叫setValue()方法,來給進度條賦值。而內部實現也是Handle傳參的一系列操作

    /**
     * Set the value of the circle view without an animation.
     * Stops any currently active animations.
     */
    public void setValue(float _value) {
        Message msg = new Message();
        msg.what = AnimationMsg.SET_VALUE.ordinal();
        msg.obj = new float[]{_value, _value};
        mAnimationHandler.sendMessage(msg);
    }

在HandleMessage方法裡又呼叫setValue(msg, circleView);
最終實現的是setValue(Message msg, CircleProgressView _circleView)方法

   private void setValue(Message msg, CircleProgressView _circleView) {
            _circleView.mValueFrom = _circleView.mValueTo;
            _circleView.mCurrentValue = _circleView.mValueTo = ((float[]) msg.obj)[0];
            _circleView.mAnimationState = AnimationState.IDLE;
            _circleView.invalidate();
        }

所以,你在程式碼操作的過程中,可以肆意呼叫SetValue()方法,不用在意會對其他部分的內容產生影響。

Sample程式碼裡的 mSeekBarSpinnerLength.setMax(360);就等於mCircleView.setSpinningBarLength(seekBar.getProgress());給環狀的SpinningBar傳一個int的值讓他呈現出一個角度為seekBar.getProgress()/360的圖形。當然你傳入的數值<360時,SeekBar拉到底了也不會成為整圓 那麼>360的話只要到達360圓就已經呈現出來了,多餘的值將沒有效果。
效果如圖:
這裡寫圖片描述

然後我們來看下核心類CircleProgressView

public class CircleProgressView extends View 繼承於View

然後洋洋灑灑1300+行的程式碼,我就不一一分析了,一些是畫的一些是用的,亟亟就不做過多解釋了,自己可以看原始碼,為了用那我們來看下一些配置

    //尺寸引數
    private int mLayoutHeight = 0;
    private int mLayoutWidth = 0;
    private int mFullRadius = 100;
    private int mCircleRadius = 80;
    private int mBarWidth = 40;
    private int mRimWidth = 40;
    private int mTextSize = 20;
    private float mContourSize = 1;
    private float mTextScale = 1;
    private float mUnitScale = 1;

對圖形的整個大小啊,半徑啊,字型的大小啊等進行設定。

    //顏色
    private final int mBarColorStandard =  0xff009688; //stylish blue
    private int mContourColor = 0xAA000000;
    private int mSpinnerColor = mBarColorStandard; //stylish blue
    private int mFillColor = 0x00000000;  //transparent
    private int mRimColor = 0xAA83d0c9;
    private int mTextColor = 0xFF000000;
    private int mUnitColor = 0xFF000000;
    private int[] mBarColors = new int[]{
            mBarColorStandard, //stylish blue
            mBarColorStandard, //stylish blue
    };

顏色的設定,圓的顏色,字的顏色等

  private float mSpinSpeed = 2.8f; 動畫的滾動速度