android攻城狮之自定义控件(二) 滑动开关

android自定义控件是作为一名优秀的android攻城狮必不可少的技能,为了进一步认识自定义控件,层次递进的学习,今天给大家以案例(滑动开关案例)的形式说明自定义控件的使用(案例UI图片取自网上图库,在此致谢图片分享者)。

首先晒上案例效果图


1.回顾一下自定义控件是什么?

1.自定义控件实现很简单,我们可以将他分为两大类:

(1)通过组合原生的控件,加上一些特殊动画的组合来达到自定义的需求

(2)定义一个类继承View,或者还可以继承ViewGroup

2.View和ViewGroup的区别:

ViewGroup里面可以添加自己的孩子(LinearLayout、FrameLayout、TableLayout、RelativeLayout、AbsoluteLayout这几大布局都继承ViewGroup)
android攻城狮之自定义控件(二) 滑动开关_第1张图片


2.滑动开关案例下面将以代码+注释的形式详解,直接看代码感觉更爽一些

1.定义一个类ToggleView,继承View

package com.example.toggleview;

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

	private Bitmap switch_background;
	private Bitmap slide_button_background;
	
	private boolean toggleCurrentState = false; //当前开关的状态
	
	private boolean isSliding = false; //默认不滑动
	private int downX;

	private OnToggleStateChangeListener mToggleStateChangeListener;
	
	//直接new 初始化的时候调用
	public ToggleView(Context context) {
		super(context);
	}

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

	//在布局里面使用的时候调用
	public ToggleView(Context context, AttributeSet attrs) {
		super(context, attrs);
		
		String namespace = "http://schemas.android.com/apk/res/com.example.toggleview";
		int switchBackground = attrs.getAttributeResourceValue(namespace, "switchBackground", -1);
		int slidingBackground = attrs.getAttributeResourceValue(namespace, "slidingBackground", -1);
		//设置开关的状态
		toggleCurrentState  = attrs.getAttributeBooleanValue(namespace, "toggleState", false);
		
		//设置 开关的背景 
		setToggleBackground(switchBackground);
		
		//设置滑动块的背景 
		setToggleSlidBackGround(slidingBackground);

	}

	//设置开关背景
	public void setToggleBackground(int switchBackground) {
		switch_background = BitmapFactory.decodeResource(getResources(), switchBackground);
	}

	//设置开关的滑动块
	public void setToggleSlidBackGround(int slideButtonBackground) {
		slide_button_background = BitmapFactory.decodeResource(getResources(),slideButtonBackground);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		//测量当前viwe的宽和高 
		setMeasuredDimension(switch_background.getWidth(), switch_background.getHeight());
	}
	
	//绘制内容  被绘制到了当前控件上
	@Override
	protected void onDraw(Canvas canvas) {
		//[1]画开关的背景 
		canvas.drawBitmap(switch_background, 0, 0, null);

		if (isSliding) {
			//[2]根据当前dwonX 画滑动块 
			int left = downX - slide_button_background.getWidth()/2;
			//[2.1]对边界进行处理
			int rightAlgin = switch_background.getWidth() - slide_button_background.getWidth();
			if (left<0) {
				left = 0;
			}else if (left > rightAlgin) {
				left = rightAlgin;
			}
			canvas.drawBitmap(slide_button_background, left, 0, null);
		}else {
			//不是滑动状态  根据 当前开关的状态 画 

			//[2]画滑动块背景
			if (toggleCurrentState) {
				//开关打开状态
				int left = switch_background.getWidth() - slide_button_background.getWidth();
				
				canvas.drawBitmap(slide_button_background, left, 0,null);
			}else {
				//开关关闭
				canvas.drawBitmap(slide_button_background, 0, 0,null);
				
			}
		}
		super.onDraw(canvas);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int action = event.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:  //按下
			//[1]获取手指触摸的位置
			isSliding = true;
			
			downX = (int) event.getX(); 
			break;

		case MotionEvent.ACTION_MOVE:  //移动 
			downX = (int) event.getX();
			break;
			
		case MotionEvent.ACTION_UP:    //抬起
			downX = (int) event.getX();
			//[0]手指抬起 处于不是滑动状态
			isSliding = false;
			
			//[1]获取开关背景一半  
			int center = switch_background.getWidth()/2;
			
			boolean state =  downX > center;
			
			
			//[1.1]开关的状态没有发生改变的时候 不触发我们写回调事件
			
			if (toggleCurrentState!=state) {
				toggleCurrentState = state;
				//[2]触发我们定义的回调方法
				if (mToggleStateChangeListener!=null) {
					
					mToggleStateChangeListener.onToggleState(toggleCurrentState);
					
				}
			}
			break;
		}
		//当前view 会进行重绘  会调用onDraw
		invalidate();
		
		//让当前控件处理事件
		return true;
	}

	//设置开关的状态
	public void setToggleState(boolean b) {
		toggleCurrentState = b;
	}
	
	//设置开关改变的监听 
	public void setOnToggleStateLinstener(OnToggleStateChangeListener listen){
		mToggleStateChangeListener = listen;
	}
	
	//开关滑动接口
	public interface OnToggleStateChangeListener{
		
		public void onToggleState(boolean state);
	}

}

2.在布局文件中将其定义出来

res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:example="http://schemas.android.com/apk/res/com.example.toggleview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" >

    <com.example.toggleview.ToggleView
        android:id="@+id/toggleView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        example:slidingBackground="@drawable/slide_button_background"
        example:switchBackground="@drawable/switch_background"
        example:toggleState="true" />

</RelativeLayout>

res/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
      <declare-styleable name="toggleview">
            <attr name="switchBackground" format="reference" />
            <attr name="slidingBackground" format="reference" />
            <attr name="toggleState" format="boolean" />
      </declare-styleable>
</resources>


3.在MainActivity中找到我们自己定义的开关控件设置相关属性和监听事件

package com.example.toggleview;

import com.example.toggleview.ToggleView.OnToggleStateChangeListener;

import android.os.Bundle;
import android.app.Activity;
import android.widget.Toast;

public class MainActivity extends Activity {

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

		//[1]找到我们自己定义的开关控件 
		ToggleView toggleView = (ToggleView) findViewById(R.id.toggleView1);
		//[2]设置开关的背景 
//		toggleView.setToggleBackground(R.drawable.switch_background);
		//[3]设置开关的滑动块 
//		toggleView.setToggleSlidBackGround(R.drawable.slide_button_background);
		//[4]设置开关的状态 
//		toggleView.setToggleState(false);
		
		//[5]设置一个开关状态的监听 
		toggleView.setOnToggleStateLinstener(new OnToggleStateChangeListener() {
			
			@Override
			public void onToggleState(boolean state) {
			     
				 if (state) {
					Toast.makeText(getApplicationContext(), "开", 0).show();
					
					//TODO 
					
				}else{
					Toast.makeText(getApplicationContext(), "关", 0).show();
				}
			}
		});
		
	}
	
}

案例到这里就基本上大功告成了

3.代码托管

托管地址:http://download.csdn.net/detail/smartbetter/9453078 点击下载

你可能感兴趣的:(android自定义控件,滑动开关案例)