天天看点

android_94_自定义ToggleButton

效果:

android_94_自定义ToggleButton

枚举:

android_94_自定义ToggleButton

自定义View与ViewGroup的区别

android_94_自定义ToggleButton

示意图:

getX();得到的是 View内部的坐标系;原点在View内的左上角

注意:文字是特殊情况,

getRawX();得到的是 屏幕坐标系:原点在屏幕的左上角

android_94_自定义ToggleButton

布局文件:

<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.sg31.sgtogglebutton.MainActivity" >

    <com.sg31.sgtogglebutton.SGToogleButton
        android:id="@+id/toggleBtn"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        />

</RelativeLayout>
           

主控制器:

package com.sg31.sgtogglebutton;

import com.sg31.sgtogglebutton.SGToogleButton.OnToggleStateChangeLisener;
import com.sg31.sgtogglebutton.SGToogleButton.ToggleState;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;


public class MainActivity extends ActionBarActivity {

    private SGToogleButton toggleBtn;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        initToggleButton();
        
    }

	private void initToggleButton() {
		toggleBtn = (SGToogleButton)findViewById(R.id.toggleBtn);
		toggleBtn.setBgImgResource(R.drawable.onimg2);
		toggleBtn.setSlideImgResource(R.drawable.slideimg);
		toggleBtn.setToggleState(ToggleState.Closed);
		toggleBtn.setOnToggleStateChangeLisener(new OnToggleStateChangeLisener() {
			
			@Override
			public void onToggleStateChanged(ToggleState state) {
				// TODO Auto-generated method stub
				System.out.println(state==ToggleState.Open?"open":"closed");
			}
		});
	}
}
           

自定义ToggleButton

package com.sg31.sgtogglebutton;


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 SGToogleButton extends View {

	// 状态枚举
	public enum ToggleState{
		Open,Closed
	}
	
	// 代理
	private OnToggleStateChangeLisener lisener;
	private ToggleState toggleSate;
	private Bitmap slideImg;
	private Bitmap bgImg;
	private int fingerX;
	private boolean isSliding;
	public interface OnToggleStateChangeLisener{
		void onToggleStateChanged(ToggleState state);
	}
	public void setOnToggleStateChangeLisener(OnToggleStateChangeLisener lisener) {
		this.lisener = lisener;
	}
	
	// 构造方法
	public SGToogleButton(Context context) {
		super(context);
	}
	public SGToogleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	
	// 供外界调用
	public void setBgImgResource(int imgID) {
		bgImg = BitmapFactory.decodeResource(getResources(), imgID);
	}
	// 供外界调用
	public void setSlideImgResource(int imgID) {
		slideImg = BitmapFactory.decodeResource(getResources(), imgID);
	}
	// 供外界调用
	public void setToggleState(ToggleState state) {
		toggleSate = state;
	}
	
	
	// 自定义View的第2步,onMeasure方法
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		setMeasuredDimension(bgImg.getWidth(), bgImg.getHeight());
	}
	
	// 自定义View的第3步,onDraw方法
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// 1.绘制背景图 在 View中的位置 (画图可以不用Paint)
		canvas.drawBitmap(bgImg, 0, 0, null);
		
		// 2根据状态及变量,进行绘制滑块
		if (isSliding) {
			int slideImgX = fingerX - slideImg.getWidth()/2;
			if (slideImgX < 0) {
				// 防止左边越界
				slideImgX = 0;
			}
			if (slideImgX > bgImg.getWidth() - slideImg.getWidth()) {
				// 防止右边越界
				slideImgX = bgImg.getWidth() - slideImg.getWidth();
			}
			canvas.drawBitmap(slideImg, slideImgX, 0, null);
		} else {
			// 抬起时:要么关,要么开
			if (toggleSate == ToggleState.Open) {
				// 背景图片: 左是开, 右是关
				canvas.drawBitmap(slideImg, 0, 0, null);				
			} else {
				canvas.drawBitmap(slideImg, bgImg.getWidth() - slideImg.getWidth(), 0, null);
			}
			
		}
		
		
	}
	
	// 自定义View的第4步,onTouchEvent方法
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		System.out.println("sg__touch");
		// 得到按下点,在View自己内部的坐标(相对于View自身的左上角)
		fingerX = (int)event.getX();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
		{
			// 只要按下,就标记为滑动
			isSliding = true;
		}
			break;
		case MotionEvent.ACTION_MOVE:
		{
			
		}
			break;
		case MotionEvent.ACTION_UP:
		{
			isSliding = false;
			int toggleCenterX = bgImg.getWidth()/2;
			if (fingerX > toggleCenterX) {
				// 如果用户手指按下的地方,在view的中心线之后面,则表示 滑块从左往右,从开到闭
				// 只有不是闭的时候,才要关闭
				if (toggleSate != ToggleState.Closed) {
					toggleSate = ToggleState.Closed;
					// 通知
					if (lisener != null) {
						lisener.onToggleStateChanged(toggleSate);
					}
				}
			} else {
				// 如果用户手指按下的地方,在view的中心线之前面,则表示 滑块从右往左,从闭到开
				// 只有不是开的时候,才要打开
				if (toggleSate != ToggleState.Open) {
					toggleSate = ToggleState.Open;
					// 通知
					if (lisener != null) {
						lisener.onToggleStateChanged(toggleSate);
					}
				}
			}
		}
			break;
			

		default:
			break;
		}
		// 非常重要的方法,不然没法更新界面
		invalidate();
		// 自己要处理,所以返回true
		return true;
	}


	

}