您的位置:首页 > 移动开发 > Android开发

Android自定义View初步(一)

2016-07-05 21:20 393 查看

一、效果图



二、知识点Get

一)自定义View的步骤

1、自定义View的属性

2、在View的构造方法中获得我们自定义的属性

[ 3、重写onMesure ]

4、重写onDraw

注意点

1、重写构造方法:

1)public View (Context context) 是在java代码创建视图的时候被调用,如果是从xml填充的视图,就不会调用这个,在代码里new的话用这个构造方法就OK了!

2)public View (Context context, AttributeSet attrs) 调用2个参数的 attr里边传过来的是 xml里边对应的height width等参数,包括自己定义的参数,如果在xml里边写入自定义控件的话 必须要重写2个参数的构造函数

3)public View (Context context, AttributeSet attrs, int defStyle) 传style的吧貌似

所以如果要在xml中使用自定义属性的话,那么至少重写前两个构造方法!!!

否则会报错(遇到过)

2、构造方法中应该做些神马?

做一些初始化工作,如:

1)一些new 操作,如new paint,避免在onDraw()中重复new 消耗资源

2)通过xml初始化自定义属性

姿势如下:

public MyView(Context context) {
this(context, null);
}

public MyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init(attrs, defStyleAttr);
}

private void init(AttributeSet attrs, int defStyleAttr){
//圆弧画笔
mPaintArc = new Paint();
mPaintArc.setColor(0x55000000);
mPaintArc.setAntiAlias(true);
mPaintArc.setStyle(Style.STROKE);
mPaintArc.setTextSize(56);

recArc = new RectF();

//图片画笔
mPaintBit = new Paint();
mPaintBit.setAntiAlias(true);

// 初始化属性
if (attrs != null){
int  slideButtonResId= attrs.getAttributeResourceValue(NAMESPACE, "myviewImg", -1);
bitmap = BitmapFactory.decodeResource(getResources(), slideButtonResId);
}

recBit = new RectF();

//属性动画
percentAnimator = ValueAnimator.ofInt(0, 360);
percentAnimator.addUpdateListener(newValueAnimator.AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animation) {
percentArc = (Integer) animation.getAnimatedValue();
invalidate();
}
});

percentAnimator.setDuration(2000);
percentAnimator.setRepeatCount(-1);  //循环次数
percentAnimator.setInterpolator(new LinearInterpolator());  //线性插值器
percentAnimator.start();
}


3、重写onMeasure

重写之前先了解MeasureSpec的specMode,一共三种类型:

EXACTLY:一般是设置了明确的值或者是MATCH_PARENT

AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT

UNSPECIFIED:表示子布局想要多大就多大,很少使用

由于我的要求不高,可在xml中指定宽高具体值即可

so:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);

widthArc = width/10;   //基于控件宽度的十分之一
recArc.set(widthArc*0.5f, widthArc*0.5f, width - widthArc*0.5f, height - widthArc*0.5f);

recBit.set(widthArc*0.5f, widthArc*0.5f, width - widthArc*0.5f, height - widthArc*0.5f);

setMeasuredDimension(width, height);
}


注意:在onMeasure中获取控件的宽高,可以基于控件的宽高去设置View的其他宽度大小(如画笔宽度、文字大小等)

4、重写onDraw()

onDraw()中就靠自己通过Paint、Canvas等API自由发挥了

注意:

1)onDraw()中避免创建对象(如new Paint)

2)onDraw()中避免做耗时操作

三)为自定义控件添加属性

1、在attrs.xml中定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SuiYi">
<attr name="myviewImg" format="reference" />
</declare-styleable>

</resources>


declare-styleable name 可以随意命名,不影响

attr name=”myviewImg” 属性名!!!

format的几种格式:

reference:参考某一资源ID

color:颜色值

boolean:布尔值

string:字符串

…..等等

2、布局中使用

1)命名空间

xmlns:custom=”http://schemas.android.com/apk/com.example.zsign”

切记添加命名空间 格式为 schemas.android.com/apk/ + 包名

2)使用

<com.example.zsign.MyView
android:id="@+id/myview"
android:layout_width="100dp"
android:layout_height="100dp"
custom:myviewImg="@drawable/ic_launcher" />


custom:myviewImg=”@drawable/ic_launcher”

3、自定义View中获取属性值

通过AttributeSet attrs获取属性值

// 初始化属性
if (attrs != null){
int  slideButtonResId= attrs.getAttributeResourceValue(NAMESPACE, "myviewImg", -1);
bitmap = BitmapFactory.decodeResource(getResources(), slideButtonResId);
}


具体请参考AttributeSet API

四)属性动画的使用

属性动画通过动态地改变对象的属性从而达到动画效果

//属性动画
percentAnimator = ValueAnimator.ofInt(0, 360);
percentAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
percentArc = (Integer) animation.getAnimatedValue();
invalidate();
}
});

percentAnimator.setDuration(2000);
percentAnimator.setRepeatCount(-1);  //循环次数
percentAnimator.setInterpolator(new LinearInterpolator());  //线性插值器
percentAnimator.start();


通过动态的改变属性值,再进行重绘invalidate()达到动画效果

这里体现出了属性动画相较于View动画的优越性

注意:

1)在主线程中start()属性动画

2)invalidate()和postInvalidate()的区别

3)Activity退出时应停止属性动画,避免内存泄漏
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android