准備工作:
考慮這個自定義view需要什么屬性來方便在xml布局里面改。
在values/attrs.xml里面添加自定義屬性,分別是尺寸,顏色,變大的倍數。
<span style="font-size:14px;"><resources>
<declare-styleable name="CustomView">
<attr name="size" format="dimension" />
<attr name="color" format="color" />
<attr name="maxValue" format="float"/>
</declare-styleable>
</resources></span>
format是定義的屬性的類型,配置完成后,就可以在xml布局中使用這些屬性了。
繼承view之后,會有三個構造方法
<span style="font-size:14px;">public class CustomView extends View{
private int DEFAULT_SIZE = 100;//默認半徑
private int DEFAULT_COLOR = Color.GREEN;//默認顏色
private float DEFAULT_MAXVALUE = 1.6f;//默認放大倍數
private int mSize;//半徑
private int mColor;
private Paint mPaint;
private int mHeight;
private int mWidth;
private Float value = 1f;
private Float maxValue;//實際放大的倍數
private ValueAnimator anim;
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.getTheme().obtainStyledAttributes(
attrs,R.styleable.CustomView,0,0);
mSize = typedArray.getDimensionPixelSize(R.styleable.CustomView_size,DEFAULT_SIZE);
mColor = typedArray.getColor(R.styleable.CustomView_color,DEFAULT_COLOR);
maxValue = typedArray.getFloat(R.styleable.CustomView_maxValue,DEFAULT_MAXVALUE);
typedArray.recycle();
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}</span>
第一個構造方法是在代碼中創建view,
<span style="font-size:14px;"> CustomView view = new CustomView(this);</span>
第二個是我們常用的構造方法,給每個自定義屬性設置個默認值,可以再布局中配置這些自定義屬性。這些屬性存放在第二個參數中。
第三個是需要指定style是調用。
然后開始自定義View。。。
主要會涉及三個方法,分別是onDraw(),onLayout(),onMeasure()。
1、onDraw():
就是把要顯示的view畫出來,就是一個圓,很簡單。
<span style="font-size:14px;">@Override
protected void onDraw(Canvas canvas) {
mPaint = new Paint();
mPaint.setColor(mColor);
mPaint.setAntiAlias(true);//抗鋸齒效果
//畫圓,前兩個參數確定圓心,第三個參數是半徑
canvas.drawCircle(mWidth/2,mHeight/2,mSize *value,mPaint);
}</span>
2,、onLayout():
這個方法主要是確定當前view在父視圖中的位置
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// 重設圓半徑,防止超出視圖大小
mHeight = getMeasuredHeight();
mWidth = getMeasuredWidth();
int maxSize = (int) Math.min(mHeight/(2 * maxValue),mWidth/(2 * maxValue));
mSize = mSize > maxSize ? maxSize : mSize;
}
我在這里重寫這個方法是為了防止圓變大時,超出屏幕范圍。其中maxSize是view可以有的最大半徑,要考慮到圓變大時也不能超出屏幕,所以是mHeight / (2 * maxValue)。
其實沒必要重寫onLayout(),這里只是為了防止半徑設置的過大。。
在這里重寫onLayout()后,有個弊端,就是當在布局中寬高設置固定大小時,顯示的圓的半徑是所設置寬高的一半,例如寬高都
設置為20dp,所顯示的半徑為10dp。設置成wrap_content或者match_parent或者不重寫onLayout()就沒影響了。
3、onMeasure():
先提一句:onMeasure()方法不是每個自定義view都需要重寫的。下面簡單的了解一下onMeasure的用法。
在xml布局中,我們會設置wrap_content或者match_parent。
但是系統給我們測量得到的寬度和高度都是match_parent。
當我們用到wrap_content時,需要的是實際寬度或高度,而不是系統測量得到的match_parent,就需要我們自己測量,即重寫
onMeasure();這里的自定義view就不需要重寫onMeasure(),因為這里所需要的寬高就是match_parent,我們只是通
過寬高得到中心點畫圓即可。
4.view花完了,開始動畫部分,使用ValueAnimator實現的。
public void startAnimation(){
anim = ValueAnimator.ofFloat(value,maxValue);
anim.setRepeatCount(ValueAnimator.INFINITE);//設置無限重復
anim.setRepeatMode(ValueAnimator.REVERSE);//設置重復模式
anim.setDuration(500);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
value = (Float) animation.getAnimatedValue();
postInvalidate();
}
});
anim.start();
}
anim = ValueAnimator.ofFloat(value,maxValue);
得到ValueAnimator對象,其中兩個參數代表從value到maxValue平滑變化。
在監聽方法中,通過調用getAnimateValue()方法獲取動畫在播放過程中屬性值的變化,也就是上面參數變化過程中的一系列值。
通過postInvalidate()實現刷新,在onDraw()方法中
<span style="font-size:14px;">canvas.drawCircle(mWidth/2,mHeight/2,mSize *value,mPaint);</span>
半徑 = mSize * value,半徑不斷變化,實現了圓放大過程。
想要實現復雜的動畫可以了解了解ValueAnimator和ObjectAnimator。
最后在Activity中啟動動畫和關閉動畫
public class MainActivity extends AppCompatActivity {
private CustomView customView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customView = (CustomView) findViewById(R.id.custom_view);
customView.startAnimation();
//customView.endAnimation();
}
}
Demo下載地址
---------------------
作者:蜉蝣DG
來源:CSDN
原文:https://blog.csdn.net/qy1993qy/article/details/52824888
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!