天天看点

SwitchButton 开关按钮 的多种实现方式

刚开始接触开关样式的按钮是在IOS系统上面,它的切换以及滑动十分帅气,深入人心。

所谓的开关按钮,就是只有2个状态:on和off,下图就是系统IOS 7上开关按钮效果。

SwitchButton 开关按钮 的多种实现方式

起初我在android上我只会使用CheckBox去满足对应的功能。后来,查看开发文档发现,android也有了自己的原生态开关控件,并且在4.0版本中又优化加入了新的类似控件--Switch控件,以及使用起来十分简单的ToggleButton,可是它们只是带有切换效果,而不带有滑动切换效果,并且Switch控件只支持高版本的系统,对于2.3就不支持。所以,要想看如何实现滑动切换的效果,必须了解这些控件的实现方式。下面,让我们查看下android开发文档,看看这些是如何实现使用的。

注意:本文中涉及到自定义控件 并自定义配置属性declare-styleable,

查看查看开发文档:

CompoundButton

<a target="_blank">java.lang.Object</a>

<a target="_blank">android.view.View</a>

<a target="_blank">android.widget.TextView</a>

<a target="_blank">android.widget.Button</a>

android.widget.CompoundButton

Known Direct Subclasses

以上4类都是开关类型切换的控件,它们的父类都是CompoundButton。

 它对应的方法和类有:

点击选择监听接口。

Nested Classes

interface

<a target="_blank">CompoundButton.OnCheckedChangeListener</a>

Interface definition for a callback to be invoked when the checked state of a compound button changed.

返回左右填充的VIEW,加上间隔

Public Methods

int

boolean:是否被选中。

boolean

设置Button的Drawable属性

void

设置是否选中

改变当前的状态,true--&gt;false  ;false--&gt;true

控件全局 绘制

 protected void onDraw (Canvas canvas)

         实现你自己的绘制。

                   参数

                            canvas    在画布上绘制背景

   protected boolean verifyDrawable (Drawable who)

         如果你的视图子类显示他自己的可视化对象,他将要重写此方法并且为了显示可绘制返回true。此操作允许进行绘制时有动画效果。

  确认当重写从方法时,需调用父类相应方法。

                            who         需判断的可绘制对象(Drawable)。如果是你要显示的对象,返回True,否则返回调用父类的结果。

                   返回值

                           boolean 如果可绘制对象(Drawable)已经在视图中显示,返回True否则返回false。并且此处不允许使用动画。

下面让我们来看看如何实现这个效果把:

一.使用ToggleButton控件实现:

使用ToggleButton控件十分方便,你可以看作他为一个CheckBox,只用设置它的button、background等几个属性即可。

首先:res--创建drawable文件夹 -- 创建switch_btn.xml资源文件--作以下配置

&lt;?xml version="1.0" encoding="utf-8"?&gt;  

&lt;selector  

  xmlns:android="http://schemas.android.com/apk/res/android"&gt;  

    &lt;item android:state_checked="true" android:drawable="@drawable/ios7_switch_on" /&gt;  

    &lt;item android:drawable="@drawable/ios7_switch_off" /&gt;  

&lt;/selector&gt;  

其中:android:state_checked="true" 表示选中on时候的,效果为:android:drawable="@drawable/ios7_switch_on" 

     反之就是未选中off情况下的效果:android:drawable="@drawable/ios7_switch_off"

之后在布局文件中写控件:

&lt;ToggleButton  

        android:id="@+id/mTogBtn"  

        android:layout_width="wrap_content"  

        android:layout_height="wrap_content"  

        android:layout_gravity="center_horizontal"  

        android:background="@android:color/transparent"  

        android:button="@drawable/toggle_btn"  

        android:checked="false"  

        android:text=""  

        android:textOff=""  

        android:textOn="" /&gt;  

这里的    

android:textOn=""   表示:选中情况下显示的文本

android:textOff=""   表示:未选中情况下显示的文本

android:checked="false"  表示:初始化时候,默认是未选中的

android:button="@drawable/toggle_btn"  表示:button样式

android:background="@android:color/transparent"  表示:背景,这里不用它的默认背景,所以设置为透明

之后在主程序中实例化,并设置checked点击监听

ToggleButton mTogBtn = (ToggleButton) findViewById(R.id.mTogBtn); // 获取到控件  

mTogBtn.setOnCheckedChangeListener(new OnCheckedChangeListener() {  

    @Override  

    public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {  

        // TODO Auto-generated method stub  

        if(isChecked){  

            //选中  

        }else{  

            //未选中  

        }  

    }  

});// 添加监听事件  

这样ToggleButton的开关切换就轻松实现了。

二.重写CompoundButton控件实现带滑动效果的开关按钮:

    重写CompuundButton的实现可能会显得相对繁琐些,主要是考虑状态是否已经选中等情况的文字显示。

    可以查看官方文档,之后继承CompuundButton,在布局的动画和显示上调用onDraw(Canvas canvas)重画既可以,如果想要加入拖动属性,那么在该VIEW内重写触摸事件onTouchEvent(MotionEvent ev)在里面判断拖动距离,之后根据拖动情况判断开关是on还是off。

    由于继承的是CompoundButton,所以里面的监听方法,setChecked等方法都是自带的,继承下来写操作就可以了,不用自己在去加判断什么的属性了。

    具体的这边不贴代码了,可以查看DEMO里面的,都有注释。

三.重写CheckBox控件实现带滑动效果的开关按钮:

    其实,看上面给的开发文档内容,大家都可以知道,CheckBox其实就是继承CompoundButton控件的,只是重构CheckBox会比CompoundButton方便好多,里面的很多方法都是写好的,只要自己去判断触摸事件onTouchEvent(MotionEvent ev),以及onDraw(Canvas canvas)重画就可以。这里DEMO中使用到的是第3放库内的一个控件,大致操作和上面其实大同小异。

四.重写View实现带滑动效果的开关按钮:

   众所周知,以上所有的控件都是继承了View这个父类,所以,如果你用View去操作的话,就没有自带方法的限制,可是要满足你要 实现的SwitchButton效果,你必须自己写开关状态监听接口,并且自己写setChecked方法实现同等的效果。在优化方面要自己多加细心考虑。其他操作与以上控件的重构大同小异。

    注意:由于状态切换等,enabled属性改变等,是你自定义的方法内的话,你必须自己去调用invalidate();方法,去让UI判断是否有更改并做出相应的变化。

例如:

@Override  

public void setEnabled(boolean enabled) {  

    // TODO Auto-generated method stub  

    mEnabled = enabled;  

    mAlpha = enabled ? MAX_ALPHA : MAX_ALPHA/2;  

    Log.d("enabled",enabled ? "true": "false");  

    super.setEnabled(enabled);  

    invalidate();  

}  

/** 自动判断切换至相反的属性 : true --&gt;false ;false --&gt;true */  

public void toggle() {  

    setChecked(!mSwitchOn);  

   /** 设置选中的状态(选中:true   非选中: false) */  

   public void setChecked(boolean checked) {  

    mSwitchOn = checked;  

       invalidate();  

   }  

还有,你如果是自定义的VIEW,你在里面设置了enabled属性,你必须在onTouchEvent(MotionEvent event)触摸操作的时候判断你所设置的enabled属性是否为true,是的话就可以相应点击事件,否则的话你要屏蔽掉点击事件。因为你自定义的view中的enabled属性并不知道他设定后会达到什么效果,这些都是要注意的点。

还有就是要设置接口监听状态变化:

/**  

 * 设置 switch 状态监听  

 * */  

public void setOnChangeListener(OnSwitchChangedListener listener) {  

    switchListener = listener;  

 * switch 开关监听接口 

 *  */  

public interface OnSwitchChangedListener{  

    public void onSwitchChange(SlideSwitchView switchView, boolean isChecked);  

有的人可能会希望有SwitchButton在enabled设置为false的时候,SwitchButton不能点击且要改变颜色,使他看过去是不能点击的。你可以进行如下操作(在学习别的人代码中得到的提示,学以致用):

先初始化透明度:255为不透明

/** 最大透明度,就是不透明 */  

private final int MAX_ALPHA = 255;  

/** 当前透明度,这里主要用于如果控件的enable属性为false时候设置半透明 ,即不可以点击 */  

private int mAlpha = MAX_ALPHA;  

之后重写setEnabled方法,通过这个方法判断enabled属性值

如果改变了enabled属性,系统便会查看UI是否需要变化,之后在UI方法onDraw(Canvas canvas)中调用:

android.graphics.Canvas.saveLayerAlpha(RectF bounds, int alpha, int saveFlags)  

方法,其中的第2个属性alpha就是透明度,之后便可以实现相应的效果。

由于目前对于重写VIEW的onDraw方法的了解不是很深入,所以这里的DEMO中的几个方法都是查看网络之后加上自己的优化和注释演变过来,等这一块深入了后在重写写一篇关于这个的感受和使用说明。由于可能理解不是很深刻,如果有什么不足之处可以提出,谢谢。

最后让我们来看看效果如何,上图:

SwitchButton 开关按钮 的多种实现方式
SwitchButton 开关按钮 的多种实现方式

本文转自欢醉博客园博客,原文链接http://www.cnblogs.com/zhangs1986/p/3776386.html如需转载请自行联系原作者

欢醉

继续阅读