Android自定义控件之旅(一)滑动开关
2015-04-07 23:12
405 查看
Android自定义控件之旅(一)滑动开关
我们的开关可以单击,可以滑动,效果如下图我们写自定义控件时,一般分为下面几步:
1、自定义View属性。
2、在布局文件中指定自定义属性的取值,并在View的构造方法中获取自定义属性的取值。
3、重写onMeasure()方法。有时也可以不用重写。
4、重写onDraw()方法。
一、自定义View属性
1、在values下创建attrs.xml资源文件<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="btnBackground" format="reference" /> <attr name="btnSwitch" format="reference" /> <attr name="switchState" format="boolean" /> <declare-styleable name="CustomSwitchButton"> <attr name="btnBackground" /> <attr name="btnSwitch" /> <attr name="switchState" /> </declare-styleable> </resources>
format指定了该属性的取值类型,有string,color,demension,integer,enum,reference,float,boolean,fraction,flag;
declare-styleable 就是我们要自定义控件的属性,name取值必须是自定义控件的类名
二、在布局文件中指定自定义属性的取值,并在View的构造方法中获取自定义属性的取值
1、在布局文件中指定自定义属性的取值
在layout下创建main_activity.xml<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:switchBtn="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.zhy.customswitchbutton.CustomSwitchButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" switchBtn:btnBackground="@mipmap/switch_background" switchBtn:btnSwitch="@mipmap/switch_button" switchBtn:switchState="true" /> </RelativeLayout>
其中xmlns:switchBtn=”http://schemas.android.com/apk/res-auto”指定命名空间
命名空间的格式为
Android Stutio中 xmlns:前缀=”http://schemas.android.com/apk/res/res-auto”
eclipse中 xmlns:前缀=”http://schemas.android.com/apk/res/app包名”
为自定义属性赋值
switchBtn:btnBackground="@mipmap/switch_background" switchBtn:btnSwitch="@mipmap/switch_button" switchBtn:switchState="true" />
2、在View的构造方法中获取自定义属性的取值
public class CustomSwitchButton extends View { private Bitmap btnBackground; private Bitmap btnSwitch; private boolean switchState; /** * 画笔对象 */ private Paint paint; /** * 滑动的距离 */ private float offset; /** * 是否发生拖动 */ private boolean isDrag = false; /** * 代码中new出来的,执行此构造方法 * @param context */ public CustomSwitchButton(Context context) { this(context, null); } /** * xml中使用时,系统会调用此构造方法 * @param context * @param attrs */ public CustomSwitchButton(Context context, AttributeSet attrs) { this(context, attrs, 0); } /** * xml中使用时,系统会调用此构造方法 * @param context * @param attrs */ public CustomSwitchButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context, attrs); } private void initView(Context context, AttributeSet attrs) { paint = new Paint(); paint.setAntiAlias(true);//设置坑锯齿 /** * 获取各个属性的值 */ TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomSwitchButton); btnBackground = BitmapFactory.decodeResource(getResources(), ta.getResourceId(R.styleable.CustomSwitchButton_btnBackground, 0)); btnSwitch = BitmapFactory.decodeResource(getResources(), ta.getResourceId(R.styleable.CustomSwitchButton_btnSwitch, 0)); switchState = ta.getBoolean(R.styleable.CustomSwitchButton_switchState, false); } }
三、重写onMeasure()方法,有时也可以不用重写
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(btnBackground.getWidth(), btnBackground.getHeight()); }
我们的开关很简单,宽高值就是背景图片的大小
四、重写onDraw()方法
@Override protected void onDraw(Canvas canvas) { /** * 绘制背景 *Bitmap bitmap 要绘制的图像 *float left 左边距 *float top 上边距 *Paint paint 画笔对象 */ canvas.drawBitmap(btnBackground, 0, 0, paint); /** * 绘制开关 */ canvas.drawBitmap(btnSwitch, offset, 0, paint); }
其中 offset 指的是距离左边的偏移距离,是动态变化的
单击事件,
@Override public void onClick(View v) { //拖动时,防止和onTouch冲突 if (!isDrag) { switchState = !switchState; changeState(); } } private void changeState() { offset = switchState ? btnBackground.getWidth() - btnSwitch.getWidth() : 0; //重绘制界面 invalidate(); }
拖动事件
/** * down 事件时的X坐标 */ private float firstX; /** * up 事件时上次的X坐标 */ private float lastX; /** * 重写onTouchEvent实现滑动效果 * * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); float curX = event.getX(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isDrag = false; firstX = lastX = curX; break; case MotionEvent.ACTION_MOVE: //判定是否进行了滑动 if (Math.abs(lastX - firstX) > 5) { isDrag = true; } float dis = curX - lastX; offset += dis; lastX = curX; break; case MotionEvent.ACTION_UP: //未滑完时,判定最终的开关状态 if (isDrag) { //能滑动的最大距离 float maxDis = btnBackground.getWidth() - btnSwitch.getWidth(); switchState = offset > maxDis / 2 ? true : false; changeState(); } break; } refreshView(); return true; } /** * 刷新界面 */ private void refreshView() { //判断是否已经超出边界 float maxDis = btnBackground.getWidth() - btnSwitch.getWidth(); offset = offset < 0 ? 0 : offset; offset = offset > maxDis ? maxDis : offset; invalidate(); }
下载源码
相关文章推荐
- android自定义滑动开关控件,自定义view
- android自定义滑动开关控件,适合所有的android系统
- Android:android自定义滑动开关控件
- 【Android进阶】Android自定义滑动开关控件,适合所有的android系统
- android自定义滑动开关控件,适合所有的android系统
- Android自定义SwitchButton左右滑动开关按钮控件
- 【视图控件篇】自定义Android控件之IOS滑动开关模拟详解
- android自定义滑动开关控件,适合所有的android系统
- Android-自定义可滑动开关控件之SlidingSwitchView
- Android开发进阶自定义控件之滑动开关实现方法【附demo源码下载】
- Android自定义控件之实现滑动选择开关
- Android自定义控件之滑动开关
- 【Android界面实现】自定义滑动开关控件的实现与使用
- Android进阶自定义控件之滑动开关
- android自定义滑动开关控件,适合所有的android系统 《转载》
- android自定义滑动开关控件,适合所有的android系统
- Android-自定义可滑动开关控件之SlidingSwitchView
- Android自定义控件之滑动开关
- 自定义开关控件 点击和滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果