许多APP上都会有一些比较酷炫美观的动画效果和自定义控件,所以最近研究了一下,又遇到一些疑惑和问题,所以这里记录一下。
自定义控件经常会要提到三个方法,也就是onLayout(),onMeasure()和onDraw()。今天我暂时先讲一下自己对onDraw()方法的学习。
首先我们自定义一个MyView1继承于View类,然后会自动提示我们添加一些方法,这些就不细说了。
在这些提示的方法里面有一个方法:
public MyView1(Context context, AttributeSet attrs, int defStyleAttr) {}
首先我在这个方法里面新建了一个TypeArray对象,通过它来获得MyView1的一些自定义属性。这里我们要新建一个xml格式的文件。
里面的代码如下:
<declare-styleable name="MyView1"> <attr name="left_circle_radius" format="dimension" /> <attr name="left_circle_color" format="color" /> <attr name="top_circle_radius" format="dimension" /> <attr name="top_circle_color" format="color" /> <attr name="right_circle_radius" format="dimension" /> <attr name="right_circle_color" format="color" /> <attr name="bottom_circle_radius" format="dimension" /> <attr name="bottom_circle_color" format="color" /> </declare-styleable>其实也就是定义这个View中需要用到的一些属性,需要注意的是记得写上format的类型,至于为什么,后面我会讲到。在这个View里面我定义了四个圆的半径和颜色。
然后在代码里面我们要获得它们,这里要注意的是获得它们必须是“declare-styleable的name+ attr的name”,例如上面的“MyView1_left_circle_radius",这应该是他们固定的一种格式,不这么写的话会报错的。
除了获得这些属性外,我们还要实例化Paint类的对象。
mPaint = new Paint(); mPaint.setAlpha(180); // 透明度 mPaint.setStrokeWidth(2); // 画笔宽度 mPaint.setAntiAlias(true); // 消除锯齿 mPaint.setTextAlign(Paint.Align.CENTER); // 文字居中上面是Paint类比较常用的几种方法,注释写的很仔细了,所以就不再赘述了。
接下来说onDraw()方法,看到这个方法,大家就知道它跟绘画有关。
onDraw()方法中有一个Canvas类,也就是画布的意思。Canvas类有许多绘画的方法,比如
画圆调用canvas的
drawCircle(left, top, radius, paint);
方法中的属性分别对应要绘制的这个圆最左侧的横坐标,最上侧的纵坐标,半径,和画笔。
画直线调用canvas的
drawLine(left, top, right, bottom, paint)
方法中的属性也就是这条直线左上右下的四个坐标点,因为宽度已经被paint的setStrokeWidth()方法给固定了。
画虚线稍微比他们复杂一些,要用到PathEffect类,下面有具体的注释。
PathEffect effects = new DashPathEffect(new float[]{1,2,4,8},1); // 绘制长度1的实线,再绘制长度2的空白,再绘制长度4的实线,再绘制长度8的空白
接下来附上本人写的demo的部分代码:
mPaint.setColor(Color.CYAN); canvas.drawLine(getWidth() - getWidth() / 5 * 4 + 40, getHeight() / 2, getWidth() - getWidth() / 5 - 40, getHeight() / 2, mPaint); // 划线,左,上,右,下,画笔 mPaint.setColor(leftCircleColor); /** * 1.Paint.Style.STROKE:描边 * 2.Paint.Style.FILL_AND_STROKE:描边并填充 * 3.Paint.Style.FILL:填充 * 默认FILL */ mPaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawCircle(getWidth() - getWidth() / 5 * 4, getHeight() / 2, leftCircleRadius, mPaint); // 画圆,左,上,半径,画笔 PathEffect effects = new DashPathEffect(new float[]{1,2,4,8},1); // 绘制长度1的实线,再绘制长度2的空白,再绘制长度4的实线,再绘制长度8的空白 mPaint.setPathEffect(effects); mPaint.setColor(topCircleColor); mPaint.setStyle(Paint.Style.STROKE); canvas.drawCircle(getWidth() / 2, getHeight() - getHeight() / 5 * 4, topCircleRadius, mPaint); canvas.drawCircle();最后就是在Activity里面使用这个MyView1了,首先自然是像那些普通控件一样在activity_main.xml中定义,代码如下:
<com.xue.myview1.MyView1 android:id="@+id/myview1_main" android:layout_width="wrap_content" android:layout_height="wrap_content" xue:left_circle_color="#00FF00" xue:left_circle_radius="30dp" xue:top_circle_color="#303F9F" xue:top_circle_radius="30dp" xue:right_circle_color="#FF4081" xue:right_circle_radius="30dp" xue:bottom_circle_color="#FFFF00" xue:bottom_circle_radius="30dp"/>,然后在Activity定义MyView1的对象并找到就好了。
然而,在开发完成的时候遇到了下面这个问题:
Error:Execution failed for task ':app:processDebugResources'. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'D:\adt-bundle-windows-x86_64-20140624\sdk\build-tools\23.0.1\aapt.exe'' finished with non-zero exit value 1这个问题困扰了我几个小时,刚开始的时候以为是
xmlns:xue="http://schemas.android.com/apk/res-auto"这条语句的问题,可是把res-auto换成对应的包名还是没有用,也仔细查看过语句,可是由于报错的信息中没有定位到错误的地方。最后还是解决了,我发现是导致这个报错的原因如下:
1、xml文件中"xue:"后面定义的属性和attrs中的属性有出入;
2、"30dp"和”#000000"和属性的类型有出入,开始的时候没有写format="color"和format="dimension",而代码中定义的是
private int leftCircleColor = Color.WHITE; private float leftCircleRadius = 40.0f; leftCircleColor = a.getColor(attr, leftCircleColor); leftCircleRadius = a.getDimension(attr, leftCircleRadius);
这就是我初次学习自定义View的一些小知识的理解和使用。