Android自定義控件之自定義屬性(二)
前言:
上篇介紹了自定義控件的基本要求以及繪制的基本原理,本篇文章主要介紹如何給自定義控件自定義一些屬性。本篇文章將繼續(xù)以上篇文章自定義圓形百分比為例進(jìn)行講解。有關(guān)原理知識請參考Android自定義控件基本原理詳解(一)這篇文章。
需求產(chǎn)生背景:
為何要引入自定義屬性?當(dāng)Android提供的原生屬性不能滿足實(shí)際的需求的時候,比如我們需要自定義圓形百分比半徑大小、圓形背景、圓形顯示的位置、圓形進(jìn)度的背景等等。這個時候就需要我們自定義屬性了。
自定義屬性步驟:
1.)在res/values文件下添加一個attrs.xml文件,如果項目比較大的話,會導(dǎo)致attrs.xml代碼相當(dāng)龐大,這時可以根據(jù)相應(yīng)的功能模塊起名字,方便查找,例如:登錄模塊相關(guān)attrs_login.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="RoundImageView"> <attr name="borderRadius" /> <attr name="type" /> </declare-styleable> </resources>
2.)如何聲明一組屬性
使用<declare-styleable name="PercentView"></declare-styleable>來定義一個屬性集合,name就是屬性集合的名字,這個名字一定要起的見名知意。
<declare-styleable name="PercentView"> <!--添加屬性--> </declare-styleable>
然后就是定義屬性值了,通過<attr name="textColor" format="color" /> 方式定義屬性值,屬性名字同樣也要起的見名知意,format表示這個屬性的值的類型,類型有以下幾種:
•reference:引用資源
•string:字符串
•Color:顏色
•boolean:布爾值
•dimension:尺寸值
•float:浮點(diǎn)型
•integer:整型
•fraction:百分?jǐn)?shù)
•enum:枚舉類型
•flag:位或運(yùn)算
基于上面的要求,我們可以定義一下百分比控件屬性
<declare-styleable name="PercentView"> <attr name="percent_circle_gravity"><!--圓形繪制的位置--> <flag name="left" value="0" /> <flag name="top" value="1" /> <flag name="center" value="2" /> <flag name="right" value="3" /> <flag name="bottom" value="4" /> </attr> <attr name="percent_circle_radius" format="dimension" /><!--圓形半徑--> <attr name="percent_circle_progress" format="integer" /><!--當(dāng)前進(jìn)度值--> <attr name="percent_progress_color" format="color" /><!--進(jìn)度顯示顏色--> <attr name="percent_background_color" format="color" /><!--圓形背景色--> </declare-styleable>
3.)布局中如何使用
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:lee="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.whoislcj.views.PercentView android:layout_width="200dp" android:layout_height="200dp" android:layout_margin="10dp" android:background="@color/red" android:padding="10dp" lee:percent_background_color="@color/gray" lee:percent_circle_gravity="left" lee:percent_circle_progress="30" lee:percent_circle_radius="50dp" lee:percent_progress_color="@color/blue" /> </LinearLayout>
為屬性集設(shè)置一個屬性集名稱,我這里用的lee,我這是因?yàn)閷?shí)在想不起使用什么屬性集名稱了,建議在真正的項目中使用項目的縮寫,比如微信可能就是使用wx。
4.)自定義控件中如何獲取自定義屬性
每一個屬性集合編譯之后都會對應(yīng)一個styleable對象,通過styleable對象獲取TypedArray typedArray,然后通過鍵值對獲取屬性值,這點(diǎn)有點(diǎn)類似SharedPreference的取法。
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PercentView);
if (typedArray != null) {
backgroundColor = typedArray.getColor(R.styleable.PercentView_percent_background_color, Color.GRAY);
progressColor = typedArray.getColor(R.styleable.PercentView_percent_progress_color, Color.BLUE);
radius = typedArray.getDimension(R.styleable.PercentView_percent_circle_radius, 0);
progress = typedArray.getInt(R.styleable.PercentView_percent_circle_progress, 0);
gravity = typedArray.getInt(R.styleable.PercentView_percent_circle_gravity, CENTER);
typedArray.recycle();
}
5.)完整示例
public class PercentView extends View {
private final static String TAG = PercentView.class.getSimpleName();
private Paint mPaint;
private int backgroundColor = Color.GRAY;
private int progressColor = Color.BLUE;
private float radius;
private int progress;
private float centerX = 0;
private float centerY = 0;
public static final int LEFT = 0;
public static final int TOP = 1;
public static final int CENTER = 2;
public static final int RIGHT = 3;
public static final int BOTTOM = 4;
private int gravity = CENTER;
private RectF rectF; //用于定義的圓弧的形狀和大小的界限
public PercentView(Context context) {
super(context);
init();
}
public PercentView(Context context, AttributeSet attrs) {
super(context, attrs);
initParams(context, attrs);
init();
}
public PercentView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initParams(context, attrs);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
rectF = new RectF();
}
private void initParams(Context context, AttributeSet attrs) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
rectF = new RectF();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PercentView);
if (typedArray != null) {
backgroundColor = typedArray.getColor(R.styleable.PercentView_percent_background_color, Color.GRAY);
progressColor = typedArray.getColor(R.styleable.PercentView_percent_progress_color, Color.BLUE);
radius = typedArray.getDimension(R.styleable.PercentView_percent_circle_radius, 0);
progress = typedArray.getInt(R.styleable.PercentView_percent_circle_progress, 0);
gravity = typedArray.getInt(R.styleable.PercentView_percent_circle_gravity, CENTER);
typedArray.recycle();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
Log.e(TAG, "onMeasure--widthMode-->" + widthMode);
switch (widthMode) {
case MeasureSpec.EXACTLY://
break;
case MeasureSpec.AT_MOST:
break;
case MeasureSpec.UNSPECIFIED:
break;
}
Log.e(TAG, "onMeasure--widthSize-->" + widthSize);
Log.e(TAG, "onMeasure--heightMode-->" + heightMode);
Log.e(TAG, "onMeasure--heightSize-->" + heightSize);
int with = getWidth();
int height = getHeight();
Log.e(TAG, "onDraw---->" + with + "*" + height);
centerX = with / 2;
centerY = with / 2;
switch (gravity) {
case LEFT:
centerX = radius + getPaddingLeft();
break;
case TOP:
centerY = radius + getPaddingTop();
break;
case CENTER:
break;
case RIGHT:
centerX = with - radius - getPaddingRight();
break;
case BOTTOM:
centerY = height - radius - getPaddingBottom();
break;
}
float left = centerX - radius;
float top = centerY - radius;
float right = centerX + radius;
float bottom = centerY + radius;
rectF.set(left, top, right, bottom);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.e(TAG, "onLayout");
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(backgroundColor);
// FILL填充, STROKE描邊,FILL_AND_STROKE填充和描邊
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawCircle(centerX, centerY, radius, mPaint);
mPaint.setColor(progressColor);
double percent = progress * 1.0 / 100;
int angle = (int) (percent * 360);
canvas.drawArc(rectF, 270, angle, true, mPaint); //根據(jù)進(jìn)度畫圓弧
}
}
運(yùn)行結(jié)果:
根據(jù)不同的配置顯示的兩種效果
小結(jié):
通過自定義屬性可以達(dá)到自定義的控件也能像原生的控件一樣實(shí)現(xiàn)可配置。但是在實(shí)際的項目開發(fā)中,像本文介紹的這種自定義控件使用頻率并不是最高的,使用頻率較高的是通過自定義一個組合控件的方式,來達(dá)到布局文件的復(fù)用,以減少項目維護(hù)成本以及開發(fā)成本,下篇文章將重點(diǎn)介紹如何自定義控件組合,點(diǎn)擊查看。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android自定義控件實(shí)現(xiàn)滑動開關(guān)效果
- android自定義控件創(chuàng)建翻頁接口詳細(xì)代碼
- Android自定義控件實(shí)現(xiàn)手勢密碼
- Android自定義控件實(shí)現(xiàn)可左右滑動的導(dǎo)航條
- Android自定義控件實(shí)現(xiàn)邊緣凹凸的卡劵效果
- Android自定義控件簡單實(shí)現(xiàn)側(cè)滑菜單效果
- Android自定義控件之廣告條滾動效果
- Android自定義控件之仿優(yōu)酷菜單
- Android自定義控件之開關(guān)按鈕學(xué)習(xí)筆記分享
- Android自定義控件實(shí)現(xiàn)簡單的輪播圖控件
相關(guān)文章
Android部分手機(jī)拍照后獲取的圖片被旋轉(zhuǎn)問題的解決方法
這篇文章主要為大家詳細(xì)介紹了Android部分手機(jī)拍照后獲取的圖片被旋轉(zhuǎn)問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01
Android實(shí)現(xiàn)自定義View控件的流程詳解
這篇文章主要為大家詳細(xì)介紹了Android中實(shí)現(xiàn)自定義View控件的流程,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解一下2023-06-06
Android WebView userAgent 設(shè)置為桌面UA實(shí)例
這篇文章主要介紹了Android WebView userAgent 設(shè)置為桌面UA實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android實(shí)現(xiàn)帶頭像的用戶注冊頁面
這篇文章主要介紹了Android實(shí)現(xiàn)帶頭像的用戶注冊頁面的相關(guān)資料,介紹的非常詳細(xì),具有參考借鑒價值,需要的朋友可以參考下2016-06-06

