自定义View以及自定义属性
Posted 安辉就是我
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义View以及自定义属性相关的知识,希望对你有一定的参考价值。
转载请注明出处:http://blog.csdn.net/lowprofile_coding/article/details/53558247
1.最终效果图.
效果图看起来蛮简单的,就是画一个圆的过程。
2.实现步骤
1).重写onDraw方法
@Override
protected void onDraw(Canvas canvas)
Log.i("MyView","onDraw");
if(null==myThread)
myThread=new MyThread();
myThread.start();
else
//第一个参数是RectF 左上的x y坐标 右下的x y坐标
//第二个参数是 弧形的开始角度
//第三个参数是 弧形的结束角度
//第四个参数是 true:画扇形 false:画弧线
//第五个参数是 画笔
canvas.drawArc(rectF, 0, sweepAngle, true, paint);
//开启一个子线程绘制ui
private class MyThread extends Thread
@Override
public void run()
while(running)
logic();
postInvalidate();//重新绘制,会调用onDraw
try
Thread.sleep(200);
catch (InterruptedException e)
e.printStackTrace();
protected void logic()
sweepAngle+=sweepAngleAdd;//每次增加弧度
//随机设置画笔的颜色
int r=random.nextInt(255);
int g=random.nextInt(255);
int b=random.nextInt(255);
paint.setARGB(255, r, g, b);
if(sweepAngle>=360)//如果弧度大于360° 从头开始
sweepAngle=0;
当第一次执行onDraw方法的时候,启动了一个线程,在线程里面改变我们画圆的参数,然后调用postInvalidate方法,这个方法的作用是重新绘制,继续调用onDraw。然后第二次调用onDraw方法的时候,线程不为空,根据角度画扇形。
2).重写onMeasure方法
讲到View的measure测量,会涉及到View的一个静态内部类MeasureSpec,MeasureSpec类封装了父View传递给子View的布局(layout)要求,每个MeasureSpec实例代表宽度或者高度(只能是其一)要求。MeasureSpec字面意思是测量规格或者测量属性,在measure方法中有两个参数widthMeasureSpec和heightMeasureSpec,如果使用widthMeasureSpec,我们就可以通过MeasureSpec计算出宽的模式Mode和宽度的实际值。
测量的模式分以下三种:
EXACTLY 精确值模式
当我们的View的layout_width 或者 layout_height属性设置为具体的数值(例: android:layout_width = “100dp”)或者指定为 “match_parent” 时(这时候系统会自动分配为父布局的大小)
就是使用的这个模式
AT_MOST 最大值模式
当我们的View的layout_width 或者 layout_height属性设置为 “wrap_content”
UNSPECIFIED
表示开发人员可以将视图按照自己的意愿设置成任意的大小,没有任何限制。这种情况比较少见,不太会用到
我们为什么要重写onMeasure方法?
给大家看一下View在布局里面的属性:
<com.ansen.view.MyView
android:background="@android:color/holo_green_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:sweepAngleAdd="10"/>
运行截图如下:
我明明设置了包裹内容,但是背景颜色的宽高跟屏幕一样大。因为我们不重写的话,View在布局文件中设置android:layout_width=”wrap_content”时会起到match_parent的效果.
接下来我们重写onMeasure方法:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 获得它的父容器为它设置的测量模式和大小
int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
if(modeWidth==MeasureSpec.EXACTLY)//指定宽度/match_parent
else if(modeWidth==MeasureSpec.AT_MOST)//指定为WRAP_CONTENT时
measuredWidth=380;
if(modeHeight==MeasureSpec.EXACTLY)//指定高度/match_parent
else if(modeHeight==MeasureSpec.AT_MOST)//指定为WRAP_CONTENT时
measuredHeight=380;
setMeasuredDimension(measuredWidth,measuredHeight);
Log.i("MyView","onMeasure");
我们通过MeasureSpec获得它的父容器为它设置的测量模式和大小,根据不同的宽高模式做处理,我们这边对模式为AT_MOST的时候做了处理,设置高度380.最后调用setMeasuredDimension方法,把处理过的实际宽高传递进去。
现在我们可以看到宽高就正常了。。。。
3).自定义属性.
首先在res/values下新建一个attrs.xml文件。内容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="customStyleView">
<attr name="sweepAngleAdd" format="integer"/>
</declare-styleable>
</resources>
需要用包围所有属性。其中name为该属性集的名字,主要用途是标识该属性集。
属性的类型也有很多: string,integer,dimension , reference , color , enum.
在布局xml文件中引用该属性:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ansen.view.MyView
android:background="@android:color/holo_green_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:sweepAngleAdd="10"/>
</RelativeLayout>
在自定义View的构造方法里面获取该自定义属性的值。我们这边用来控制扇形的弧度增加,每次画扇形的时候,弧度的增加数量如果有变化就不需要修改java代码了,只要在xml中修改一下就行。
public MyView(Context context)
this(context,null);
public MyView(Context context,AttributeSet attrs)
super(context, attrs);
init(context,attrs);
//初始化
private void init(Context context,AttributeSet attrs)
//获取自定义属性的值
TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.customStyleView);
sweepAngleAdd=typedArray.getInt(R.styleable.customStyleView_sweepAngleAdd,0);
typedArray.recycle();
paint=new Paint();
paint.setTextSize(60);
学了这么多,想不想下载源码自己运行一下呢。。。点击我下载源码
如果你想第一时间看我们的后期文章,扫码关注公众号,每周不定期推送Android开发实战教程文章,你还等什么,赶快关注吧,学好技术,出任ceo,赢取白富美。。。。
Android开发666 - 安卓开发技术分享
扫描二维码加关注
以上是关于自定义View以及自定义属性的主要内容,如果未能解决你的问题,请参考以下文章