Android 《Android 自定義控件開發入門與實戰》學習筆記(二)

目錄

一、前言

二、學習筆記

第四章:屬性動畫進階

第五章:動畫進階

第六章:Paint基本使用

​三、Demo地址

四、內容推薦


一、前言

自定義控件一直是Android很重要的一部分,但是大部分時間我們可能很少自己去寫控件。因爲現在開源的控件比較多,自定義寫起來也比較麻煩。但是當我們需要的時候可能就忘了,所以菜鳥作者就買了本書打算系統的學習一遍。順便做下筆記,防止以後忘記。

大家可以瀏覽一遍,複習一下鞏固基礎。如果要深入學習這裏也推薦兩位大神博客

https://www.jianshu.com/p/146e5cec4863

https://blog.csdn.net/harvic880925  啓艦《Android 自定義控件開發入門與實戰》

《Android 自定義控件開發入門與實戰》學習筆記(一)

二、學習筆記

第四章:屬性動畫進階 

一、PropertyValuesHolder

簡介:PropertyValuesHolder保存了動畫過程中所需要操作的屬性和對應的值。

1.實例函數:

public static PropertyValuesHolder ofFloat(String propertyName,float... values)
public static PropertyValuesHolder ofInt(String propertyName,int... values)
public static PropertyValuesHolder ofObject(String propertyName,TypeEvaluator evaluator,Object... values)
public static PropertyValuesHolder ofKeyfram(String propertyName,Keyfram... values)
// propertyName:表示屬性名,通過反射查找對應屬性的setProperty()函數。
// values:屬性所對應的參數,同樣是可變長參數,可以指定多個。

2.如何使用:ObjectAnimator提供了一個設置PropertyValuesHolder實例的入口。

//target:執行動畫的控件 values:PropertyValuesHolder實例 ,
傳入多個PropertyValuesHolder實例,則會對控件的多個屬性同時執行動畫操作
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)

3.例:

PropertyValuesHolder holder = PropertyValuesHolder.ofFloat("Rotation",60f,-60f,40f,-40f,-20f,20f,10f)
PropertyValuesHolder holder2 = PropertyValuesHolder.ofObject("CharText",new CharEvaluator(),new Character('A'),new Character('z'));
ObjectAnimator.ofPropertyValuesHolder(mMytV,holder,holder2);
ObjectAnimator.setDuration(3000);
ObjectAnimator.setInterpolator(new AccelerateInterpolator());
ObjectAnimator.start();

二、KeyFrame

簡介:提供方便地控制動畫速率問題。

1.使用方式:

//第一步:生成Keyframe對象
//fraction表示當前的顯示進度  value:表示動畫當前所在的數值位置。
public static Keyframe ofFloat(float fraction,float value);
public static Keyframe ofInt(float fraction,int value);
public static Keyframe ofObject(float fraction,int value);
//第二步:利用PropertyValuesHolder.ofKeyframe()函數生成PropertyValuesHolder對象。
public static PropertyValuesHolder ofKeyframe(String propertyName,Keyframe... values)
//第三步:利用ObjectAnimator.ofPropertyValuesHolder()函數生成對應的Animator
public static ObjectAnimator ofPropertyValuesHolder(View view,PropertyValuesHolder holder)

2.KeyFrame常用函數:

//設置fraction參數,即KeyFrame所對應的進度
public void setFraction(float fraction)
//設置當前Keyframe所對應的值
public void setValue(Object value)
//設置插值器
public void setInterpolator(TimeInterpolator interpolator)

3.PropertyValuesHolder函數:

//設置動畫的Evaluator
public void setEvaluator(TypeEvaluator evaluator)
//用於設置ofFloat()所對應的動畫值列表
public void setFloatValues(float... values)
//用於設置ofInt()所對應的動畫值列表
public void setIntValues(int... values)
//用於設置ofKeyframes()所對應的動畫值列表
public void setKeyframes(Keyframe... values)
//用於設置ofObject()所對應的動畫值列表
public void setObjectValues(Object... values)
//設置動畫屬性名
public void setPropertyName(String propertyName)

三、ViewPropertyAnimator

簡介:Android3.1中新增ViewPropertyAnimator機制,給默認屬性提供了一種更加便捷的用法。

1.例:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview,"alpha",0f);
//轉
textview.animate().alpha(0f);

(1)animate():整個系統從調用View的這個叫做animate()的新函數開始。這個函數會返回一個ViewPropertyAnimator對象,可以通過調用這個對象的函數來設置需要實現動畫的屬性。

(2)自動開始:我們沒有顯示調用過start()函數。在新的API中,啓動動畫是隱式的,在聲明完成後,動畫就開始了。

(3)流暢:ViewPropertyAnimator擁有一個流暢的接口,它允許將多個函數調用很自然地串在一起,並把一個多屬性的動畫寫成一行代碼。

2.常用函數:

屬性設置
alpha(float value) 設置透明度
scaleY(float value) 設置Y軸方向的縮放大小
scaleX(float value) 設置X軸方向的縮放大小
translationY(float value) 設置Y軸方向的移動值
translationX(float value) 設置X軸方向的移動值
rotation(float value) 設置繞Z軸旋轉度數
rotationX(float value) 設置繞X軸旋轉度數
rotationY(float value) 設置繞Y軸旋轉度數
x(float value) 相對於父容器的左上角座標在X軸方向的最終位置
y(float value) 相對於父容器的左上角座標在Y軸方向的最終位置
alphaBy(float value) 設置透明度增量
rotationBy(float value) 設置繞Z軸旋轉增量
rotationXBy(float value) 設置繞X軸旋轉增量
rotationYBy(float value) 設置繞Y軸旋轉增量
translationXBy(float value) 設置X軸方向的移動值增量
translationYBy(float value) 設置Y軸方向的移動值增量
scaleXBy(float value) 設置X軸方向的縮放大小增量
scaleYBy(float value) 設置Y軸方向的縮放大小增量
xBy(float value) 相對於父容器的左上角座標在X軸方向的位置增量
yBy(float value) 相對於父容器的左上角座標在Y軸方向的位置增量
setInterpolator(TimeInterpolator interpolator) 設置插值器
setStarDelay(long startDelay) 設置開始延時
setDuration(long startDelay) 設置動畫時長

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.設置監聽器:

tv.animate().scaleX(2).scaleY(2).setListener(new Animator.AnimatorListener(){
		......
	});

4.animateLayoutChanges屬性:

簡介:Android爲了支持ViewGroup類控件,在添加或移除其中的控件時自動添加動畫。提供了一個非常簡單的屬性

android:animateLayoutChanges="true/false"

5.LayoutTransition

簡介:因爲animateLayoutChanges只能使用默認動畫效果,所以LayoutTransition實現自定義動畫。

使用方式:

    第一步:創建實例
	LayoutTransition transitioner = new LayoutTransition();
	第二步:創建動畫並進行設置
	ObjectAnimator animOut = ObjectAnimator.ofFloat(null,"rotation",0f,90f,0f);
	transitioner.setAnimator(LayoutTransition.DISAPPEARING,animOut);
	第三步:將LayoutTransition設置到ViewGroup中。
	linearLayout.setLayoutTransition(transitioner);
	
	//transitionType表示當前應用動畫的對象範圍。
	public void setAnimator(int transitionType,Animator animator)
	//APPEARING:元素在容器中出現時所定義的動畫
	//DISAPPEARING:元素在容器中消失時所定義的動畫
	//CHANGE_APPEARING:由於容器中要顯現一個新的元素,其他需要變化的元素所應用的動畫。
	//CHANGE_DISAPPEARING:當容器中某個元素消失時,其他需要變化的元素所應用的動畫。

四、開源動畫庫NineOldAndroids

簡介:Android3.0推出了全新的AnimationApi,使用起來很方便,但是不能在3.0以下版本中使用。NineOldAndroids是一個可以在任意Android版本上使用AnimationAPI,和Anidroid 3.0中的API類似。

第五章:動畫進階

1.利用PathMeasure實現路徑動畫

簡介:AndroidSDK提供了一個非常有用的API來幫助開發者實現這樣一個Path路徑點的座標追蹤,這個API就是PathMeasure,通過它就可以實現複雜的動畫效果。

(1)初始化方法:

PathMeasure pathMeasure = new PathMeasure();
或
PathMeasure(Path path,boolean forceClosed);

(2)綁定路徑:

setPath(Path path, boolean forceClosed)

(3)簡單函數使用

//獲取計算的路徑長度
public float getLength();
//用於判斷測量Path時是否計算閉合
public boolean isClosed();
//用於跳轉到下一條曲線的函數
public boolean nextContour();
//用於截取整個Path中的某個片段,通過參數startD和stopD來控制截取的長度,並將截取後
//的Path保存到參數dst中。最後一個參數startWithMoveTo表示起始點是否使用moveTo將路徑的
//新起始點移到結果Path的起始點,通常設置爲true,以保證每次截取的Path都是正常的,完整的,
//通常和dst一起使用,因爲dst中保存的Path是被不斷添加的,而不是每次被覆蓋的。
public boolean getSegment(float startD,float stopD,Path dst,boolean startWithMoveTo);
//用於得到路徑上某一長度的位置以及該位置的正切值。
//distance:距離Path起始點的長度,取值範圍爲0<=distance<=getLength。
//pos:該點的座標值。     tan:該點的正切值。
public boolean getPosTan(float distance,float[] pos,float[] tan);
//用於得到路徑上某一長度的位置以及該位置的正切值的矩陣
public boolean getMatrix(float distance,Matrix matrix,int flags);
例:
public void ondraw(){
    Path path = new Path();
    path.addRect(-50,-50,50,50,Path.Direction.CW);
    path.addRect(-50,-50,50,50,Path.Direction.CW);
    path.addRect(-50,-50,50,50,Path.Direction.CW);
    canvas.drawPath(Path,paint);
    PathMeasure measure = new PathMeasure(path,false);
    do{
        float len = measure.getLength();
        Log.e(TAG,"len="+len);
    }while(measure.nextContour());
}

2.SVG動畫

簡介:Goole在Android 5.0中增加了對SVG圖形的支持。對於5.0以下的機型,可以通過引入com.android.support:appcompat-v7:23.4.0及以上版本進行支持。android並沒有對原生的SVG圖像語法進行支持,而是以一種簡化的方式對SVG進行兼容,也就是通過使用它的path標籤,幾乎可以實現SVG中的其他所有標籤。

在Android中,SVG矢量圖是使用標籤定義的,並存放在res/drawable/目錄下

(1)例:一段簡單的SVG圖像代碼定義如下

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http:/schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="100dp"
    android:viewporWidth="100"
    android:viewportHeight="50">
    <path
            android:name = "bar"
            andorid:pathData = "M50,23 L100,25"
            android:strokeWidth = "2"
            android:strokeColor = "@android:color/darker_gray"/>
</vector>
  • width與height屬性:表示該SVG圖形的具體大小。
  • viewportWidth與viewportHeight屬性:表示SVG圖形劃分的比例。
  • path中字母M表示moveTo,字母L表示lineTo。
  • vector標籤指定的是畫布帶下,而path標籤則指定的是路徑內容

(2)path標籤

常用屬性:

  • android:name:聲明一個標記,類似於ID,便於對其做動畫的時候順利地找到該節點。
  • android:pathData:對SVG矢量圖的描述。
  • android:strokeWidth:畫筆的寬度。
  • android:fillColor:填充顏色。
  • android:fillAlpha:填充顏色的透明度。
  • android:strokeColor:描邊顏色。
  • android:strokeWidth:描邊寬度。
  • android:strokeAlpha:描邊透明度。
  • android:strokeLineJoin:用於指定折線拐角形狀,取值有miter、round、bevel。
  • android:strokeLineCap:畫出線條的終點形狀,取值有butt/round/square
  • android:strokeMiterLimit:設置斜角的上限。
  • android:trimPathStart:用於指定路徑從哪開始,取值爲0~1,表示路徑開始位置的百分比。
  • android:trimPathEnd:用於指定路徑的結束位置,取值爲0~1,表示路徑結束位置的百分比。
  • android:trimPathOffset:用於指定結果路徑的位移距離,取值爲0~1,當取值爲0時,不進行位移;當取值爲1時,位移整條路徑的長度。
  • android:pathData:在path標籤中,主要通過pathData屬性來指定SVG圖像的顯示內容。

pathData屬性除M和L指令以外,還有更多的指令:

  • M = moveto(M X,Y):將畫筆移動到指定的座標位置。
  • L = lineto(L X,Y):畫直線到指定的座標位置。
  • H = horizontal lineto(H X):畫水平線到指定的X座標位置。
  • V = vertical lineto(V Y):畫垂直線到指定的Y座標位置。
  • C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三階貝濟埃曲線。
  • S = smooth curveto(S X2,Y2,ENDX,ENDY):三階貝濟埃曲線。
  • Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二階貝濟埃曲線。
  • T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射前面路徑後的終點。
  • A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧線。
  • Z = closepath():關閉路徑。

(3)Group標籤

簡介:用於定義一系列路徑後者將path標籤分組。

group標籤常用屬性:

  • android:name:組的名字,用於與動畫相關聯
  • android:rotation:指定該組圖像的旋轉度數
  • android:pivotX:定義縮放和旋轉改組時的X參考點
  • android:pivotY:定義縮放和旋轉該組時的Y參考點
  • android:scaleX:指定該組X軸縮放大小
  • android:scaleY:指定該組Y軸縮放大小
  • android:translateX:指定該組沿X軸平移的距離
  • android:translateY:指定該組沿Y軸平移的距離

(4)製作SVG圖像

1.設計軟件:直接使用illustrator或在線SVG工具製作SVG圖像

2.Iconfont:把你想要的矢量圖標打包成一個.ttf文件,在Android中應用這個.ttf文件來方便地加載和指定各種圖標。通過Iconfont公共網站可以下載到每個圖標所對應的SVG文件。例:阿里巴巴矢量圖庫。

(5)在Android中引入SVG圖像

Android不支持SVG圖像解析,必須將SVG圖像轉換成vector標籤描述:

1.在線轉換

2.通過AndroidStudio引入

3.Android中使用ImageView顯示SVG圖像 

  • 1)引入兼容包:appcompat
  • 2)  build.gradle添加對Vector兼容性支持
  • 3)使用: app:srcCompat = "@drawable/svg_line"  ,  setImageResource(R.drawable.svg_line);

3.動態Vector

簡介:實現Vector動畫,首先需要Vector圖像和它所對應的動畫。

(1)Vector圖像

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="100dp"
    android:viewportWidth="100"
    android:viewportHeight="50">
    <path
        android:name="bar"
        android:pathData="M50,23 L100,25"
        android:strokeWidth="2"
        android:strokeColor="@android:color/darker_gray"/>
</vector>

(2)定義Vector圖像動畫

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="trimPathStart"
    android:valueFrom="0"
    android:valueTo="1"
    android:duration="2000"/>

(3)Vector圖像關聯動畫

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/svg_line">
    <target
            android:name="bar"
            android:animation="@animator/anim_trim_start"/>
</animated-vector>

(4)代碼使用

public void start(){
    ImageView imageView = (ImageView)findViewById(R.id.iv);
    AnimatedVectorDrawableCompat compat = AnimatedVectorDrawableCompat.create(this,R.drawable.line_animateed_vector);
    imageView.setImageDrawable(animatedVectorDrawableCompat);
    ((Animatable)imageView.getDrawable()).start();
}

第六章:Paint基本使用

1.硬件加速

簡介:在API11之前是沒有GPU的概念的;在API11之後,在程序集中加入了對GPU加速的支持;在API14之後,硬件加速功能是默認開啓的。硬件加速提高了Android系統顯示和刷新的速度。

缺點:

(1)兼容性問題:由於是將繪製函數轉換成OpenGL指令來繪製,所以必然會存在OpenGL並不能完全支持原始繪製函數的問題,從而造成在打開GPU加速時效果會失效的問題。

(2)內存消耗問題:由於需要OpenGL指令,所以需要把系統中與OpenGL相關的包加載到內存中來。單純的OpenGL API調用會佔用8MB內存,實際內存佔用會更大。

(3)電量消耗問題:多使用一個部件,耗電相應增加。

禁用GPU:針對不同的類型,Android提供了不同的禁用方法,分Application、Activity、Window、View 4個層級。

(1)在AndroidManifest.xml文件中爲application標籤添加如下屬性,即可爲整個應用程序開啓/關閉硬件加速

<application android:hardwareAccelerated = "true" ...>

(2)在activity標籤下使用hardwareAccelerated屬性開啓或關閉硬件加速。

<activity android:hardwareAccelerated = "false"/>

(3)在Window層級上使用如下代碼開啓硬件加速(在View層級上不支持開啓硬件加速):

getWindow().setFlages(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
);

(4)在View層級上使用如下代碼關閉硬件加速(在View層級上不支持開啓硬件加速):

setLayerType(View.LAYER_TYPE_SOFTWARE,null);

2.文字

(1)canvas.DrawText()函數

//text:要繪製的文字
//x:繪製原點x座標
//y:繪製原點y座標
//paint:用來作畫的畫筆
public void drawText(String text,float x,float y,Paint paint)

(2)paint.setTextAlign()函數

  • Paint.Align.LEFT:從原點x.y左側開始繪製
  • Paint.Align.CENTER:使原點x.y正好在所要繪製矩形的正中間
  • Paint.Align.RIGHT:從原點x.y右側開始繪製

(3)繪製四線格與FontMetrics

簡介:除了基線以外,系統在繪製文字時還有4條線,分別是ascent、descent、top和bottom。基線的位置是在構造drawText()函數時由參數y來決定的。而這4條線是由FontMetrics計算出來的

  • ascent:系統推薦的,在繪製單個字符時,字符應當的最高高度所在線
  • descent:系統推薦的,在繪製單個字符時,字符應當的最低高度所在線
  • top:可繪製的最高高度所在線
  • bottom:可繪製的最低高度所在線

這4個成員變量的含義與值的計算方法分別如下:

  • ascent = ascent線的y座標  - baseline線的y座標。
  • descent = descent線的y座標 - baseline線的y座標。
  • top = top線的y座標 -  baseline線的y座標。
  • bottom = bottom線的y座標 - baseline線的y座標。
//獲取FontMetrics對象
Paint paint = new Paint();
Paint.FontMetrics fm = paint.getFontMetrics();
Paint.FontMetricsInt fmInt = paint.getFontMetricsInt();

字符串所佔區域的高度和寬度

1)高度

Paint.FontMetricsInt fm = paint.getFontMetricsInt();
int top = baseLineY + fm.top;
int bottom = baseLineY + fm.bottom;
//所佔區域的高度
int height = bottom - top;

2)寬度

Paint paint = new Paint();
paint.setTextSize(120);
//獲取寬度
int width = (int)paint.measureText("XXXXXX");

3)最小矩形

//獲取指定字符串所對應的最小矩形,以(0.0)點所在位置爲基線
public void getTextBounds(String text,int start,int end,Rect bounds);

3.Paint常用函數

(1)基本設置函數

  • reset():重置畫筆
  • setColor(int color):給畫筆設置顏色值
  • setARGB():給畫筆設置顏色值
  • setAlpha(int a):設置畫筆透明度
  • setStyle(Paint.Style style):設置畫筆樣式
  • setStrokeWidth(float width):設置畫筆寬度
  • setStrokeMiter(float miter):設置畫筆是否抗鋸齒
  • setAntiAlias(boolean aa):設置畫筆的傾斜度
  • setPathEffect(PathEffect effect):設置路徑樣式
  • setStrokeCap(Paint.Cap cap):設置線帽樣式

(2)字體相關函數

  • setTextSize(float textSize):設置文字大小
  • setFakeBoldText(boolean fakeBoldText):設置是否爲粗體文字
  • setStrikeThruText(boolean strikeThruText):設置帶有刪除線效果
  • setUnderlineText(boolean underlineText):設置下劃線
  • setTextAlign(Paint.Align align):設置開始繪圖點位置
  • setTextScaleX(float scaleX):設置水平拉伸
  • setTextSkewX(float skewX):設置字體水平傾斜度
  • setTypeface(Typeface typeface):設置字體樣式
  • setLinearText(boolean linearText):設置是否打開線性文本標識

​三、Demo地址

Github:https://github.com/DayorNight/BLCS

碼雲:https://gitee.com/blcs/BLCS

apk下載體驗地址:https://www.pgyer.com/BLCS

四、內容推薦

簡書:

《Android 《Android 自定義控件開發入門與實戰》學習筆記(一)》

《Android 數據庫知識回顧》

《Android 《Android移動性能實戰》學習筆記》

《Android 下載安裝應用APK封裝(適配8.0)》

《Android Notification通知簡單封裝(適配8.0)》

如果你覺得寫的不錯或者對您有所幫助的話

不妨頂一個【微笑】,別忘了點贊、收藏、加關注哈

看在花了這麼多時間整理寫成文章分享給大家的份上,記得手下留情哈

您的每個舉動都是對我莫大的支持

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章