自定义控件专题之二:滑动开关

来源:互联网 发布:华劲集团待遇知乎 编辑:程序博客网 时间:2024/05/22 01:34

总体思想

我们可以把该控件的实现分成多个步骤进行:
(1)、实现开关的绘制,使开关能正确显示在手机上
(2)、实现开关的滑动

1、开关的绘制


首先在布局activity_main.xml中放置该开关,宽高选择包裹内容,实际的大小和图片我们将在java代码中指定
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="cn.hugo.android.slidetoggle.MainActivity" ><!--必须需要把自定义的控件的包名和类名写完整-->    <cn.hugo.android.slidetoggle.widget.SlideToggle        android:id="@+id/toggle"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true" >    </cn.hugo.android.slidetoggle.widget.SlideToggle></RelativeLayout>

然后,在activity中设置该布局文件MainActivity.java

package cn.hugo.android.slidetoggle;import android.app.Activity;import android.os.Bundle;import cn.hugo.android.slidetoggle.widget.SlideToggle;public class MainActivity extends Activity {private SlideToggle toggle;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);toggle = (SlideToggle) findViewById(R.id.toggle);toggle.setToggleState(true); //设置开关状态为打开}}




最后定义一个继承view的滑动开关控件,SlideToggle.java

package cn.hugo.android.slidetoggle.widget;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.View;import cn.hugo.android.slidetoggle.R;public class SlideToggle extends View {private Bitmap slideButton;private Bitmap switchButton;private boolean mState; // 开关状态public SlideToggle(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SlideToggle(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);slideButton = BitmapFactory.decodeResource(getResources(),R.drawable.slide_button_background);switchButton = BitmapFactory.decodeResource(getResources(),R.drawable.switch_background);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 把开关的背景画到画布上canvas.drawBitmap(switchButton, 0, 0, null);// 根据开关状态把可移动的背景描绘在画布上if (mState) {canvas.drawBitmap(slideButton, switchButton.getWidth()- slideButton.getWidth(), 0, null);}else {canvas.drawBitmap(slideButton, 0, 0, null);}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 设置控件的宽和高,为背景图片的宽高setMeasuredDimension(switchButton.getWidth(), switchButton.getHeight());}/** * 设置开关状态 *  * @param b *            true:开;false:关 */public void setToggleState(boolean b) {this.mState = b;}}




Canvas.drawBitmap(Bitmap bitmap,float left, float top,Paint paint)  方法,是在该控件中绘制图画,其中bitmap是需
要绘制的图,left和top是把该图画在距离该控件左边、上边的距离的位置。现在,安装该应用后,显示效果如下图:



2、实现滑动

我们此时需要覆盖View的public boolean onTouchEvent(MotionEvent event);方法,对手指的按下、移动、移开操作进行处理。有些细节需要进行特殊处理,比如滑块滑出控件,开关状态的处理等。

package cn.hugo.android.slidetoggle.widget;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import cn.hugo.android.slidetoggle.R;public class SlideToggle extends View {private Bitmap slideButton;private Bitmap switchButton;private boolean mState; // 开关状态private float mCurrentX; // 记录手指按下的位置private boolean isSliding; // 是否正在滑动public SlideToggle(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SlideToggle(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);slideButton = BitmapFactory.decodeResource(getResources(),R.drawable.slide_button_background);switchButton = BitmapFactory.decodeResource(getResources(),R.drawable.switch_background);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 把开关的背景画到画布上canvas.drawBitmap(switchButton, 0, 0, null);if (isSliding) { // 正在对开关进行滑动float left = mCurrentX - slideButton.getWidth() / 2; // 使滑块处于手指的中间位置// 避免滑块滑出控件范围if (left < 0) {left = 0;}else if (left > switchButton.getWidth() - slideButton.getWidth()) {left = switchButton.getWidth() - slideButton.getWidth();}canvas.drawBitmap(slideButton, left, 0, null);}else {// 根据开关状态把可移动的背景描绘在画布上if (mState) {canvas.drawBitmap(slideButton, switchButton.getWidth()- slideButton.getWidth(), 0, null);}else {canvas.drawBitmap(slideButton, 0, 0, null);}}}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN: {mCurrentX = event.getX(); // 记录按下时相对控件的x轴位置,event.getRawX是相对整个屏幕的x位置isSliding = true;break;}case MotionEvent.ACTION_UP: {isSliding = false;// 判断当前状态属于何种状态,把开关设置为相应状态mState = mCurrentX > switchButton.getWidth() / 2; // 移开滑块的x位置大于开关背景一半,则视为打开状态break;}case MotionEvent.ACTION_MOVE: {mCurrentX = event.getX();break;}default:break;}invalidate(); // 使控件调用一次onDraw()方法return true; // 消耗触摸事件,事件不再传递}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 设置控件的宽和高,为背景图片的宽高setMeasuredDimension(switchButton.getWidth(), switchButton.getHeight());}/** * 设置开关状态 *  * @param b *            true:开;false:关 */public void setToggleState(boolean b) {this.mState = b;}}




总的来说还是比较简单的。

源码链接:

我是源码链接



0 0
原创粉丝点击