編輯:關於Android編程
先給大家展示下效果圖,如果感覺不錯,請參考實現思路:
我們要實現一個自定義的再一個圓形中繪制一個弧形的自定義View,思路是這樣的:
先要創建一個類ProgressView,繼承自View類,然後重寫其中的兩個構造方法,一個是一個參數的,一個是兩個參數的,因為我們要在xml文件中使用該自定義控件,所以必須要定義這個兩個參數的構造函數。創建完了這個類後,我們先不去管它,先考慮我們實現的這個自定義View,我們想讓它的哪些部分可以由使用者自己指定,比如說這個Demo中我們讓他的外面圓的外邊框顏色和寬度,還有扇形部分的顏色,扇形增長的速度等等屬性,這時候我們要在項目工程目錄的res/values目錄下創建一個資源文件命名為attrs(注意,名字隨意,只是大多數情況下都這麼叫而已),然後我們在這個資源文件中添加我們想要的屬性,如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ProgressView"> <!--circleColor 設置圓形邊框的顏色 sweepColor設置扇形變換的顏色 startAngle 設置起始角度 sweepStep 設置變換的步長--> <attr name="circleColor" format="color|reference"></attr> <attr name="sweepColor" format="color|reference"></attr> <attr name="startAngle" format="integer"></attr> <attr name="sweepStep" format="integer"></attr> <attr name="padding" format="integer"></attr> </declare-styleable> </resources>
可以看到,<declare-styleable>標簽中的name屬性是為了方便我們獲取AttributeSet時候使用,而<attr>標簽中name,則是我們希望控件可以自定義的屬性部分,類似於xml文件中的android:name=""等標簽的使用。format屬性是設置該屬性可以接受什麼類型的參數。
定義好了自定義資源類,我們開始寫ProgressView中的主要代碼:
package com.yztc.customprogressview; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * 自定義的 */ public class ProgressView extends View { private int sweepStep = 10;//扇形變換的步長(就是角度) private int padding = 40;//外邊框距離扇形的距離 填充 private int circleColor = Color.GRAY;//邊框的顏色 private int sweepColor = Color.BLUE;//扇形顏色 private int startAngle = 90;//起始角度 //設置外邊框圓的邊框粗細 private int storke = 20; private int sweepAngle = 0;//掃過的角度 private static final int DEFAULT_WIDTH = 200; private static final int DEFAULT_HEIGHT = 200; public ProgressView(Context context) { super(context); } //如果要在xml文件中使用該自定義控件,則必須重寫兩個參數的構造函數 //因為我們使用自定義的屬性的時候,會默認傳遞過來一個AttributeSet集合 public ProgressView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProgressView); if (array != null) { //獲取我們在xml中設置的各個自定義屬性 sweepStep = array.getInteger(R.styleable.ProgressView_sweepStep, sweepStep); padding = array.getInteger(R.styleable.ProgressView_padding, padding); circleColor = array.getColor(R.styleable.ProgressView_circleColor, circleColor); sweepColor = array.getColor(R.styleable.ProgressView_sweepColor, sweepColor); startAngle = array.getInteger(R.styleable.ProgressView_startAngle, startAngle); //回收TypeArray資源 array.recycle(); } } /** * 先繪制外邊框 --內部扇形 * * @param canvas */ @Override protected void onDraw(Canvas canvas) { Paint mPaint = new Paint(); mPaint.setAntiAlias(true); //設置抗鋸齒 //繪制外層的圓框 mPaint.setColor(circleColor); mPaint.setStrokeWidth(storke); mPaint.setStyle(Paint.Style.STROKE);//設置圓形為空心的圓 //這裡我們得到控件的Height和Width,根據Heigh和Width來確定圓心的位置,來繪制外層圓 canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2 - storke / 2, mPaint); // Log.d("tag", "onDraw: "+getWidth()); invalidate();//請求重新繪制view //繪制內部的扇形 mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setColor(sweepColor); /* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint) RectF oval 指定扇形的矩形容器對象 指定圓弧的外輪廓的矩形 float startAngle 表示圓弧的起始角度 float sweepAngle 表示圓弧走過掃過的角度 順時針方向 boolean useCenter 如果設置為true 在繪制圓弧時將圓心包括在內,是指以一個固定的圓心來繪制弧形(扇形), 如果指定為false,則不規則繪制扇形 Paint paint 畫筆 顏色 填充 public RectF(float left, float top, float right, float bottom) float left 矩形的左邊點(左切點)的x坐標 float top 矩形上邊點(上切點)的y軸坐標 float right, 矩形的右邊點(右切點)的x坐標 float bottom 矩形的下邊點(下切點)的y坐標 */ //RectF中的四個參數,分別對應其內切圓的四個切點的坐標 RectF rectF = new RectF(padding + storke, padding + storke, getWidth() - padding - storke, getWidth() - padding - storke); canvas.drawArc(rectF, startAngle, sweepAngle, true, mPaint); sweepAngle += sweepStep;//根據步長更新掃過的角度 sweepAngle = sweepAngle > 360 ? 0 : sweepAngle; invalidate();//重繪view } //因為我們是繼承的View來自定義的View,所以onMeasure()方法要重寫 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int wMode = MeasureSpec.getMode(widthMeasureSpec); int hMode = MeasureSpec.getMode(heightMeasureSpec); int wSize = MeasureSpec.getSize(widthMeasureSpec); int hSize = MeasureSpec.getSize(heightMeasureSpec); //因為繪制的是圓,所以判斷一下高度或者寬度中的一個就可以。 switch (wMode) { case MeasureSpec.AT_MOST://android:layout_width="warp_content" //獲取屏幕像素 float density = getResources().getDisplayMetrics().density; wSize = (int) (DEFAULT_WIDTH * density); hSize = (int) (DEFAULT_HEIGHT * density); break; //當在xml中指定控件的寬高為match_parent或者指定數值的寬高時,回調以下代碼 case MeasureSpec.EXACTLY://android:layout_width="match_parent" android:layout_width="40dp" wSize = hSize = Math.min(wSize, hSize); break; } //只要重寫onMeasure()方法,一定要調用以下方法,不然會報錯 setMeasuredDimension(wSize, hSize); } }
我們先畫一個外部的圓,也就是都用drawCircle()方法,這裡我們調用getWidth(),getHeight()表示得到布局中設置的控件的尺寸,因為是圓,所以可以使用getWidth()/2來表示圓心位置。而畫內部弧形的時候,確定其圓心位置,左部點的坐標是外面圓的邊框加上弧形與原的間距padding來確定,右側點的x坐標則是getWidth()得到總長度,減去邊框寬度,再減去padding得到,上邊距和下邊距同樣,不明白的畫一個圖立馬明白。大部分不好理解的地方都有注釋,只要認真看不會看不明白的~
然後就是在布局中引入我們的自定義View了:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.yztc.customprogressview.MainActivity"> <com.yztc.customprogressview.ProgressView android:id="@+id/pv" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#0000ff" app:padding="20" app:circleColor="#aa0000" app:sweepColor="#00aa00" app:sweepStep="1" app:startAngle="180" /> </RelativeLayout>
需要注意的是我們需要在布局的跟標簽下面加上這麼一段代碼:xmlns:app="http://schemas.android.com/apk/res-auto"
用來指定我們可以使用自己再attrs中自定義的屬性啦~,使用的形式就是app:你定義的屬性。當然,這個app也不是固定的寫法,只要跟上面你加的那段代碼的xmlns後面的字段一致就可以了~
還有需要注意的是:
默認使用Canvas類的drawCircle()方法來畫圓的時候,圓的半徑是你指定的半徑,再加上一半的邊長,比如你的邊框size=10,radius=50,則實際空心部分的半徑為55.注意這點,否則畫出來的圓的四個切點位置會與其他位置有些不一樣,類似出現鋸齒的效果。具體請看drawCircle()的Rect邊框問題。
以上所述是小編給大家介紹的Android自定義View實現簡單的圓形Progress效果,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!
本文介紹了ListView給每個Item上面的按鈕添加事件,具體如下:1.先看下效果圖:在這裡僅供測試,我把數據都寫死了,根據需要可以自己進行修改,此外實現ListVie
可以使用該套 SDK開發適用於Android系統移動設備的地圖應用,通過調用地圖SDK接口,您可以輕松訪問百度地圖服務和數據,構建功能豐富、交互性強的LBS(地圖類)應用
好了,跟隨潮流,還是先看下效果,不然可能都沒人想看下去了(不會看到效果後不想看了吧O(∩_∩)O~)嗯,就是讓左面板在主面板的下面,所以我們自定義的控件S
Gallery 的用法很簡單,百度一下一大堆。現在就結合1個效果的例子。 這個效果其實很簡單,設置未被選中的項,的透明度 周圍的看起來就會有點模糊vcD4KPH