自定義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; 動畫的滾動速度