自定义控件1_切换按钮

来源:互联网 发布:淘宝讲师爱上黄昏 编辑:程序博客网 时间:2024/06/06 18:55

1.自定义属性values/attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="ToggleView">        <attr name="switch_background" format="reference" />        <attr name="slide_button" format="reference" />        <attr name="switch_state" format="boolean" />    </declare-styleable></resources>

2.view的java文件:

package zdl.switchbutton.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;/** * 自定义开关 * */public class ToggleView extends View {    private Bitmap switchBackgroupBitmap; // 背景图片    private Bitmap slideButtonBitmap; // 滑块图片    private Paint paint; // 画笔    private boolean mSwitchState = false; // 开关状态, 默认false    private float currentX;    /**     * 用于代码创建控件     *     * @param context     */    public ToggleView(Context context) {        super(context);        init();    }    /**     * 用于在xml里使用, 可指定自定义属性     *     * @param context     * @param attrs     */    public ToggleView(Context context, AttributeSet attrs) {        super(context, attrs);        init();        // 获取配置的自定义属性        String namespace = "http://toly.android.com/apk/res/zdl.switchbutton.view.ToggleView";        int switchBackgroundResource = attrs.getAttributeResourceValue(namespace, "switch_background", -1);        int slideButtonResource = attrs.getAttributeResourceValue(namespace, "slide_button", -1);        mSwitchState = attrs.getAttributeBooleanValue(namespace, "switch_state", false);        setSwitchBackgroundResource(switchBackgroundResource);        setSlideButtonResource(slideButtonResource);    }    /**     * 用于在xml里使用, 可指定自定义属性, 如果指定了样式, 则走此构造函数     *F:\Android\SwitchButton\app\src\main\java\zdl\switchbutton\view\ToggleView.java     * zdl.switchbutton.view.ToggleView     * @param context     * @param attrs     * @param defStyle     */    public ToggleView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init();    }    private void init() {        paint = new Paint();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(switchBackgroupBitmap.getWidth(), switchBackgroupBitmap.getHeight());    }    // Canvas 画布, 画板. 在上边绘制的内容都会显示到界面上.    @Override    protected void onDraw(Canvas canvas) {        // 1. 绘制背景        canvas.drawBitmap(switchBackgroupBitmap, 0, 0, paint);        // 2. 绘制滑块        if (isTouchMode) {            // 根据当前用户触摸到的位置画滑块            // 让滑块向左移动自身一半大小的位置            float newLeft = currentX - slideButtonBitmap.getWidth() / 2.0f;            int maxLeft = switchBackgroupBitmap.getWidth() - slideButtonBitmap.getWidth();            // 限定滑块范围            if (newLeft < 0) {                newLeft = 0; // 左边范围            } else if (newLeft > maxLeft) {                newLeft = maxLeft; // 右边范围            }            canvas.drawBitmap(slideButtonBitmap, newLeft, 0, paint);        } else {            // 根据开关状态boolean, 直接设置图片位置            if (mSwitchState) {// 开                int newLeft = switchBackgroupBitmap.getWidth() - slideButtonBitmap.getWidth();                canvas.drawBitmap(slideButtonBitmap, newLeft, 0, paint);            } else {// 关                canvas.drawBitmap(slideButtonBitmap, 0, 0, paint);            }        }    }    boolean isTouchMode = false;    private OnSwitchListener onSwitchListener;    // 重写触摸事件, 响应用户的触摸.    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                isTouchMode = true;                System.out.println("event: ACTION_DOWN: " + event.getX());                currentX = event.getX();                break;            case MotionEvent.ACTION_MOVE:                System.out.println("event: ACTION_MOVE: " + event.getX());                currentX = event.getX();                break;            case MotionEvent.ACTION_UP:                isTouchMode = false;                System.out.println("event: ACTION_UP: " + event.getX());                currentX = event.getX();                float center = switchBackgroupBitmap.getWidth() / 2.0f;                // 根据当前按下的位置, 和控件中心的位置进行比较.                boolean state = currentX > center;                // 如果开关状态变化了, 通知界面. 里边开关状态更新了.                if (state != mSwitchState && onSwitchListener != null) {                    // 把最新的boolean, 状态传出去了                    onSwitchListener.onStateUpdate(state);                }                mSwitchState = state;                break;            default:                break;        }        // 重绘界面        invalidate(); // 会引发onDraw()被调用, 里边的变量会重新生效.界面会更新        return true; // 消费了用户的触摸事件, 才可以收到其他的事件.    }    /**     * 设置背景图     *     * @param switchBackground     */    public void setSwitchBackgroundResource(int switchBackground) {        switchBackgroupBitmap = BitmapFactory.decodeResource(getResources(), switchBackground);    }    /**     * 设置滑块图片资源     *     * @param slideButton     */    public void setSlideButtonResource(int slideButton) {        slideButtonBitmap = BitmapFactory.decodeResource(getResources(), slideButton);    }    /**     * 设置开关状态     */    public void setSwitchState(boolean mSwitchState) {        this.mSwitchState = mSwitchState;    }    public interface OnSwitchListener {        // 状态回调, 把当前状态传出去        void onStateUpdate(boolean state);    }    public void setOnSwitchListener(OnSwitchListener onSwitchListener) {        this.onSwitchListener = onSwitchListener;    }}


3.layout中使用

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:toly="http://toly.android.com/apk/res/zdl.switchbutton.view.ToggleView"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"><zdl.switchbutton.view.ToggleView    android:id="@+id/toggleView"    toly:switch_background="@drawable/switch_background"    toly:slide_button="@drawable/slide_button"    toly:switch_state="false"    android:layout_width="20dp"    android:layout_height="wrap_content"/></LinearLayout>

4.MainActivity.java中:

package zdl.switchbutton;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.Toolbar;import android.view.Menu;import android.view.MenuItem;import android.widget.Toast;import zdl.switchbutton.view.ToggleView;public class MainActivity extends AppCompatActivity {    private Toolbar mTb;    private ToggleView toggleView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        toggleView = (ToggleView) findViewById(R.id.toggleView);        // 设置开关更新监听        toggleView.setOnSwitchListener(new ToggleView.OnSwitchListener(){            @Override            public void onStateUpdate(boolean state) {                Toast.makeText(getApplicationContext(), "state: " + state, 0).show();            }        });}