自定义控件ToggleButton滑动开关

---恢复内容开始---

滑动开关--------
自定义控件步骤:
测量:onMeasure 设置自己显示在屏幕上的宽高
布局:onLayout 设置自己显示在屏幕上的位置(只有在自定义ViewGroup中才用到)
绘制:onDraw 控制显示在屏幕上的样子(自定义viewgroup时不需要这个)

View和ViewGroup的区别
1.他们都需要进行测量操作
2.ViewGroup主要是控制子view如何摆放,所以必须实现onLayout
View没有子view,所以不需要onLayout方法,但是必须实现onDraw

 

 

然后要想你设计这个控件能够有哪些功能?

1.设置滑动开关的背景图片,

2.设置滑动开关的滑块图片,

3.设置滑动开关的状态,

然后有了这些功能需求就可以进行代码的编写,

这次我们要自定义一个view,所以要继承view,实现它的构造方法,然后要实现设置图片的两个方法,和设置开关状态的方法,这里开关状态用了枚举类型。

因为绘制的时候只能绘制bitmap类型,所以要进行转化

    /**
     * 选择框的背景
     * 
     * @param icLauncher
     */
    public void setSwitchBackgroundResource(int icLauncher) {
        switchBg = BitmapFactory.decodeResource(getResources(), icLauncher);

    }

    /**
     * 滑动按钮背景
     * 
     * @param icLauncher
     */
    public void setSlideBackgroundResouce(int icLauncher) {
        slideBg = BitmapFactory.decodeResource(getResources(), icLauncher);
    }

    /**
     * 设置开关的初始状态
     * 
     * @param state
     */
    public void setSlideStare(ToggleState state) {
        togglestate = state;
    }

然后要重写测量方法,就是背景图片的宽高

/**
     * 设置当前控件显示在屏幕上的宽高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(switchBg.getWidth(), switchBg.getHeight());
    }

测量之后要进行绘制

首先绘制分为两种,

一种是滑动中绘制,

还有一种是不滑动根据设置的状态进行绘制

滑动中绘制:这个主要就是通过Touch事件来改变滑块距离左侧的值来进行绘制

@Override
    public boolean onTouchEvent(MotionEvent event) {
        //改变的值
     currentX
= (int) event.getX(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; // 松开的时候看当前X的值在哪里 case MotionEvent.ACTION_UP: break; case MotionEvent.ACTION_MOVE: break; } // 由它来调用ondraw方法 invalidate(); return true; }

绘制方法

    /*
             * 设置在正中间
             */
            int left = currentX - slideBg.getWidth() / 2;
            if (left < 0) {
                left = 0;
            } else if (left >= (switchBg.getWidth() - slideBg.getWidth())) {
                left = switchBg.getWidth() - slideBg.getWidth();
            }

另外一种就是不滑动根据状态绘制。首先要规定出状态,状态布尔值默认是false,然后当down变成true,当up时候重新变成false

// 绘制滑块
            // 判断滑块的状态
            // 打开
            if (togglestate == ToggleState.Open) {
                canvas.drawBitmap(slideBg,
                        switchBg.getWidth() - slideBg.getWidth(), 0, null);
                // 关闭
            } else {
                canvas.drawBitmap(slideBg, 0, 0, null);
            }

完整代码

package com.example.tbtn.view;

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;

public class ToggleButton extends View {
    // 设置的状态
    private ToggleState togglestate = ToggleState.Open;
    // 选择背景
    private Bitmap switchBg;
    // 滑动按钮背景
    private Bitmap slideBg;
    // 点击的X值
    private int currentX = 0;
    // 是否滑动
    private boolean isSliding = false;

    // 枚举类型
    public enum ToggleState {
        Open, Close
    }

    /**
     * 布局文件引用调用
     * 
     * @param context
     * @param attrs
     */
    public ToggleButton(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    /**
     * 代码使用调用
     * 
     * @param context
     */
    public ToggleButton(Context context) {
        super(context);

    }

    /**
     * 选择框的背景
     * 
     * @param icLauncher
     */
    public void setSwitchBackgroundResource(int icLauncher) {
        switchBg = BitmapFactory.decodeResource(getResources(), icLauncher);

    }

    /**
     * 滑动按钮背景
     * 
     * @param icLauncher
     */
    public void setSlideBackgroundResouce(int icLauncher) {
        slideBg = BitmapFactory.decodeResource(getResources(), icLauncher);
    }

    /**
     * 设置开关的初始状态
     * 
     * @param state
     */
    public void setSlideStare(ToggleState state) {
        togglestate = state;
    }

    /**
     * 设置当前控件显示在屏幕上的宽高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(switchBg.getWidth(), switchBg.getHeight());
    }

    /**
     * 绘制
     */
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        // left 距图片左侧 top 距图片上部
        canvas.drawBitmap(switchBg, 0, 0, null);

        if (isSliding) {
            /*
             * 设置按在正中间
             */
            int left = currentX - slideBg.getWidth() / 2;
            if (left < 0) {
                left = 0;
            } else if (left >= (switchBg.getWidth() - slideBg.getWidth())) {
                left = switchBg.getWidth() - slideBg.getWidth();
            }
            canvas.drawBitmap(slideBg, left, 0, null);
        } else {
            // 绘制滑块
            // 判断滑块的状态
            // 打开
            if (togglestate == ToggleState.Open) {
                canvas.drawBitmap(slideBg,
                        switchBg.getWidth() - slideBg.getWidth(), 0, null);
                // 关闭
            } else {
                canvas.drawBitmap(slideBg, 0, 0, null);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        currentX = (int) event.getX();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            isSliding = true;
            break;
        // 松开的时候看当前X的值在哪里
        case MotionEvent.ACTION_UP:
            isSliding = false;
            // 图片中心点
            int centerX = switchBg.getWidth() / 2;
            // 打开
            if (currentX > centerX) {
                // 判断当前状态是否真的改变(就是滑动一半回去了)
                if (togglestate != ToggleState.Open) {
                    togglestate = ToggleState.Open;
                    // 设置回调借口
                    if (lisern != null) {
                        lisern.onToggleChange(togglestate);
                    }
                }
                // 关闭
            } else {
                if (togglestate != ToggleState.Close) {
                    togglestate = ToggleState.Close;
                    // 设置回调借口
                    if (lisern != null) {
                        lisern.onToggleChange(togglestate);
                    }
                }
            }

            break;
        case MotionEvent.ACTION_MOVE:

            break;
        }
        // 由它来调用ondraw方法
        invalidate();
        return true;
    }

    private OnToggleChangeLisern lisern;

    public void setOnToggleChangeLisern(OnToggleChangeLisern lisern) {
        this.lisern = lisern;
    }

    // 回调接口
    public interface OnToggleChangeLisern {
        void onToggleChange(ToggleState state);
    }

}

 Activity中使用

package com.example.tbtn;

import com.example.tbtn.view.ToggleButton;
import com.example.tbtn.view.ToggleButton.OnToggleChangeLisern;
import com.example.tbtn.view.ToggleButton.ToggleState;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;


public class MainActivity extends Activity {
    private ToggleButton tBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tBtn = (ToggleButton) findViewById(R.id.tbtn);
        tBtn.setSwitchBackgroundResource(R.drawable.togglebtn);
        tBtn.setSlideBackgroundResouce(R.drawable.ic_launcher);
        tBtn.setSlideStare(ToggleState.Open);
        tBtn.setOnToggleChangeLisern(new OnToggleChangeLisern() {
            
            @Override
            public void onToggleChange(ToggleState state) {
                if(state==ToggleState.Open){
                    Toast.makeText(MainActivity.this,"打开", 0).show();
                }else{
                    Toast.makeText(MainActivity.this,"关闭", 0).show();
                }
                
            }
        });
    }

}

 

posted @ 2016-02-01 16:16  aaddrrooiidd  阅读(300)  评论(0编辑  收藏  举报