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)》

如果你觉得写的不错或者对您有所帮助的话

不妨顶一个【微笑】,别忘了点赞、收藏、加关注哈

看在花了这么多时间整理写成文章分享给大家的份上,记得手下留情哈

您的每个举动都是对我莫大的支持

 

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