教育行業(yè)A股IPO第一股(股票代碼 003032)

全國(guó)咨詢/投訴熱線:400-618-4000

Android培訓(xùn)之自定義View那些事

更新時(shí)間:2016年07月13日17時(shí)29分 來(lái)源:Android培訓(xùn)學(xué)院 瀏覽次數(shù):

自定義View那些事

前言

Android系統(tǒng)已經(jīng)為我們提供了有各種功能的View了,如顯示文本的,圖片的,還提供了一些ViewGroup控制子View顯示的,如ListView,LinearLayout,RelativeLayout,然而呢,面對(duì)復(fù)雜多變的產(chǎn)品需求,這些還是無(wú)法滿足。在黑馬的課程中,我們有4天的專門(mén)講解自定義View知識(shí)的課程,也在4個(gè)項(xiàng)目中去穿插的講解自定義控件,可以說(shuō)算是比較全面了。今天我從幾個(gè)方面綜合講解下如何去自定義出你想要的View。
 

分析

當(dāng)我們說(shuō)要自定義一個(gè)View時(shí),其實(shí)你是在想自定義這個(gè)View的這些方面:
1. 你想自定義這個(gè)View上顯示的內(nèi)容
2. 你想自定義這個(gè)View中子View的擺放位置
3. 你想讓這個(gè)View跟隨手指的移動(dòng)進(jìn)行某些變化
 
所以,我們就從這4個(gè)方面來(lái)學(xué)習(xí)如何自定義效果。
 

實(shí)踐

如何自定義View顯示的內(nèi)容

首先,你要知道想自定義View應(yīng)該去繼承自誰(shuí),到底是View還是ViewGroup;如果你只是想自定義單個(gè)View的內(nèi)容,那么應(yīng)該繼承自View;如果你想自定義一個(gè)布局的顯示內(nèi)容,那么應(yīng)該繼承ViewGroup。
現(xiàn)在我們?cè)O(shè)定需求,要做一個(gè)顯示一個(gè)紅色圓形的View,那么你要繼承View,重寫(xiě)onDraw方法,因?yàn)閛nDraw方法就是允許自定義顯示內(nèi)容的方法。我們?cè)诶锩胬L制一個(gè)圓,代碼如下:
 
public class CircleView extends View{
Paint paint = new Paint();
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setColor(Color.RED);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(getWidth()/2, getHeight()/2, 50, paint);
}
}
 
效果圖如下:
 
 
下面呢,我們?cè)谠O(shè)一個(gè)復(fù)雜點(diǎn)的需求,要求自定義一個(gè)顯示一個(gè)紅色對(duì)勾的View,這時(shí)候要繪制對(duì)勾,需要借助Path類來(lái)勾勒。代碼如下:
 
public class TickView extends View{
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Path path = new Path();
public TickView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setColor(Color.RED);
paint.setStrokeWidth(8);
paint.setStyle(Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.moveTo(100, 100);
path.lineTo(140, 140);
path.lineTo(220, 60);
canvas.drawPath(path, paint);
}
}
 
效果圖如下:
 
 
Ok,以上這些就是如何自定義View內(nèi)容的技巧,當(dāng)然如果你想繪制更加復(fù)雜的效果,那就要仔細(xì)學(xué)習(xí)一下Canvas和Path的api了。
 

如何自定義View中子View的位置

此處由于你要自定義的View中是包含子View的,那么你應(yīng)該繼承ViewGroup,并且通常情況下,我們?yōu)榱耸∪?shí)現(xiàn)onMeasure方法,那么就可以繼承系統(tǒng)提供的某個(gè)布局,如FrameLayout。自定義子View的位置,那么需要重寫(xiě)onLayout方法了,該方法是允許你隨意指定子View位置的。
現(xiàn)在我們?cè)O(shè)定需求,要求實(shí)現(xiàn)一個(gè)ViewGroup,它的子View是從右往左邊排列的。代碼如下:
 
public class RightLayout extends FrameLayout{
public RightLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
View child1 = getChildAt(0);
View child2 = getChildAt(1);
child1.layout(getMeasuredWidth()-child1.getMeasuredWidth(),
getPaddingTop(),getMeasuredWidth(),
getPaddingTop()+child1.getMeasuredHeight());
child2.layout(child1.getLeft()-child2.getMeasuredWidth(), getPaddingTop(),getMeasuredWidth()-child1.getMeasuredWidth(),
getPaddingTop()+child2.getMeasuredHeight());
}
}
 
效果圖如下:
 
 
總結(jié),通過(guò)layout的方法來(lái)控制View的位置,這個(gè)屬于比較簡(jiǎn)單的。
 

如何讓View隨手指移動(dòng)進(jìn)行變化

要實(shí)現(xiàn)這個(gè),那么你需要完成2個(gè)點(diǎn):
1. 監(jiān)聽(tīng)手指移動(dòng)的距離
2. 讓View進(jìn)行一些變化
 
對(duì)于第一點(diǎn),監(jiān)聽(tīng)手指移動(dòng)的距離,這個(gè)很簡(jiǎn)單,可以重寫(xiě)onTouch方法,獲取手指移動(dòng)距離,也可以借助ViewDragHelper所封裝的方法來(lái)監(jiān)聽(tīng)手指的移動(dòng)。對(duì)于通過(guò)onTouch方法來(lái)獲取手指移動(dòng)距離的代碼略過(guò),下面展示一下通過(guò)ViewDragHelper來(lái)獲取手指距離的代碼,你需要熟悉一下ViewDragHelper的用法才能看懂下面的代碼,clampViewPositionHorizontal方法的dx參數(shù)就是手指移動(dòng)的距離,代碼如下:
 
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//dx就是手指移動(dòng)的距離
return super.clampViewPositionHorizontal(child, left, dx);
}
 
所以,獲取手指移動(dòng)距離很簡(jiǎn)單,我們主要把精力放在讓View進(jìn)行一些變化上。
這些變化一般是的是縮放,平移,透明,旋轉(zhuǎn)的變化,這些變化Android都為我們提供了對(duì)應(yīng)的操作View屬性的方法,代碼如下:
 
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//dx就是手指移動(dòng)的距離
//平移
view.setTranslationX(dx);
//縮放
view.setScaleX(0.1f);
view.setScaleY(0.1f);
//透明
view.setAlpha(0.1f);
//旋轉(zhuǎn)
view.setRotation(180);
 
return super.clampViewPositionHorizontal(child, left, dx);
}
 
當(dāng)然如果你需要讓View執(zhí)行某些動(dòng)畫(huà)效果,那么你要借助屬性動(dòng)畫(huà)了,如果你想自定義動(dòng)畫(huà)效果,那么就需要使用ValueAnimator,或者繼承Animaton類實(shí)現(xiàn)自定義動(dòng)畫(huà)。
 

總結(jié)

以上總結(jié)了我們自定義View中最常用的情景,當(dāng)然還有其他很多情況。不過(guò)我們可以在這3種基礎(chǔ)上舉一反三。遇到復(fù)雜的效果,就分離模塊,一點(diǎn)一點(diǎn)實(shí)現(xiàn),自定義View也就那么點(diǎn)事。
 
 
 
 本文版權(quán)歸傳智播客Android培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
作者:傳智播客Android培訓(xùn)學(xué)院
首發(fā):http://metathetuscanyresort.com/Android
 
 
 
 
 
0 分享到:
和我們?cè)诰€交談!