转眼间从事android开发也有一段时间了,今天想把自己学到的东西与大家分享下,今天给大家带来的是自定义view——SlideSwitch开源控件的讲解。
SlideSwitch是一个开关的效果,这里贴上两张效果图:
自定义View的实现方式可以分为三种,自绘控件、组合控件、以及继承控件。今天要讲的就是自绘控件。主要步骤分为:
一、定义View的属性信息。 // attrs.xml 文件
二、在View中检索定义的属性 // TypedArray检索
三、重写onMeasure() /**/ 测量:决定View的大小
四、重写onLayout() /**/ 布局:决定View在ViewGroup中的位置
五、重写onDraw() 绘制:如何绘制这个View
其中三、四步视具体情况而定,不是必须重写的,这里讲解的就是第四步没有重写。
一、定义view的属性:在项目的res/values/ 文件夹下建立一个attrs.xml 文件, 在里面定义我们的属性和声明我们的样式。
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="slideswitch"> <attr name="themeColor" format="color" /> <attr name="isOpen" format="boolean" /> <attr name="shape"> <enum name="rect" value="1" /> <enum name="circle" value="2" /> </attr> </declare-styleable> </resources></span>
自定义View会用到TypedArray,attrs.xml和AttributeSet知识,这里先说下attrs.xml;
其中标签declare-styleable的name属性代表了接下来定义的属性的所属控件(这里name只是用来区分不同的declare-styleable,不一定和控件的名称一致,只是方便阅读)。标签attr就是用来的定义具体的属性,name代表属性名,format代表属性的类型。
Attrs.xml文件中属性类型format值的格式
引用型reference
例如:Tools:background = “@drawable/图片ID”
颜色型color
例如 : tools:textColor = “#ffffff”
布尔型boolean
例如 : tools: focusable = “true”
尺寸型dimension
例如 : tools: layout_width = “42dip”
浮点型float
例如 : tools: fromAlpha = “1.0”
整型integer
例如 : tools: frameDuration = “100”
字符串string
例如 : tools: apiKey = “dsegergegasefwg”
百分数fraction
例如 : tools: pivotx = “200%”
枚举型enum:
< attr name="orientation">
< enum name="horizontal" value="0" />
< enum name="vertical" value="1" />
< /attr>
使用:android:orientation = "vertical"
标志位、位或运算,格式如下:
< 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>
XML中使用:
android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">
属性定义可以指定多种类型:
定义:< attr name = "background" format = "reference|color" />
使用:android:background = "@drawable/图片ID|#00FF00"
这里我们只用到了布尔型、颜色型、枚举型。
二、在View中检索定义的属性
<pre name="code" class="html">public SlideSwitch(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); listener = null; paint = new Paint(); paint.setAntiAlias(true); //TypedArray是一个用来存放由context.obtainStyledAttributes获得的属性的数组 //属性的名称是styleable中的名称+“_”+属性名称 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.slideswitch); color_theme = a.getColor(R.styleable.slideswitch_themeColor, DEFAULT_COLOR_THEME);// 滑动背景颜色,默认值 isOpen = a.getBoolean(R.styleable.slideswitch_isOpen, false);// 开关是打开还是关闭,默认false shape = a.getInt(R.styleable.slideswitch_shape, SHAPE_RECT);// 形状属性 //在使用完成后,一定要调用recycle方法 a.recycle(); } public SlideSwitch(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlideSwitch(Context context) { this(context, null); }
TypedArray:
与Context类的obtainStyledAttributes方法一起使用,作为一个不同类型的数据的容器使用。这句一般是使用在自定义View的构造方法中的,其中attrs是构造方法的形参,而R.styleable.slideswitch是和attrs.xml相关的。
slideswitc是attrs.xml中declare-styleable的name属性的值。如果这个自定义View在attrs.xml文件中对应的declare-styleable的name属性值为A,那么这里就写R.styleable.A 。
其中包括很多方法,用来获取这个容器中包含的值.getColor()获取颜色值.getDimension()获取尺寸值。这些方法一般都有这两个参数int index, int defValue。其中index为用来查找属性的检索值。如果是在attrs.xml文件中定义的属性,就是R.styleable.xx_yy。xx代表declare-styleable的name值,yy代表attr的name值。defValue代表默认值,即如果在xml文件中没有设置,可以使用默认值来进行设置。
AttributeSet是一个属性的集合,与一个在XML文件中的标签相联系。如在自定义View中,构造方法中会有一个AttributeSet类型的参数,这个参数就和XML中定义的自定义View相联系的。一般不需要直接使用它。
好了添加完上面那些就完成了对自定义view的属性构造,那大家一定会有疑问,这些个方法是用来干什么的?为什么要添加他们?别急,这里我再来讲解:
·public SlideSwitch(Context context) \\ 当在代码中创建对象时会被调用
·public SlideSwitch (Context context, AttributeSet attrs)
官方的文档是:
Constructor that is called when inflating a view from XML. This is called when a view is being constructed from an XML file, supplying attributes that were specified in the XML file. This version uses a default style of 0, so the only attribute values applied are those in the Context's Theme and the given AttributeSet
从这可以知道这个方法是当我们在xml文件来创建一个view对象的时候调用。xml文件一般是布局文件,就是现实控件的时候调用,
两个参数
Context The Context the view is running in, through which it can access the current theme,Attrs The attributes of the XML tag that is inflating the view
·public SlideSwitch (Context context, AttributeSet attrs,int defStyle)
官方的文档是:
Perform inflation from XML and apply a class-specific base style. This constructor of View allows subclasses to use their own base style when they are inflating. For example, a Button class's constructor would call this version of the super class constructor and supply R.attr.buttonStyle fordefStyle; this allows the theme's button style to modify all of the base view attributes (in particular its background) as well as the Button class's attributes.
大意是:当我们需要通过xml给view定义style主题的时候允许我们按照自己的需求去定义自己的主题。就像我们要给一个Button定义新的背景主题就可以通过此方法。当然给button定义背景其实写一个xml然后设置他的background属性就好了。这里主要说的是自定义view的主题设置需要用的此方法。
三、重写onMeasure()
<pre name="code" class="html">@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = measureDimension(280, widthMeasureSpec); int height = measureDimension(140, heightMeasureSpec); // 这里是当滑块形状是圆形时,如果view的宽度小于高度了就给宽度重新赋值为高的两倍。 if (shape == SHAPE_CIRCLE) { if (width < height) width = height * 2; } //ViewGroup初始是没有大小的,自定义时需要在onMeasure中设置。 setMeasuredDimension(width, height); initDrawingVal();//对于一些值的初始化,后面会讲到。 } //根据测量的值返回不同的结果值 public int measureDimension(int defaultSize, int measureSpec) { int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = defaultSize; // UNSPECIFIED if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; }
onMeasure()顾名思义就是测量view的大小,此方法接收两个参数,宽详细测量值(widthMeasureSpec)和高详细测量值(heightMeasureSpec)。这两个值分别用于确定视图的宽度和高度的规格和大小。MeasureSpec的值由specSize和specMode共同组成的,其中specSize记录的是大小,specMode记录的是规格。specMode一共有三种类型,如下所示:
1. EXACTLY
表示父视图希望子视图的大小应该是由specSize的值来决定的,系统默认会按照这个规则来设置子视图的大小,开发人员当然也可以按照自己的意愿设置成任意的大小。
2. AT_MOST
表示子视图最多只能是specSize中指定的大小,开发人员应该尽可能小得去设置这个视图,并且保证不会超过specSize。系统默认会按照这个规则来设置子视图的大小,开发人员当然也可以按照自己的意愿设置成任意的大小。
3. UNSPECIFIED
表示开发人员可以将视图按照自己的意愿设置成任意的大小,没有任何限制。这种情况比较少见,不太会用到。
基本上知道上面几点就差不多了,但是学习要讲求专研,对于里面的具体实现细节我们要是能知道就最好不过了。这里介于内部实现比较多就不占用篇幅来写了,大家有兴趣的可以参考下:
http://blog.csdn.net/a396901990/article/details/36475213
http://blog.csdn.net/guolin_blog/article/details/16330267 (郭霖大神)
这两篇博客已经写的很详细了,相信大家看完就能了解了,这里我们还是继续写对于SlideSwitch的解析。
static final int SHAPE_RECT = 1; //表示长方形 public static final int SHAPE_CIRCLE = 2; //表示圆形 private static final int RIM_SIZE = 6; // 开关滑块与边框的边距,默认6像素。 private static final int DEFAULT_COLOR_THEME = Color.parseColor("#ff00ee00"); //默认滑动颜色 // 3 attributes private int color_theme; // 自定义主题颜色参数 private boolean isOpen; // 开关是否打开 private int shape; // 对于形状的判断 // varials of drawing private Paint paint; // 画笔 private Rect backRect; // 长方形的背景边框 private Rect frontRect; // 长方形的滑块 private RectF frontCircleRect; //圆形的滑块 private RectF backCircleRect; //圆形的背景边框 private int alpha; // 滑动滑块时的背景渐变效果,通过修改透明度值实现 private int max_left; // 当滑块打开时距离左边的距离 private int min_left; // 当滑块关闭时距离左边的距离 private int frontRect_left; // 实时记录滑块滑动时离左边的距离 private int frontRect_left_begin = RIM_SIZE; // 记录滑块离左边的距离(max_left,min_left,手指抬起时) private int eventStartX; //手指按下的位置 private int eventLastX; //手指抬起时的位置 private int diffX = 0; //手指滑动的距离 private boolean slideable = true; //控制滑块可否滑动 private SlideListener listener; //滑动开关的监听接口 public interface SlideListener { public void open(); public void close(); }
<span style="white-space:pre"> </span>public void initDrawingVal() { int width = getMeasuredWidth(); int height = getMeasuredHeight(); backCircleRect = new RectF(); frontCircleRect = new RectF(); frontRect = new Rect(); backRect = new Rect(0, 0, width, height); min_left = RIM_SIZE; if (shape == SHAPE_RECT) max_left = width / 2; else max_left = width - (height - 2 * RIM_SIZE) - RIM_SIZE; if (isOpen) { frontRect_left = max_left; alpha = 255; } else { frontRect_left = RIM_SIZE; alpha = 0; } frontRect_left_begin = frontRect_left; }
这是对view的一些初始化操作,RIM_SIZE 是滑块与边框的边距,默认6,max_left 是滑块打开时滑块右边缘与边框最右边的距离,当shape是长方形时就是整个view宽度的一半,当是圆形时就是整个宽度减去滑块的直径与边缘的距离,滑块直径就是(height - 2 * RIM_SIZE),不清楚的在纸上拿笔画下就知道了。min_left是滑块关闭时与边缘的距离,这里就是RIM_SIZE的大小6。
@Override protected void onDraw(Canvas canvas) { if (shape == SHAPE_RECT) { paint.setColor(Color.GRAY); //画笔为灰色,先绘制背景颜色,也是开关关闭时候的背景色 canvas.drawRect(backRect, paint); paint.setColor(color_theme); //此处是绘制开关开启时候的背景颜色 paint.setAlpha(alpha); canvas.drawRect(backRect, paint); //此处是设置滑块的大小及位置。 frontRect.set(frontRect_left, RIM_SIZE, frontRect_left + getMeasuredWidth() / 2 - RIM_SIZE, getMeasuredHeight() - RIM_SIZE); paint.setColor(Color.WHITE); canvas.drawRect(frontRect, paint); } else { // draw circle int radius; radius = backRect.height() / 2 - RIM_SIZE; paint.setColor(Color.GRAY); backCircleRect.set(backRect); canvas.drawRoundRect(backCircleRect, radius, radius, paint); paint.setColor(color_theme); paint.setAlpha(alpha); canvas.drawRoundRect(backCircleRect, radius, radius, paint); frontRect.set(frontRect_left, RIM_SIZE, frontRect_left + backRect.height() - 2 * RIM_SIZE, backRect.height() - RIM_SIZE); frontCircleRect.set(frontRect); paint.setColor(Color.WHITE); canvas.drawRoundRect(frontCircleRect, radius, radius, paint); } }
@Override public boolean onTouchEvent(MotionEvent event) { getParent().requestDisallowInterceptTouchEvent(true); //通知父控件勿拦截本控件touch事件 if (slideable == false) return super.onTouchEvent(event); int action = MotionEventCompat.getActionMasked(event);//这是用于多指触控 switch (action) { case MotionEvent.ACTION_DOWN: eventStartX = (int) event.getRawX();//手指按下点 break; case MotionEvent.ACTION_MOVE: eventLastX = (int) event.getRawX(); diffX = eventLastX - eventStartX; int tempX = diffX + frontRect_left_begin;//手指滑动的距离加上离左边的距离 tempX = (tempX > max_left ? max_left : tempX); tempX = (tempX < min_left ? min_left : tempX); //当tempX处于min_left和max_left之间时代表滑块正处于滑动状态,需要根据透明度来改变背景色,调用刷新 if (tempX >= min_left && tempX <= max_left) { frontRect_left = tempX; alpha = (int) (255 * (float) tempX / (float) max_left); invalidateView(); } break; case MotionEvent.ACTION_UP: int wholeX = (int) (event.getRawX() - eventStartX); frontRect_left_begin = frontRect_left; boolean toRight; //frontRect_left就是滑块滑动的距离,这里判断他是否滑过了中心点,如果过了,我们就让它自动划过去。 toRight = (frontRect_left_begin > max_left / 2 ? true : false); //这个加上绝对值来判断实际滑动的距离 if (Math.abs(wholeX) < 3) { toRight = !toRight; } moveToDest(toRight); // 后面会讲到。 break; default: break; } return true; }
这一段代码是对手势的监听处理,上面注释也很详细了,其中有一点需要提一下,就是第三行代码
getParent().requestDisallowInterceptTouchEvent(true);这个是之前做的时候发现的一个bug,就是如果把按钮放在了srcollview这样可以滑动的布局里面话会造成事件冲突,需要上面这一句来进行拦截,这一块就涉及到事件的分发机制了,这是很重要的一点。事件分发机制也是很重要的一块,以后有时间可以单独来出来讲讲,需要的同学可以上网搜搜,有很多这方面的文章。
public void moveToDest(final boolean toRight) { ValueAnimator toDestAnim = ValueAnimator.ofInt(frontRect_left, toRight ? max_left : min_left); toDestAnim.setDuration(500); toDestAnim.setInterpolator(new AccelerateDecelerateInterpolator()); toDestAnim.start(); toDestAnim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { frontRect_left = (Integer) animation.getAnimatedValue(); alpha = (int) (255 * (float) frontRect_left / (float) max_left); invalidateView(); } }); toDestAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (toRight) { isOpen = true; if (listener != null) listener.open(); frontRect_left_begin = max_left; } else { isOpen = false; if (listener != null) listener.close(); frontRect_left_begin = min_left; } } }); }
注意到上一段最后调用的moveToDest(final boolean toRight)方法,这其实就是对属性动画的操作,根据toRight来判断是否进行滑动,往哪边滑动。属性动画也是学习android不可不知的,android真是博大精深,缺少一点知识都不行,对于属性动画这里就不进行讲解了,一两句也是讲不清楚。这里推荐郭大神的博客
http://blog.csdn.net/guolin_blog/article/details/43536355,有兴趣的同学自己去看吧。 最后属性动画结束后不忘初始化frontRect_left_begin 的值。
接下来贴出全部的代码大家看看:
package com.slideswitchbutton; import com.test.R; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.os.Bundle; import android.os.Looper; import android.os.Parcelable; import android.support.v4.view.MotionEventCompat; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; public class SlideSwitch extends View { public static final int SHAPE_RECT = 1; public static final int SHAPE_CIRCLE = 2; private static final int RIM_SIZE = 6; private static final int DEFAULT_COLOR_THEME = Color.parseColor("#ff00ee00"); // 3 attributes private int color_theme; private boolean isOpen; private int shape; // varials of drawing private Paint paint; private Rect backRect; private Rect frontRect; private RectF frontCircleRect; private RectF backCircleRect; private int alpha; private int max_left; private int min_left; private int frontRect_left; private int frontRect_left_begin = RIM_SIZE; private int eventStartX; private int eventLastX; private int diffX = 0; private boolean slideable = true; private SlideListener listener; public interface SlideListener { public void open(); public void close(); } public SlideSwitch(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); listener = null; paint = new Paint(); paint.setAntiAlias(true); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.slideswitch); color_theme = a.getColor(R.styleable.slideswitch_themeColor, DEFAULT_COLOR_THEME); isOpen = a.getBoolean(R.styleable.slideswitch_isOpen, false); shape = a.getInt(R.styleable.slideswitch_shape, SHAPE_RECT); a.recycle(); } public SlideSwitch(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlideSwitch(Context context) { this(context, null); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = measureDimension(280, widthMeasureSpec); int height = measureDimension(140, heightMeasureSpec); if (shape == SHAPE_CIRCLE) { if (width < height) width = height * 2; } //ViewGroup初始是没有大小的,自定义时需要在onMeasure中设置。 setMeasuredDimension(width, height); initDrawingVal(); } public void initDrawingVal() { int width = getMeasuredWidth(); int height = getMeasuredHeight(); backCircleRect = new RectF(); frontCircleRect = new RectF(); frontRect = new Rect(); backRect = new Rect(0, 0, width, height); min_left = RIM_SIZE; if (shape == SHAPE_RECT) max_left = width / 2; else max_left = width - (height - 2 * RIM_SIZE) - RIM_SIZE; if (isOpen) { frontRect_left = max_left; alpha = 255; } else { frontRect_left = RIM_SIZE; alpha = 0; } frontRect_left_begin = frontRect_left; } public int measureDimension(int defaultSize, int measureSpec) { int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = defaultSize; // UNSPECIFIED if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } @Override protected void onDraw(Canvas canvas) { if (shape == SHAPE_RECT) { paint.setColor(Color.GRAY); canvas.drawRect(backRect, paint); paint.setColor(color_theme); paint.setAlpha(alpha); canvas.drawRect(backRect, paint); frontRect.set(frontRect_left, RIM_SIZE, frontRect_left + getMeasuredWidth() / 2 - RIM_SIZE, getMeasuredHeight() - RIM_SIZE); paint.setColor(Color.WHITE); canvas.drawRect(frontRect, paint); } else { // draw circle int radius; radius = backRect.height() / 2 - RIM_SIZE; paint.setColor(Color.GRAY); backCircleRect.set(backRect); canvas.drawRoundRect(backCircleRect, radius, radius, paint); paint.setColor(color_theme); paint.setAlpha(alpha); canvas.drawRoundRect(backCircleRect, radius, radius, paint); frontRect.set(frontRect_left, RIM_SIZE, frontRect_left + backRect.height() - 2 * RIM_SIZE, backRect.height() - RIM_SIZE); frontCircleRect.set(frontRect); paint.setColor(Color.WHITE); canvas.drawRoundRect(frontCircleRect, radius, radius, paint); } } @Override public boolean onTouchEvent(MotionEvent event) { getParent().requestDisallowInterceptTouchEvent(true); //通知父控件勿拦截本控件touch事件 if (slideable == false) return super.onTouchEvent(event); int action = MotionEventCompat.getActionMasked(event);//这是用于多指触控 switch (action) { case MotionEvent.ACTION_DOWN: eventStartX = (int) event.getRawX();//手指按下点 break; case MotionEvent.ACTION_MOVE: eventLastX = (int) event.getRawX(); diffX = eventLastX - eventStartX; int tempX = diffX + frontRect_left_begin;//手指滑动的距离加上离左边的距离 tempX = (tempX > max_left ? max_left : tempX); tempX = (tempX < min_left ? min_left : tempX); //当tempX处于min_left和max_left之间时代表滑块正处于滑动状态,需要根据透明度来改变背景色,调用刷新 if (tempX >= min_left && tempX <= max_left) { frontRect_left = tempX; alpha = (int) (255 * (float) tempX / (float) max_left); invalidateView(); } break; case MotionEvent.ACTION_UP: int wholeX = (int) (event.getRawX() - eventStartX); frontRect_left_begin = frontRect_left; boolean toRight; //frontRect_left就是滑块滑动的距离,这里判断他是否滑过了中心点,如果过了,我们就让它自动划过去。 toRight = (frontRect_left_begin > max_left / 2 ? true : false); //有时候我们按住来回滑动也会导致frontRect_left_begin的值大于一半,但是这是我们不希望出现的, //这个加上绝对值来判断实际滑动的距离,确保不出现误判 if (Math.abs(wholeX) < 3) { toRight = !toRight; } moveToDest(toRight); break; default: break; } return true; } /** * draw again */ private void invalidateView() { if (Looper.getMainLooper() == Looper.myLooper()) { invalidate(); } else { postInvalidate(); } } public void setSlideListener(SlideListener listener) { this.listener = listener; } public void moveToDest(final boolean toRight) { ValueAnimator toDestAnim = ValueAnimator.ofInt(frontRect_left, toRight ? max_left : min_left); toDestAnim.setDuration(500); toDestAnim.setInterpolator(new AccelerateDecelerateInterpolator()); toDestAnim.start(); toDestAnim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { frontRect_left = (Integer) animation.getAnimatedValue(); alpha = (int) (255 * (float) frontRect_left / (float) max_left); invalidateView(); } }); toDestAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (toRight) { isOpen = true; if (listener != null) listener.open(); frontRect_left_begin = max_left; } else { isOpen = false; if (listener != null) listener.close(); frontRect_left_begin = min_left; } } }); } public void setState(boolean isOpen) { this.isOpen = isOpen; initDrawingVal(); invalidateView(); if (listener != null) if (isOpen == true) { listener.open(); } else { listener.close(); } } public void setShapeType(int shapeType) { this.shape = shapeType; } public void setSlideable(boolean slideable) { this.slideable = slideable; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; this.isOpen = bundle.getBoolean("isOpen"); state = bundle.getParcelable("instanceState"); } super.onRestoreInstanceState(state); } @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable("instanceState", super.onSaveInstanceState()); bundle.putBoolean("isOpen", this.isOpen); return bundle; } }</span><span style="font-size:24px;"> </span>
接着在xml文件中声明就可以使用了:
<span style="font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:slideswitch="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.slideswitchbutton.SlideSwitch android:id="@+id/slidebt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" slideswitch:isOpen="true" slideswitch:shape="circle" slideswitch:themeColor="#ff73aa00" > </com.slideswitchbutton.SlideSwitch> </LinearLayout></span>
最后在Activity里面声明调用就好了:
public class MainActivity extends Activity { private SlideSwitch slide; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); slide = (SlideSwitch) findViewById(R.id.slidebt); // slide.setState(true); //设置状态 slide.setSlideListener(new SlideListener() { @Override public void open() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"打开了..." , Toast.LENGTH_SHORT).show(); } @Override public void close() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this,"关闭了..." , Toast.LENGTH_SHORT).show(); } }); }
好了今天讲解就到这里了,第一次发博客讲的不好的地方请担待。(突然发现写博客也是好累的。自己理解了简单,但是要讲解出来还要别人能懂也是很难的。在此敬佩大神前辈们)。