class BallView extends View { private Paint paint; private Bitmap mSwitchBackground; private Bitmap mSwitchButton; private int mBackgroundWidth; private int mButtonWidth; private int downX; private int downY; private int moveX; private int moveY; private long downtime; private int buttonX; private boolean on_off = false; private int mBackgroundHeight; private int mMaxX; private int buttonXhalf; private TypedArray mTypedArray; public BallView(Context context) { this(context,null); } public BallView(Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); } public BallView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); intiview(); mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.My_view); } private void intiview() { paint = new Paint();//创建画笔 //用bitmap引入滑动按钮背景图 mSwitchBackground = BitmapFactory.decodeResource(getResources(), R.drawable.switch_backgound); //用bitmap引入滑动按钮 mSwitchButton = BitmapFactory.decodeResource(getResources(), R.drawable.switch_button); //获取背景图的宽高 mBackgroundHeight = mSwitchBackground.getHeight(); mBackgroundWidth = mSwitchBackground.getWidth(); //获取滑动按钮的宽 mButtonWidth = mSwitchButton.getWidth(); //滑动按钮滑动的宽度 mMaxX = mBackgroundWidth - mButtonWidth; //粘性判断值 buttonXhalf = mMaxX / 2; //触摸事件监听 setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN://手指按下 //获取手指按下的(X,Y)坐标 downX=(int)getX(); downY=(int)getY(); //手指移动的距离坐标为0 moveX=0; moveY=0; //获取手指按下的时间 downtime=System.currentTimeMillis(); break; case MotionEvent.ACTION_MOVE://手指移动 //移动的距离等于移动时的坐标和按下时的坐标差,取绝对值 moveX+=Math.abs(getX()-downX); moveY+=Math.abs(getY()-downY); //实时更新坐标 downX=(int) event.getX(); downY=(int)event.getY(); //按钮跟着手指实时移动的距离 buttonX=(int) getX()+downX; break; case MotionEvent.ACTION_UP://手指抬起 //获取手指抬起的时间 long movetime=System.currentTimeMillis()-mBackgroundWidth; //判断点击与滑动事件,手指按下与抬起的时间过短并且移动的距离过小判断为点击事件,否为触摸事件 if (movetime>200&&(moveX>20||moveY>20)){ //此处判断为滑动事件,不做操作,break之后调用flushviewbound();方法 }else { //判断为点击事件,状态判断,滑动按钮移动 if (on_off){ on_off=false; buttonX=0; }else{ on_off=true; buttonX=mMaxX; } invalidate(); } //粘性判断 if (buttonX>0&&buttonX<mMaxX){ //是否中间坐标判断,改变状态值 if (buttonX<buttonXhalf){ on_off=false; buttonX=0; }else { on_off=true; buttonX=mMaxX; } } break; } //调用此方法 flushviewbound(); //消费此次触摸事件 return true; } }); } private void flushviewbound() { //滑动越界判断 if (buttonX<0){ //最小滑到坐标为零 buttonX=0; }else if (buttonX>mMaxX){ //最大坐标宽度 buttonX=mMaxX; } //接口回调 if (mOnNumberChangerListener !=null){ mOnNumberChangerListener.OnNumberChanger(!on_off); } //调用ondraw(); invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); /* * 背景的寬高 * */ setMeasuredDimension(mBackgroundWidth,mBackgroundHeight); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画笔颜色 paint.setColor(Color.RED); //消除锯齿 paint.setAntiAlias(true); //画布背景,滑动按钮背景图 canvas.drawBitmap(mSwitchBackground,0,0,paint); //添加按钮图片 canvas.drawBitmap(mSwitchButton,buttonX,0,paint); } //接口回调 public interface OnNumberChangerListener{ void OnNumberChanger(boolean value); } //定义接口对象 private OnNumberChangerListener mOnNumberChangerListener; //设置方法接收外界传来的接口对象方法 public void setOnNumberChangerListener(OnNumberChangerListener onNumberChangerListener){ mOnNumberChangerListener =onNumberChangerListener; } }
MainLayout界面
mContainer = (RelativeLayout) findViewById(R.id.relativeLayout); mBallView = new BallView(this); mContainer.addView(mBallView); mBallView.setOnNumberChangerListener(new BallView.OnNumberChangerListener() { @Override public void OnNumberChanger(boolean value) { Toast.makeText(BallActivity.this,""+value,Toast.LENGTH_SHORT).show(); } });
layout布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/relativeLayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:ignore="ResAuto"> <com.example.admin.ballveiwdemo.BallView android:id="@+id/ball" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>