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

Android学习之自定义view(一)

2015-08-21 00:21 381 查看
最近一直在通过看csdn上大牛的博客学自定义view,而且面试中也经常问道怎么自定义view,通过一段时间的学习,算是初步掌握了自定义view的步骤和注意事项,所以特此想总结一下目前阶段所学到的关于自定义view的知识;当然,这也是自定义view的第一篇博客,后续还会有关于自定义view的相关文章。

废话少说,上干货。



自定义view三部曲:

一).在values文件夹下创建attr.xml文件,内容如下:

<declare-styleable name="CustomImageView">

<attr name="customimageview" format="reference"/>

</declare-styleable>

这里name一般指定为自定义view的类名,当然也可以是其他任意的字符串,如:test等;然后定义一个属性,这里的属性代表引用一张图片;

format的取值可以为:string,color,demension,integer,enum,reference,float,boolean,fraction,flag,假如属性

定义都为<attr name="attr1" format="xxxtype"/>,那么:

(1) boolean表示布尔值,调用如 xx:attr1="false"

(2) integer表示整型,调用如 xx:attr1="1"

(3) dimension表示尺寸值,调用如 xx:attr1="42dp"

(4) float表示浮点型,调用如 xx:attr1="0.7"

(5) color表示颜色值,调用如 xx:attr1="#00FF00"

(6) string表示字符串,调用如 xx:attr1="#adbddd"

(7) reference表示参考某一资源id,调用如 xx:attr1 = "@drawable/图片ID"

(8) fraction表示百分数,调用如 xx:attr1="30%"

(9)enum:枚举类型

<attr name="ImageScaleType">

<enum name="fitxy" value="0"/>

<enum name="center" value="1"/>

</attr>

(10)flag:表示位或运算

<attr name="windowSoftInputMode">
    <flag name = "stateUnspecified" value = "0" />
    <flag name = "stateUnchanged" value = "1" />
    <flag name = "stateHidden" value = "2" />
    <flag name = "stateAlwaysHidden" value = "3" />
    <flag name = "stateVisible" value = "4" />
    <flag name = "stateAlwaysVisible" value = "5" />
    <flag name = "adjustUnspecified" value = "0x00" />
    <flag name = "adjustResize" value = "0x10" />
    <flag name = "adjustPan" value = "0x20" />
    <flag name = "adjustNothing" value = "0x30" />
 </attr>

调用如:xx:attr1="stateUnspecified | stateUnchanged | stateHidden"
(11) 混合类型,定义为

<declare-styleable name = "combine_type">
    <attr name = "background" format = "reference|color" />
</declare-styleable>


调用如 xx:attr1 = "@drawable/图片ID|#DDFF00"

二)、在布局文件中使用定义的属性,在使用之前,需要引入命名空间:

xmlns:custom="http://schemas.android.com/apk/res/com.example.bottomtabline"

然后就可以使用了,如:

<com.example.bottomtabline.CustomImageView

android:id="@+id/id1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#ff0000"

custom:customimageview="@drawable/ic_action_favor_normal"/>

三)、编写一个类继承自view,然后在构造函数中获取定义的属性

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomImageView);

for(int i=0;i<ta.getIndexCount();i++){

int attr = ta.getIndex(i);

switch(attr){

case R.styleable.CustomImageView_customimageview :

imageview = BitmapFactory.decodeResource(getResources(), ta.getResourceId(attr,0));

break;

}

}

ta.recycle();

最后就是重写onDraw方法和onMeasure方法

onMeasure方法就是规定组件的大小,它和MeasureSpec有紧密的联系,而MeasureSpec是由两部分组成,分别为模型mode和大小size;

mode的取值最常用的有两种:MeasureSpec.EXACTLY代表布局文件中宽或者高中的match_parent和固定值;


MeasureSpec.AT_MOST,代表warp_parent;这个时候布局的大小就需要根据实际情况在代码中决定。

最后调用setMeasuredDimension()方法决定组件的大小。只有调用了这个方法之后,getMeasuredWidth()方法才有值,不然就是零。getWidth()(获取组件的大小)和getMeasuredWidth()方法好像一直是相等的,那是因为在onLayout方法中,对这个组件布局的时候,右坐标传入的值就是getMeasuredWidth(),而左坐标为0,两者相减之后还是原来的值,所以它们两个的值是一直相等的。

onDraw方法就是各种直接的画图、画文本的操作

画图片:

protected void onDraw(Canvas canvas) {

rect.left = 0;

rect.right = getMeasuredWidth();

rect.top = 0;

rect.bottom = getMeasuredHeight();

canvas.drawBitmap(imageview, null, rect, mPaint);

}

画半弧:

RectF oval = new RectF(xleft,xtop,xright,xbottom); //一个矩形

canvas.drawArc(oval, -90, mProgress, false, mPaint); //画的弧在这个矩形之中 -90代表画弧的起始位置,mProgress代表画的弧有多大

画圆:

drawCircle(float cx, float cy, float radius,
Paint paint) cx、cy代表坐标点,radius代表半径

画文本:

drawText(String text, int start, int end, float x, float y,
Paint paint)

画矩形:

drawRect(float left, float top, float right, float bottom,
Paint paint)

若现在有一个需求,就是使用多次这个自定义的view的组件,然后让其点击不同的组件来实现不同的业务操作,应该怎么办?这里可以在自定义的view的类里面定义一个接口,然后获取不同组件的id,实现这个接口。

自定义的view类里面:

public void setClickListener(ClickListener l){

this.listener = l;

}



public ClickListener getClickListener(){

return listener;

}



public interface ClickListener{

void onClickListener();

}

在Activity中:

write.setClickListener(new ClickListener() {



@Override

public void onClickListener() {//在这里面做具体的业务逻辑,比如调转到指定的activity,或者显示提示信息等

// TODO Auto-generated method stub

Intent intent = new Intent(MainActivity.this,WriteActivity.class);

startActivity(intent);

Toast.makeText(getApplicationContext(), "跳转到编辑界面的Activity", Toast.LENGTH_SHORT).show();

}

});



write.setOnClickListener(new View.OnClickListener() {



@Override

public void onClick(View v) {

// TODO Auto-generated method stub

write.getClickListener().onClickListener();

}

});

大体自定义view的步骤就这些吧。

很少写博客,阐述的不是很清楚,望见谅,谢谢,最后,附上源码。

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: