对handler机制一直感觉不太懂,想写一篇handler分析类的,看别人写的都挺好,自己写,从哪开始都感觉不对劲。所以先搞一篇自定义控件练练。
其实对于自定义控件感觉也不懂,每次用总是东拼西凑,东西是搞出来了。不知道怎么搞出来的。所以这次就先搞出来一段,分析下。权当总结记录
public class MyOneText extends View {
String text;
int msrc;
public MyOneText(Context context, AttributeSet attrs) {
super(context, attrs);
int textId = attrs.getAttributeResourceValue(null, "text", 0);
int srcId = attrs.getAttributeResourceValue(null, "src", 0);
text = context.getResources().getText(textId).toString();
msrc = srcId;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint=new Paint();
InputStream inputStream = getResources().openRawResource(msrc);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
int height = bitmap.getHeight();
int width = bitmap.getWidth();
canvas.drawBitmap(bitmap,0,0,paint);
canvas.drawText(text,width/2,30,paint);
}
}
xml
<com.example.administrator.customcontrol2.MyOneText
android:id="@+id/text"
android:layout_width="wrap_content"
text="@string/hello_world"
src="@mipmap/ic_launcher"
android:layout_height="wrap_content" />
MyOneText继承了view
为什么要继承view 那,view是所有图形的基类,不用不行~~~
view里面有三个需要注意的方法 measure() , layout() , draw() ,
1,measure 是计算视图大小用的 , 主要调用了onmeasure方法, 如果有需要,子类可以覆写并实现自己的计算视图大小。并通过setMeasuredDimension保存。
2,layout 设置视图在屏幕中显示的位置,主要有两个需要注意,setFrame , onLayout , setFrame 设置子视图在父视图中的位置, onLayout , 这个是在你的控件是viewGroup类型时设置子视图使用的。
3,draw 将上两步设置的参数,绘制显示在屏幕上 内部定义了绘图的基本操作,具体可以参考View类的draw方法。自定义控件需要特别注意的方法就是这三个。既然是要自定义view,肯定是要用一些系统控件没有的属性或者属性组合。
自定义view增加属性的两种方法
1,上面的MyOneText 这个类用的就是view类中定义, 通过构造函数中的 AttributeSet 查找布局的属性名称,然后获得id进行使用。
2, 下面这种就是Android提供的标准写法,通过xml注册。
在values中新建attrsxmlpublic class MyOneImage extends LinearLayout { public MyOneImage(Context context, AttributeSet attrs) { super(context, attrs); int resourcedId = -1; TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyOneImage); ImageView iv = new ImageView(context); TextView tv = new TextView(context); int n = typedArray.getIndexCount(); for (int i = 0; i < n; i++) { int attr = typedArray.getIndex(i); switch (attr) { case R.styleable.MyOneImage_Oriental: resourcedId = typedArray.getInt(R.styleable.MyOneImage_Oriental, 0); this.setOrientation(resourcedId == 1 ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL); break; case R.styleable.MyOneImage_Text: resourcedId = typedArray.getResourceId(R.styleable.MyOneImage_Text, 0); tv.setText(resourcedId > 0 ? typedArray.getResources().getText(resourcedId) : typedArray.getString(R.styleable.MyOneImage_Text)); break; case R.styleable.MyOneImage_Src: resourcedId = typedArray.getInt(R.styleable.MyOneImage_Oriental, 0); iv.setImageResource(resourcedId > 0 ? resourcedId : R.mipmap.ic_launcher); break; } } addView(iv); addView(tv); typedArray.recycle(); } }
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyOneImage">
<attr name="Text" format="reference|string"></attr>
<attr name="Oriental" >
<enum name="Horizontal" value="1"></enum>
<enum name="Vertical" value="0"></enum>
</attr>
<attr name="Src" format="reference|integer"></attr>
</declare-styleable>
</resources>
<com.example.administrator.customcontrol2.MyOneImage android:layout_width="wrap_content" app:Text="@string/hello_world" app:Src="@mipmap/ic_launcher" app:Oriental="Vertical" android:layout_height="wrap_content"></com.example.administrator.customcontrol2.MyOneImage>
eclipse需要在用到自定义view的xml里面定义这个 xmlns:android="http://schemas.android.com/apk/res/com.example.administrator.customcontrol2.MyOneImage"studio 则直接添上已经这个就可以了
xmlns:app="http://schemas.android.com/apk/res-auto"上面是自定义view添加属性的两种方法。
自定义控件主要有三种实现方式
1,继承已有的控件进行扩展,已有的控件属性不够用了,扩展下
2,继承view类,加载一个布局文件实现, 组合控件可能用到,在构造方法里面通过inflater加载自定义控件的布局文件。再addView.
3, 继承view类,使用GDI直接绘制。一般这种用到没上面两种多。
http://blog.163.com/ppy2790@126/blog/static/103242241201382210910473/ 其实就是按照自己的理解整理了一下,主要是为了加深记忆。
后边会搞一搞复杂一点的。