Android自定义View示例(二)—滑动开关

MainActivity如下:

package cc.testview3;

import cc.testview3.SwitchView.SwitchChangedListener;
import android.os.Bundle;
import android.widget.Toast;
import android.app.Activity;
/**
 * Demo描述:
 * 自定义View实现滑动开关
 *
 * 测试设备:
 * 分辨率为480x854
 */
public class MainActivity extends Activity {
    private SwitchView mSwitchView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		init();
	}
    private void init(){
    	mSwitchView=(SwitchView) findViewById(R.id.switchView);
    	mSwitchView.initSwitchStatus(true);
    	mSwitchView.setOnSwitchChangedListener(new SwitchChangedListenerImpl());
    }

    private class SwitchChangedListenerImpl implements SwitchChangedListener{
		@Override
		public void OnChanged(boolean currentStatus) {
			Toast.makeText(MainActivity.this, "currentIsOff?-->"+currentStatus, Toast.LENGTH_SHORT).show();
		}

    }

}

SwitchView如下:

package cc.testview3;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class SwitchView extends View  {
	private Bitmap mOnBitmap;
	private Bitmap mOffBitmap;
	private Bitmap mDotBitmap;
	private float currentX;
	private boolean currentIsSlipping=false;
	private boolean currentIsOff;
	private SwitchChangedListener mSwitchChangedListener;
    private int dotWidth;
    private int switchWidth;
	public SwitchView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initSwitchView();
	}

	public SwitchView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initSwitchView();
	}

	public SwitchView(Context context) {
		super(context);
		initSwitchView();
	}

	private void initSwitchView(){
		mOnBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.on);
		mOffBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.off);
		mDotBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.dot);
		dotWidth=mDotBitmap.getWidth();
		switchWidth=mOnBitmap.getWidth();
		this.setOnTouchListener(new TouchListenerImpl());
	}

	public void initSwitchStatus(boolean isOff){
		if (isOff) {
			currentX=switchWidth;
		} else {
			currentX=0;
		}
		currentIsOff=isOff;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,int bottom) {
		super.onLayout(changed, left, top, right, bottom);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		Matrix matrix=new Matrix();
		Paint paint=new Paint();

		//先画出开关的背景(关/开)
		if (currentIsOff) {
			canvas.drawBitmap(mOffBitmap, matrix, paint);
		} else {
			canvas.drawBitmap(mOnBitmap, matrix, paint);
		}

		//再画出滑块
		//1 在滑动中(if),滑块的left就是不断变化的currentX
		//2 手指抬起后(else)停止滑动时.此时的开关应该在左右
		//  其中一侧处于开或者关的状态
		if (currentIsSlipping) {
			canvas.drawBitmap(mDotBitmap, currentX, 17, paint);
		} else {
			if (currentIsOff) {
				canvas.drawBitmap(mDotBitmap, currentX-dotWidth, 17, paint);
			}else{
				canvas.drawBitmap(mDotBitmap, currentX, 17, paint);
			}
		}
	}

	private class TouchListenerImpl implements OnTouchListener{
		@Override
		public boolean onTouch(View v, MotionEvent event) {
			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:

				break;
			case MotionEvent.ACTION_MOVE:
				currentIsSlipping=true;
				currentX = event.getX();
				if (currentX>switchWidth/2) {
					currentIsOff=true;
				}else {
					currentIsOff=false;
				}

				//防止向右边滑动时越界
				if (event.getX()>switchWidth-dotWidth) {
					currentX = switchWidth-dotWidth;
					currentIsOff=true;
				}
				//防止向左边滑动时越界
				if (event.getX()<0) {
					currentX=0;
					currentIsOff=false;
				}
				//重绘!!!
				invalidate();
				break;
			case MotionEvent.ACTION_UP:
				currentIsSlipping=false;
				currentX = event.getX();
				//抬起时若(if)已经超过开关一般的长度,则让其处于关闭的状态
				//否则(else)让其处于打开的状态
				if (currentX >= switchWidth / 2) {
					currentX = switchWidth;
					currentIsOff=true;
				} else {
					currentX = 0;
					currentIsOff=false;
				}
				if (mSwitchChangedListener != null) {
					mSwitchChangedListener.OnChanged(currentIsOff);
				}
				// 重绘!!!
				invalidate();
				break;

			default:
				break;
			}

			return true;
		}

	}

	// 接口
	public interface SwitchChangedListener {
		public void OnChanged(boolean currentIsOff);
	}

	public void setOnSwitchChangedListener(SwitchChangedListener switchChangedListener) {
		this.mSwitchChangedListener = switchChangedListener;
	}

}

main.xml如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <cc.testview3.SwitchView
        android:id="@+id/switchView"
        android:layout_width="wrap_content"
        android:layout_height="60dip"
        android:layout_marginTop="200dip"
        android:layout_marginLeft="30dip"
    />

</RelativeLayout>
时间: 2024-09-20 15:35:07

Android自定义View示例(二)—滑动开关的相关文章

Android自定义View示例(三)—滑动控件

MainActivity如下: package cc.testview4; import cc.testview4.SlideView.SwitchChangedListener; import android.app.Activity; import android.os.Bundle; /** * Demo描述: * 自定义滑动控件 * * 参考资料: * http://blog.csdn.net/lfdfhl/article/details/8195441 * * 备注说明: * 在Cop

Android自定义View示例(四)—带有动画的Dialog

MainActivity如下: package cc.testview1; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 自定义Dialog,在Dialog中有动画(旋转动画或者帧动画)效果 */ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceStat

Android自定义View示例(一)—带有删除按钮的EditText

MainActivity如下: package cc.textview5; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import android.app.Activity;

Android自定义View之酷炫圆环(二)_Android

先看下最终的效果 静态: 动态: 一.开始实现 新建一个DoughnutProgress继承View public class DoughnutProgress extends View { } 先给出一些常量.变量以及公共方法的代码,方便理解后面的代码     private static final int DEFAULT_MIN_WIDTH = 400; //View默认最小宽度 private static final int RED = 230, GREEN = 85, BLUE =

Android自定义View绘制的方法及过程(二)

上一篇<Android 自定义View(一) Paint.Rect.Canvas介绍>讲了最基础的如何自定义一个View,以及View用到的一些工具类.下面讲下View绘制的方法及过程 public class MyView extends View { private String TAG = "--------MyView"; private int width, height; public MyView(Context context, AttributeSet a

android自定义view插入xml

问题描述 android自定义view插入xml 自定义View代码如下.我希望把这个view插入到一个layout的xml的文件中.一直出错,错误类型是error inflating class.应该是这个View出的问题package com.example.browserstation; import java.util.Timer;import java.util.TimerTask; import android.content.Context;import android.graph

组合-android自定义view怎样指定自定义view的布局

问题描述 android自定义view怎样指定自定义view的布局 我有现成的布局xml文件,现在想定义一个组合的自定义view,怎样把这个view的布局指定为一个xml文件 解决方案 LayoutInflater.from(mActivity).inflate(R.layout.mainscreen_title, this, true);这样就行了,this是当前的View,而后面这两个参数是将R.layout.mainscreen_title attachToRoot 也就是以当前这个Vie

android自定义view和自定义layout

问题描述 android自定义view和自定义layout 我自定义了一个view,实现一个图片的移动,然后我想在view添加一个按钮,网上说是要建一个layout,然后再add.求教具体方法啊,能不能不用layout直接用view添加按钮. 解决方案 类似如下 LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); Lin

Android 自定义View是继承view还是viewgroup

问题描述 Android 自定义View是继承view还是viewgroup 我一直对于自定义View一知半解,不知道该怎么去 入手,看到一些自定义的view,一些继承的view,一些是ViewGroup,还有的就是一些自带的控件,怎么去区分我所要的view该继承谁?求郭老师指导一下! 解决方案 看你的具体需求,如果单独一个控件就继承View,如果还要承装其他控件就继承ViewGroup. 解决方案二: Android 自定义View和ViewGroupAndroid 自定义View 和 Vie