为android自定义View控件添加自定义的属性
2015-07-05 20:18
555 查看
主要步骤:
1、在attrs.xml文件中声明属性,有属性名:name和格式:format 。如:
2、在布局文件中使用新属性,使用之前必须先声明命名空间,如:xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"
3、在自定义view的构造方法当中,通过解析 AttributeSet 对象,获得所需要的属性值。
一、在attrs.xml文件中声明属性,如:
所有的format类型,详见注1:
二、在布局文件中使用:在使用之前必须声名命名空间,xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"
说明:xmlns 是XMLname space 的缩写;
heima 可为任意写符
http://schemas.android.com/apk/res/ 此为android固定格式;
com.itheima.mytogglebtn 此应用的包名,如manifest配置文件中一致。
布局文件:
<com.itheima.mytogglebtn.MyToggleButton
xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
heima:slide_button="@drawable/slide_button" />
三、在代码中对属性进行解析,主要代码:
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyToggleBtn); // 由attrs 获得TypeArray
注1:
format 常用类型
reference 引用
color 颜色
boolean 布尔值
dimension 尺寸值
float 浮点值
integer 整型值
string 字符串
enum 布尔值
附一完整的自定义控件实现
整理自相关教程
1、在attrs.xml文件中声明属性,有属性名:name和格式:format 。如:
<declare-styleable name="MyToggleBtn"> <attr name="current_state" format="boolean"/> </declare-styleable>
2、在布局文件中使用新属性,使用之前必须先声明命名空间,如:xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"
3、在自定义view的构造方法当中,通过解析 AttributeSet 对象,获得所需要的属性值。
一、在attrs.xml文件中声明属性,如:
<declare-styleable name="MyToggleBtn"> //声名属性集的名称,即这些属性是属于哪个控件的。 <attr name="current_state" format="boolean"/> //声名属性 current_state 格式为 boolean 类型 <attr name="slide_button" format="reference"/> //声名属性 slide_button 格式为 reference 类型 </declare-styleable>
所有的format类型,详见注1:
二、在布局文件中使用:在使用之前必须声名命名空间,xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"
说明:xmlns 是XMLname space 的缩写;
heima 可为任意写符
http://schemas.android.com/apk/res/ 此为android固定格式;
com.itheima.mytogglebtn 此应用的包名,如manifest配置文件中一致。
布局文件:
<com.itheima.mytogglebtn.MyToggleButton
xmlns:heima="http://schemas.android.com/apk/res/com.itheima.mytogglebtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
heima:slide_button="@drawable/slide_button" />
三、在代码中对属性进行解析,主要代码:
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyToggleBtn); // 由attrs 获得TypeArray
注1:
format 常用类型
reference 引用
color 颜色
boolean 布尔值
dimension 尺寸值
float 浮点值
integer 整型值
string 字符串
enum 布尔值
附一完整的自定义控件实现
public class MyToggleButton extends View implements OnClickListener{ /** * 做为背景的图片 */ private Bitmap backgroundBitmap; /** * 可以滑动的图片 */ private Bitmap slideBtn; private Paint paint; /** * 滑动按钮的左边届 */ private float slideBtn_left; /** * 背景图的资源ID */ private int backgroundId; /** * 滑动图片的资源ID */ private int slideBtnId; /** * 在代码里面创建对象的时候,使用此构造方法 */ public MyToggleButton(Context context) { super(context); // TODO Auto-generated constructor stub } /** * 在布局文件中声名的view,创建时由系统自动调用。 * @param context 上下文对象 * @param attrs 属性集 */ public MyToggleButton(Context context, AttributeSet attrs) { super(context, attrs); //无命名空间测试 String testAttrs = attrs.getAttributeValue(null, "testAttrs"); System.out.println("testAttrs===:"+testAttrs); //获得自定义的属性 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn); int N = ta.getIndexCount(); for (int i = 0; i < N; i++) { /* * 获得某个属性的ID值 */ int itemId = ta.getIndex(i); switch (itemId) { case R.styleable.MyToggleBtn_curr_state: currState = ta.getBoolean(itemId, false); break; case R.styleable.MyToggleBtn_my_background: backgroundId = ta.getResourceId(itemId, -1); if(backgroundId == -1){ throw new RuntimeException("请设置背景图片"); } backgroundBitmap = BitmapFactory.decodeResource(getResources(), backgroundId); break; case R.styleable.MyToggleBtn_my_slide_btn: slideBtnId = ta.getResourceId(itemId, -1); slideBtn = BitmapFactory.decodeResource(getResources(), slideBtnId); break; default: break; } } initView(); } /** * 初始化 */ private void initView() { //初始化图片 // backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background); // slideBtn = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button); //初始化 画笔 paint = new Paint(); paint.setAntiAlias(true); // 打开抗矩齿 //添加onclick事件监听 setOnClickListener(this); flushState(); } /* * view 对象显示的屏幕上,有几个重要步骤: * 1、构造方法 创建 对象。 * 2、测量view的大小。 onMeasure(int,int); * 3、确定view的位置 ,view自身有一些建议权,决定权在 父view手中。 onLayout(); * 4、绘制 view 的内容 。 onDraw(Canvas) */ @Override /** * 测量尺寸时的回调方法 */ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); /** * 设置当前view的大小 * width :view的宽度 * height :view的高度 (单位:像素) */ setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight()); } //确定位置的时候调用此方法 //自定义view的时候,作用不大 // @Override // protected void onLayout(boolean changed, int left, int top, int right, // int bottom) { // super.onLayout(changed, left, top, right, bottom); // } /** * 当前开关的状态 * true 为开 */ private boolean currState = false; @Override /** * 绘制当前view的内容 */ protected void onDraw(Canvas canvas) { // super.onDraw(canvas); // 绘制 背景 /* * backgroundBitmap 要绘制的图片 * left 图片的左边届 * top 图片的上边届 * paint 绘制图片要使用的画笔 */ canvas.drawBitmap(backgroundBitmap, 0, 0, paint); //绘制 可滑动的按钮 canvas.drawBitmap(slideBtn, slideBtn_left, 0, paint); } /** * 判断是否发生拖动, * 如果拖动了,就不再响应 onclick 事件 * */ private boolean isDrag = false; @Override /** * onclick 事件在View.onTouchEvent 中被解析。 * 系统对onclick 事件的解析,过于简陋,只要有down 事件 up 事件,系统即认为 发生了click 事件 * */ public void onClick(View v) { /* * 如果没有拖动,才执行改变状态的动作 */ if(!isDrag){ currState = !currState; flushState(); } } /** * down 事件时的x值 */ private int firstX; /** * touch 事件的上一个x值 */ private int lastX; @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: firstX = lastX =(int) event.getX(); isDrag = false; break; case MotionEvent.ACTION_MOVE: //判断是否发生拖动 if(Math.abs(event.getX()-firstX)>5){ isDrag = true; } //计算 手指在屏幕上移动的距离 int dis = (int) (event.getX() - lastX); //将本次的位置 设置给lastX lastX = (int) event.getX(); //根据手指移动的距离,改变slideBtn_left 的值 slideBtn_left = slideBtn_left+dis; break; case MotionEvent.ACTION_UP: //在发生拖动的情况下,根据最后的位置,判断当前开关的状态 if (isDrag) { int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth(); // slideBtn // 左边届最大值 /* * 根据 slideBtn_left 判断,当前应是什么状态 */ if (slideBtn_left > maxLeft / 2) { // 此时应为 打开的状态 currState = true; } else { currState = false; } flushState(); } break; } flushView(); return true; } /** * 刷新当前状态 */ private void flushState() { if(currState){ slideBtn_left = backgroundBitmap.getWidth()-slideBtn.getWidth(); }else{ slideBtn_left = 0; } flushView(); } /** * 刷新当前视力 */ private void flushView() { /* * 对 slideBtn_left 的值进行判断 ,确保其在合理的位置 即 0<=slideBtn_left <= maxLeft * */ int maxLeft = backgroundBitmap.getWidth()-slideBtn.getWidth(); // slideBtn 左边届最大值 //确保 slideBtn_left >= 0 slideBtn_left = (slideBtn_left>0)?slideBtn_left:0; //确保 slideBtn_left <=maxLeft slideBtn_left = (slideBtn_left<maxLeft)?slideBtn_left:maxLeft; /* * 刷新当前视图 导致 执行onDraw执行 */ invalidate(); } }
整理自相关教程
相关文章推荐
- Android 水波纹点击效果(Ripple Effect)
- Activity的launchMode相关
- 【Android】Environment variable does not point to a valid JVM instalation
- Android 物理按键
- 内部类对宿主类private成员的访问
- android 如何使用jar替换java代码编译
- 实习前的准备工作:Android开发环境的搭建
- android 相对布局属性
- AsyncTask的基本使用
- Caused by: android.os.NetworkOnMainThreadException
- Android学习笔记
- CSDN Androidclient生产 导航帖
- Android开发——为移动的Paint元素指定图片的方法
- 开始研究tigase和android客户端的实现
- android installer hijacking---安卓安装劫持
- 百度云消息推送机制简介及开发前的集成,入门篇
- android学习笔记(九)——动画效果的实现逐帧动画
- Android中的Data Binding初探 (一)
- Android调用手机自带图库选择图片
- 单独编译Android的image文件