3個自定義view佈局:矩形TextView,圓形進度條,圓環view
注:本文3個自定義view佈局共用使用一個xml檔案,
1.自定義矩形TextView的view
package com.bwie.CustomView.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.widget.TextView; import com.bwie.CustomView.R; /**
自定義矩形TextView的view
*/
public class CustomTextView extends TextView{ private String text; private int color; private Paint paint; private int size; private Rect rect; public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); //通過context.obtainStyledAttributes()方法讀取自定義view的屬性 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView); //獲取自定義view的屬性的數量 int count = typedArray.getIndexCount(); //通過下標獲取自定義view的屬性 for (int i=0;i<count;i++){ int indexAttr = typedArray.getIndex(i); switch (indexAttr){ //獲取自定義view的text屬性 case R.styleable.CustomTextView_text: text = typedArray.getString(indexAttr); break; //獲取自定義view的color屬性,先設定一個預設顏色 case R.styleable.CustomTextView_textColor: color = typedArray.getInt(indexAttr, Color.YELLOW); break; //獲取自定義view的size屬性 case R.styleable.CustomTextView_textSize: //通過下面前2行程式碼的方法轉換獲取的size屬性資料 DisplayMetrics metrics = getResources().getDisplayMetrics(); float dimension = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 18, metrics); size = typedArray.getDimensionPixelSize(indexAttr, (int) dimension); break; } } //資料不用時,回收以下 typedArray.recycle(); //設定畫筆的size paint = new Paint(); paint.setTextSize(size); //設定一個矩形。對text內容進行測量 rect = new Rect(); paint.getTextBounds(text,0,text.length(),rect); } /** * onMeasure方法:計運算元控制元件的尺寸和模式,以及設定自己的寬和高,測量View大小 widthMeasureSpec:當前父容器的widthMeasureSpec heightMeasureSpec:當前父容器的heightMeasureSpec 使用的是onMeasure函式,關於三種測量模式mode說法: (1)EXACTLY:一般是設定了明確的值(100dp)或者是MATCH_PARENT; (2)AT_MOST:表示子佈局限制在一個最大值內,一般為WARP_CONTENT; (3)UNSPECIFIED:表示子佈局想要多大就多大,很少使用; */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //計算當前父容器下view的模式 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); //計算當前父容器下view的size int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); System.out.println("width = " + width); System.out.println("height = " + height); } //onDraw方法:繪圖方法(canvas畫布) @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //getWidth(): View在設定好佈局後,整個View的寬度 getHeight(): View在設定好佈局後,整個View的高度 int widht = getWidth(); int height = getHeight() ; //獲取矩形的寬高 int rectWidth = rect.width(); int rectHeight = rect.height(); //設定畫筆的顏色 paint.setColor(Color.YELLOW); //drawRect 就是使用畫筆繪製一個矩形 前面兩個引數代表起始座標, 也就是左上角 後面兩個引數可以標識你想畫的長度和寬度 也可以理解為右下角的座標點。 canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint); //設定畫筆畫出的內容顏色,設定畫出內容的所在位置座標 paint.setColor(color); /** * drawText方法:繪製文字。引數: * text:要繪製的文字 * x:繪製原點x座標 * y:繪製原點y座標 * paint:用來做畫的畫筆 */ canvas.drawText(text,(getWidth()-rect.width())/2,(getHeight()+rect.height())/2,paint); System.out.println("getWidth() = " + getWidth()); System.out.println("getMeasuredWidth() = " + getMeasuredWidth()); } /** * * @param w view改變後當前的寬 * @param h view改變後當前的高 * @param oldw view改變前的寬 * @param oldh view改變前的高 */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); System.out.println("w = " + w + " " + h + " " + oldw + " " + oldh); } public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
※ 在values資料夾下的自定義矩形TextView使用的自定義屬性xml檔案
<?xml version="1.0" encoding="utf-8"?> <resources> <!--在declare-styleable控制元件中寫自定義view的屬性--> <!-- format表示自定義view屬性值的取值型別 --> <declare-styleable name="CustomTextView"> <attr name="text" format="string"/> <attr name="textSize" format="dimension"/> <attr name="textColor" format="color"/> </declare-styleable> </resources>
2. 自定義圓形進度條view
package com.bwie.CustomView.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * 自定義顯示圓形進度條的view */ public class CustomProgressView extends View{ private boolean runing = true; private int progress = 0; private Paint paint; public CustomProgressView(Context context) { super(context); } public CustomProgressView(Context context, AttributeSet attrs) { super(context, attrs); //建立一個畫筆 paint = new Paint(); //設定畫筆的顏色 paint.setColor(Color.BLUE); //設定畫筆的style:內容是填充的空心圓 paint.setStyle(Paint.Style.STROKE); //執行進度條是耗時操作,需放在子執行緒中執行 new Thread(new Runnable() { @Override public void run() { while (runing){ if (progress >= 360){ runing = false; return; } progress += 10; //子執行緒重新整理方法:postInvalidate(),此事系統會呼叫onDraw()方法 postInvalidate(); try { Thread.sleep(188); }catch (Exception e){ e.printStackTrace(); } } } }).start(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //(1)獲取當前自定義view的寬高度 int x = getWidth() / 2; int y = getHeight() / 2; //(2)設定圓半徑的大小 int radius = 300; //(3)設定畫筆的粗細 paint.setStrokeWidth(18); //(4)定義一個矩形區域:RectF物件持有一個矩形的四個float座標值 RectF rectF = new RectF(x - radius, y - radius, x + radius, y + radius); /** * 畫一個圓弧:drawArc方法:繪製圓弧,該方法用於在畫布上繪製圓弧,通過指定圓弧所在的橢圓物件、起始角度、終止角度來實現。 * oval:圓弧所在的橢圓物件。 startAngle:圓弧的起始角度。 sweepAngle:圓弧的角度。 useCenter:是否顯示半徑連線,true表示顯示圓弧與圓心的半徑連線,false表示不顯示。 paint:繪製時所使用的畫筆。 */ canvas.drawArc(rectF,-90,progress,false,paint); //(5)把progress轉換為int值 int intProgress = (int) ((float)progress/360 * 100); //(6) measureText 測量字串的寬度 float textWidth = paint.measureText(intProgress + "%"); //定義一個矩形區域:Rect物件持有一個矩形的四個integer座標值 Rect rect = new Rect(); //測量矩形中內容 paint.getTextBounds(intProgress+"%",0,(intProgress+"%").length(),rect); //設定畫筆寫出內容的size和畫筆的粗細西 paint.setTextSize(90); paint.setStrokeWidth(1); //畫出文字 rect.height() 獲取字串的高度 /** * drawText方法引數: * text:要繪製的文字 * x:繪製原點x座標 * y:繪製原點y座標 * paint:用來做畫的畫筆 */ canvas.drawText(intProgress+"%",x-textWidth/2,y+rect.height()/2,paint); } public CustomProgressView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
3. 自定義圓環view
package com.bwie.CustomView.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * 自定義圓環view */ public class CustomCircleView extends View{ private Paint paint; private int xCircle = 200; //圓心的x座標 private int yCircle = 200; //圓心的y座標 public CustomCircleView(Context context) { super(context); } //CustomCircleView方法:設定自定義圓形view的檢視 public CustomCircleView(Context context, AttributeSet attrs) { super(context, attrs); //設定畫筆的顏色,style,setAntiAlias 抗鋸齒形式(true為去除鋸齒,false則不去),setStrokeWidth方法:設定空心線寬 paint = new Paint(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.STROKE); paint.setAntiAlias(true); paint.setStrokeWidth(80); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: //getRawX()和getRawY()獲得的是相對螢幕的位置 System.out.println("按下時: x "+event.getRawX()+" y "+event.getRawY()); break; case MotionEvent.ACTION_MOVE: //getRawX()和getRawY()獲得的是相對螢幕的位置 System.out.println("移動時: x "+event.getRawX()+" y "+event.getRawY()); //獲取滑鼠移動時的座標,為X軸和Y軸座標重新賦值:getX()和getY()獲得的永遠是view的觸控位置座標 xCircle = (int) event.getX(); yCircle = (int)event.getY(); /** * Android提供了Invalidate方法實現介面重新整理,但是Invalidate不能直接線上程中呼叫,因為他是違背了單執行緒模型: 1. Android UI操作並不是執行緒安全的,並且這些操作必須在UI執行緒中呼叫。 invalidate()是用來重新整理View的,必須是在UI執行緒中進行工作。比如在修改某個view的顯示時,呼叫invalidate()才能看到重新繪製的介面。invalidate()的呼叫是把之前的舊的view從主UI執行緒佇列中pop掉。 2.Android 程式預設情況下也只有一個程式,但一個程式下卻可以有許多個執行緒。在這麼多執行緒當中,把主要是負責控 制UI介面的顯示、更新和控制元件互動的執行緒稱為UI執行緒,由於onCreate()方法是由UI執行緒執行的,所以也可以把UI執行緒理解 為主執行緒。其餘的執行緒可以理解為工作者執行緒。invalidate()得在UI執行緒中被調動,在工作者執行緒中可以通過Handler來通 知UI執行緒進行介面更新。而postInvalidate()在工作者執行緒中被呼叫。 */ invalidate(); break; case MotionEvent.ACTION_UP: //getRawX()和getRawY()獲得的是相對螢幕的位置 System.out.println("抬起時: x "+event.getRawX()+" y "+event.getRawY()); break; } return true; } /** * onMeasure方法:計運算元控制元件的尺寸和模式,以及設定自己的寬和高 widthMeasureSpec:當前父容器的widthMeasureSpec heightMeasureSpec:當前父容器的heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } //onDraw方法:繪圖方法(canvas畫布) @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /** * canvas.drawCircle()方法:該方法用於在畫布上繪製圓形,通過指定圓形圓心的座標和半徑來實現。該方法是繪製圓形的主要方法,同時也可以通過設定畫筆的空心效果來繪製空心的圓形。 * cx:圓心的x座標。 cy:圓心的y座標。 radius:圓的半徑。 paint:繪製時所使用的畫筆。 */ canvas.drawCircle(xCircle,yCircle,200,paint); } public CustomCircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
4. 3個自定義view共用的xml檔案
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 如上:自定義view的佈局檔案必寫屬性:xmlns:app="http://schemas.android.com/apk/res-auto"--> <!-- 自定義矩形TextView的view控制元件屬性 --> <!-- 自定義view的屬性宣告時使用 app: 字首 --> <com.bwie.CustomView.view.CustomTextView android:layout_centerInParent="true" android:layout_marginTop="28dp" android:layout_width="188dp" android:layout_height="188dp" app:textSize="18sp" app:text="自定義TextView" app:textColor="@color/colorAccent" /> <!-- 自定義圓形進度條view時的控制元件屬性 --> <!-- <com.bwie.CustomView.view.CustomProgressView android:layout_width="match_parent" android:layout_height="match_parent" />--> <!-- 自定義圓形view時的控制元件屬性 --> <!-- <com.bwie.CustomView.view.CustomCircleView android:layout_width="match_parent" android:layout_height="match_parent" />--> </RelativeLayout>
相關文章
- Android進階 自定義View(三)圓形刻度進度條AndroidView
- 自定義view - 進度條View
- Android自定義View——從零開始實現圓形進度條AndroidView
- 自定義圓形進度條
- 圓形進度條+二維碼掃描+自定義組合控制元件標題欄+自定義矩形view+介面回撥方法控制元件View
- ios自定義圓環進度條iOS
- Android 自定義 View:包含多種狀態的下載用圓形進度條AndroidView
- Android自定義圓形進度條Android
- 自定義view實現半圓環View
- Android自定義圓形進度條原始碼解析Android原始碼
- Anroid自定義View-繪製圓環View
- Android自定義View(四)側滑佈局AndroidView
- Android自定義圓形進度條實現程式碼Android
- [-Flutter 自定義元件-] 圓形進度條Flutter元件
- objc系列譯文(3.3):自定義Collection View佈局OBJView
- 利用Xfermode 自定義形狀ViewView
- 安卓自定義View進階:繪製基本形狀安卓View
- CSS3圓形進度條效果CSSS3
- 自定義圓形View:實現跟隨手指移動的小球View
- Android Paint應用之自定義View實現進度條控制元件AndroidAIView控制元件
- 自定義view實現圓角圖片View
- 自定義隨機顏色的圓形小球view隨手指移動隨機View
- 自定義VIEWView
- Flutter 波浪圓形進度條Flutter
- SVG畫圓形進度條SVG
- 自定義View合輯(3)-下雨View
- Android自定義控制元件系列之圓形進度條的實現Android控制元件
- Android自定義View:View(二)AndroidView
- css3 製作圓環進度條CSSS3
- 自定義進度條
- Android自定義View 百分比進度動畫AndroidView動畫
- Android自定義View實現流式佈局(熱門標籤效果)AndroidView
- 自定義View公式View公式
- Android 自定義圓形旋轉進度條,仿微博頭像載入效果Android
- 自定義View實現箭頭沿圓轉動View
- 分享一個Kotlin 寫的超級 簡單的自定義View,圓環統計KotlinView
- Android自定義控制元件實現一個帶文字與數字的圓形進度條Android控制元件
- Android自定義View之圖片外形特效——輕鬆實現圓角和圓形圖片AndroidView特效