自訂View學習之12/1,自訂view學習12
感謝AigeStudio提供的自訂view講解(地址http://blog.csdn.net/aigestudio)下面是我看了Aige的講解之後自己的理解以及demo,有說錯的地方歡迎大家指出。
在這裡自訂一個圓形等級條的view來加強自己對自訂的理解。
思路:
1、需要畫一個背景圓,再需要一個覆蓋在背景圓上面的進度圓。
2、使用線程讓進度圓產生動畫。
3、在進度圓達到圓滿的時候回到原點,給個回調。
現在我們先畫出一個空心圓。
代碼塊
/** 背景圓的畫筆 */ private Paint paint; /** 進度條圓的畫筆 */ private Paint paint1; /** 設定矩陣的座標點 */ private RectF rectF; /** 螢幕的高度 */ private int width = 0; /** 園的半徑 */ private int circleRadius = 0; /** 園的y軸起始座標 */ private int circleStartY = 20; /** 園的y軸終點座標 起始座標加上園的半徑*2 */ private int circleEndy = 0; /**我一般喜歡直接寫3個構造方法,方便引用*/ public CircleView(Context context) { super(context); init(context); } public CircleView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } /**初始化畫筆*/ private void init(Context context){ paint = new Paint();// 布局xml裡面引用 paint1 = new Paint();// 布局xml裡面引用 paint.setAntiAlias(true);// 設定消除鋸齒 paint.setColor(getResources().getColor(R.color.char_circlebackground)); paint.setStyle(Style.STROKE);// 設定圓心掏空 paint.setStrokeWidth(dip2px(context, 10)); // 設定畫筆形狀 圓形,需要先設定畫筆樣式 SYROKE 或者 FILL_AND_STROKE paint.setStrokeCap(Paint.Cap.ROUND); paint1.setAntiAlias(true);// 設定消除鋸齒 paint1.setColor(getResources().getColor(R.color.char_circleplan)); paint1.setStyle(Style.STROKE); paint1.setStrokeWidth(dip2px(context, 10)); paint1.setStrokeCap(Paint.Cap.ROUND); width = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth(); circleRadius = width / 4; circleEndy = circleStartY + circleRadius * 2; rectF = new RectF(width / 2 - circleRadius, circleStartY, width / 2 + circleRadius, circleEndy);// 弧形 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 第一個參數是圓的大小,根據矩陣來控制。第二個參數是在哪個點起始,已順時針方向走,所以說90為正下方。0為最右邊。第三個參數是圓的度數360為一圈 canvas.drawArc(rectF, 90, 360, false, paint); //這裡等級為4/1等級,所以是90 canvas.drawArc(rectF, 90, 90, false, paint1); } /**傳入dp,返回px*/ public float dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (float) (dpValue * scale + 0.5f); }
效果如下:
效果已經畫出來了。但是缺少點東西,現在view裡面東西全是死的,得讓他活起來,並且具有動畫,滿級之後自動反0操作。所以我加了以下代碼
/** 背景圓的畫筆 */ private Paint paint; /** 進度條圓的畫筆 */ private Paint paint1; /** 設定矩陣的座標點 */ private RectF rectF; /** 螢幕的高度 */ private int width = 0; /** 園的半徑 */ private int circleRadius = 0; /** 園的y軸起始座標 */ private int circleStartY = 20; /** 園的y軸終點座標 起始座標加上園的半徑*2 */ private int circleEndy = 0; /** 初始進度 */ private float currentPorcent = 0; /** 進度是多少 */ private float maxPorcent = 0; /**滿級回調*/ public RestoreCirclr rc; /** 是否還原 */ public boolean isRestore = false; /**我一般喜歡直接寫3個構造方法,方便引用*/ public CircleView(Context context) { super(context); init(context); } public CircleView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } /**初始化畫筆*/ private void init(Context context){ paint = new Paint();// 布局xml裡面引用 paint1 = new Paint();// 布局xml裡面引用 paint.setAntiAlias(true);// 設定消除鋸齒 paint.setColor(getResources().getColor(R.color.char_circlebackground)); paint.setStyle(Style.STROKE);// 設定圓心掏空 paint.setStrokeWidth(dip2px(context, 10)); // 設定畫筆形狀 圓形,需要先設定畫筆樣式 SYROKE 或者 FILL_AND_STROKE paint.setStrokeCap(Paint.Cap.ROUND); paint1.setAntiAlias(true);// 設定消除鋸齒 paint1.setColor(getResources().getColor(R.color.char_circleplan)); paint1.setStyle(Style.STROKE); paint1.setStrokeWidth(dip2px(context, 10)); paint1.setStrokeCap(Paint.Cap.ROUND); width = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth(); circleRadius = width / 4; circleEndy = circleStartY + circleRadius * 2; rectF = new RectF(width / 2 - circleRadius, circleStartY, width / 2 + circleRadius, circleEndy);// 弧形 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 第一個參數是圓的大小,根據矩陣來控制。第二個參數是在哪個點起始,已順時針方向走,所以說90為正下方。0為最右邊。第三個參數是圓的度數360為一圈 canvas.drawArc(rectF, 90, 360, false, paint); //這裡等級為4/1等級,所以是90 canvas.drawArc(rectF, 90, currentPorcent, false, paint1); if (currentPorcent == 0) { handler.postDelayed(drawRunnable, 0); } } /**啟動動畫重新整理介面*/ public void invalidateView(){ handler.postDelayed(drawRunnable, 0); } private Handler handler = new Handler(); Runnable drawRunnable = new Runnable() { @Override public void run() { if (!isRestore) {//有經驗時動畫 if (currentPorcent >= maxPorcent) { currentPorcent = maxPorcent; invalidate(); //移除當前Runnable handler.removeCallbacks(drawRunnable); } else { currentPorcent += 5;//這裡是動畫速度,當前為5。可自己去調試經驗值增長速度 handler.postDelayed(drawRunnable, (long) (1300 / maxPorcent)); invalidate(); } if (currentPorcent == 360) { if (rc != null) { isRestore = rc.OnRestoreCirclr(); handler.postDelayed(drawRunnable, 0); } } } else {//滿級之後經驗條動畫返回0進度 if (currentPorcent <= 0) { currentPorcent = 0; invalidate(); handler.removeCallbacks(drawRunnable); } else { currentPorcent -= 3;//這裡是動畫速度,當前為3。可自己去調試經驗值反0速度 handler.postDelayed(drawRunnable, (long) (1300 / maxPorcent)); invalidate(); } } } }; public boolean isRestore() { return isRestore; } public void setRestore(boolean isRestore) { this.isRestore = isRestore; } /** 設定等級進度,傳入升級經驗,以及當前經驗 maxPorcent就是當前經驗在升級經驗占的百分比*/ public void setCirclePlan(int max, int current) { maxPorcent = (int) (((float)360 / (float)max) * current); } /**傳入dp,返回px*/ public float dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (float) (dpValue * scale + 0.5f); } /** 設定園線的顏色 */ public void setCircleColor(int color) { paint.setColor(color); } /** 設定進度線的顏色 */ public void setCirclePlanColor(int color) { paint1.setColor(color); } public void setRc(RestoreCirclr rc) { this.rc = rc; } public interface RestoreCirclr { public boolean OnRestoreCirclr(); }
在mainActivity裡面調用代碼如下:
private CircleView circleView; /** 升級經驗為100 */ private int max ; /** 目前經驗值為10 */ private int current ; /** 經驗加10 */ private Button button_1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); circleView = (CircleView) findViewById(R.id.circleView); button_1 = (Button) findViewById(R.id.button_1); button_1.setOnClickListener(this); max = 100; current = 10; circleView.setCirclePlan(max, current);// 進度條已滿 升級數是100,當前經驗數是10 circleView.setRc(new RestoreCirclr() {// 滿級之後的回調 @Override public boolean OnRestoreCirclr() { //滿級之後的操作 返回true就回到原點 current=0; return true; } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button_1: current += 10; circleView.setRestore(false); //false經驗值增加 circleView.setCirclePlan(max, current); circleView.invalidateView();//重新整理view break; } }
:
由於本人第一次寫部落格,不會製作那種可動的gif圖片,所以導致動畫效果看不見。如果各位有興趣的看看動畫效果可去(http://download.csdn.net/detail/u013895206/8431395)這個地址下載源碼。
本篇自訂view學習就到這裡,歡迎大家指正錯誤。互相學習。第一次專註的寫部落格,希望各位大大多多支援。提前祝福兄弟姐妹們新年快樂。。
未完待續、、、