自定义控件(开关,含自定义卡榫函数)

- Android 的界面绘制流程
     
      测量             摆放        绘制
      measure    ->    layout    ->    draw
            |           |             |
      onMeasure -> onLayout -> onDraw 重写这些方法, 实现自定义控件
      
      都在onResume()之后执行
      
      View流程
      onMeasure() (在这个方法里指定自己的宽高) -> onDraw() (绘制自己的内容)
      
      ViewGroup流程
      onMeasure() (指定自己的宽高, 所有子View的宽高)-> onLayout() (摆放所有子View) -> onDraw() (绘制内容)

 


如果想在自定义空间里刷新图片,就用    invalidate();

1.activity

package com.example.openAndClose;

import com.example.openAndClose.view.MyView;
import com.example.openAndClose.view.MyView.onSwitchChangeListener;

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

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		MyView mv_switch = (MyView) findViewById(R.id.mv_switch);
		mv_switch.setOnSwitchChangeListener(new onSwitchChangeListener() {

			@Override
			public void switchChange(boolean SwitchState) {
				Toast.makeText(getApplicationContext(), "开关" + SwitchState, 0)
						.show();

			}
		});
	}
}

2.布局文件



    

3.属性文件




    
        
        
        
    

4.自定义控件

package com.example.openAndClose.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.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class MyView extends View {

	private int backResourceValue;
	private int srcResourceValue;
	private boolean switchBooleanValue;
	private Bitmap srcBitmap;
	private Bitmap backBitmap;
	private boolean isTouch = false;
	/**
	 * 关键变量,说明开关是不是开启的
	 */
	private boolean isSwitch = false;
	private float PlaceX = 0;
	private onSwitchChangeListener oscl;

	public MyView(Context context) {
		super(context);
	}

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initAttrs(attrs);
	}

	public MyView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initAttrs(attrs);
	}

	/**
	 * 得到属性,并把图片对应的ID转换为bitmap
	 * 
	 * @param attrs
	 *            属性对象
	 */
	private void initAttrs(AttributeSet attrs) {
		// 命名空间
		String spaceName = "http://schemas.android.com/apk/res/com.example.openAndClose";

		// 得到三个属性
		backResourceValue = attrs.getAttributeResourceValue(spaceName, "back",
				-1);
		srcResourceValue = attrs
				.getAttributeResourceValue(spaceName, "src", -1);
		switchBooleanValue = attrs.getAttributeBooleanValue(spaceName,
				"is_switch", false);

		// 把图片创建出来
		backBitmap = BitmapFactory.decodeResource(getResources(),
				backResourceValue);
		srcBitmap = BitmapFactory.decodeResource(getResources(),
				srcResourceValue);
	}

	// 测量
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 通过背景图片的大小,设置控件大小
		setMeasuredDimension(backBitmap.getWidth(), backBitmap.getHeight());
	}

	// 绘图
	@Override
	protected void onDraw(Canvas canvas) {
		// 画笔
		Paint paint = new Paint();
		// 画背景图
		canvas.drawBitmap(backBitmap, 0, 0, paint);

		if (isTouch) {
			// 按下,画图
			// 画开关图片
			float code = PlaceX;

			code = code - srcBitmap.getWidth() / 2;
			// 把坐标容错,不会把开关滑倒控件外
			if (code < 0) {
				code = 0;
			} else if (code > backBitmap.getWidth() - srcBitmap.getWidth()) {
				code = backBitmap.getWidth() - srcBitmap.getWidth();
			}
			// 开始画
			canvas.drawBitmap(srcBitmap, code, 0, paint);
		} else {
			// 抬起,画图

			if (isSwitch) {
				// 如果是开的
				canvas.drawBitmap(srcBitmap,
						backBitmap.getWidth() - srcBitmap.getWidth(), 0, paint);
			} else {
				// 如果是关的
				canvas.drawBitmap(srcBitmap, 0, 0, paint);
			}
		}
		super.onDraw(canvas);
	}

	// 检测手势动作
	@Override
	public boolean onTouchEvent(MotionEvent event) {

		switch (event.getAction()) {

		// 按下
		case MotionEvent.ACTION_DOWN:
			isTouch = true;
			PlaceX = event.getX();
			break;

		// 移动
		case MotionEvent.ACTION_MOVE:
			isTouch = true;
			PlaceX = event.getX();
			break;

		// 抬起
		case MotionEvent.ACTION_UP:
			isTouch = false;
			PlaceX = event.getX();
			// 得到开关中心点的值
			float center = PlaceX;

			// 判定当前是不是开启的,如果开关状态改变,就把通知监听器
			boolean state = center > backBitmap.getWidth() / 2;
			if (state != isSwitch && oscl != null) {
				oscl.switchChange(state);
			}

			isSwitch = state;

			break;

		}
		invalidate();
		return true;
	}

	public interface onSwitchChangeListener {
		public void switchChange(boolean SwitchState);
	}

	public void setOnSwitchChangeListener(onSwitchChangeListener oscl) {
		this.oscl = oscl;
	}

	public boolean isSwitch() {
		return isSwitch;
	}
}

 

你可能感兴趣的:(自定义控件(开关,含自定义卡榫函数))