目錄
一、前言
自定義控件一直是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
四、內容推薦
簡書:
如果你覺得寫的不錯或者對您有所幫助的話
不妨頂一個【微笑】,別忘了點贊、收藏、加關注哈
看在花了這麼多時間整理寫成文章分享給大家的份上,記得手下留情哈
您的每個舉動都是對我莫大的支持