原文地址:http://blog.csdn.net/swust_chenpeng/article/details/19967501


前几天在看蘑菇街上有个开关按钮:

就在想是怎样实现的,于是反编译了它的源码,但是这时得到了下面的几张图片:

图片对应的名称:

无色长条:switch_frame;

白色圆点:switch_btn_pressed;
左白右红的长条:switch_bottom;
黑色长条:switch_mask.

那我们就用这几张图片来实现类似的效果吧。

代码:

SwitchButton类:

packagecom.example.switchbutton;importandroid.content.Context;importandroid.graphics.Bitmap;importandroid.graphics.BitmapFactory;importandroid.graphics.Canvas;importandroid.graphics.Paint;importandroid.graphics.PorterDuff.Mode;importandroid.graphics.PorterDuffXfermode;importandroid.graphics.Rect;importandroid.graphics.RectF;importandroid.util.AttributeSet;importandroid.view.MotionEvent;importandroid.view.View;publicclassSwitchButtonextendsViewimplementsandroid.view.View.OnClickListener{privateBitmapmSwitchBottom,mSwitchThumb,mSwitchFrame,mSwitchMask;privatefloatmCurrentX=0;privatebooleanmSwitchOn=true;//开关默认是开着的privateintmMoveLength;//最大移动距离privatefloatmLastX=0;//第一次按下的有效区域privateRectmDest=null;//绘制的目标区域大小privateRectmSrc=null;//截取源图片的大小privateintmDeltX=0;//移动的偏移量privatePaintmPaint=null;privateOnChangeListenermListener=null;privatebooleanmFlag=false;publicSwitchButton(Contextcontext){this(context,null);//TODOAuto-generatedconstructorstub}publicSwitchButton(Contextcontext,AttributeSetattrs){this(context,attrs,0);//TODOAuto-generatedconstructorstub}publicSwitchButton(Contextcontext,AttributeSetattrs,intdefStyle){super(context,attrs,defStyle);//TODOAuto-generatedconstructorstubinit();}/***初始化相关资源*/publicvoidinit(){mSwitchBottom=BitmapFactory.decodeResource(getResources(),R.drawable.switch_bottom);mSwitchThumb=BitmapFactory.decodeResource(getResources(),R.drawable.switch_btn_pressed);mSwitchFrame=BitmapFactory.decodeResource(getResources(),R.drawable.switch_frame);mSwitchMask=BitmapFactory.decodeResource(getResources(),R.drawable.switch_mask);setOnClickListener(this);setOnTouchListener(newOnTouchListener(){@OverridepublicbooleanonTouch(Viewv,MotionEventevent){//TODOAuto-generatedmethodstubreturnfalse;}});mMoveLength=mSwitchBottom.getWidth()-mSwitchFrame.getWidth();mDest=newRect(0,0,mSwitchFrame.getWidth(),mSwitchFrame.getHeight());mSrc=newRect();mPaint=newPaint();mPaint.setAntiAlias(true);mPaint.setAlpha(255);mPaint.setXfermode(newPorterDuffXfermode(Mode.DST_IN));}@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){//TODOAuto-generatedmethodstubsetMeasuredDimension(mSwitchFrame.getWidth(),mSwitchFrame.getHeight());}@OverrideprotectedvoidonDraw(Canvascanvas){//TODOAuto-generatedmethodstubsuper.onDraw(canvas);if(mDeltX>0||mDeltX==0&&!mSwitchOn){if(mSrc!=null){mSrc.set(mMoveLength-mDeltX,0,mSwitchBottom.getWidth()-mDeltX,mSwitchFrame.getHeight());}}elseif(mDeltX<0||mDeltX==0&&mSwitchOn){if(mSrc!=null){mSrc.set(-mDeltX,0,mSwitchFrame.getWidth()-mDeltX,mSwitchFrame.getHeight());}}//这儿是离屏缓冲,自己感觉类似双缓冲机制吧intcount=canvas.saveLayer(newRectF(mDest),null,Canvas.MATRIX_SAVE_FLAG|Canvas.CLIP_SAVE_FLAG|Canvas.HAS_ALPHA_LAYER_SAVE_FLAG|Canvas.FULL_COLOR_LAYER_SAVE_FLAG|Canvas.CLIP_TO_LAYER_SAVE_FLAG);canvas.drawBitmap(mSwitchBottom,mSrc,mDest,null);canvas.drawBitmap(mSwitchThumb,mSrc,mDest,null);canvas.drawBitmap(mSwitchFrame,0,0,null);canvas.drawBitmap(mSwitchMask,0,0,mPaint);canvas.restoreToCount(count);}@OverridepublicbooleanonTouchEvent(MotionEventevent){//TODOAuto-generatedmethodstubswitch(event.getAction()){caseMotionEvent.ACTION_DOWN:mLastX=event.getX();break;caseMotionEvent.ACTION_MOVE:mCurrentX=event.getX();mDeltX=(int)(mCurrentX-mLastX);//如果开关关着向左滑动,或者开关开着向右滑动(这时候是不需要处理的)if((mSwitchOn&&mDeltX>0)||(!mSwitchOn&&mDeltX<0)){mFlag=true;mDeltX=0;}if(Math.abs(mDeltX)>mMoveLength){mDeltX=mDeltX>0?mMoveLength:-mMoveLength;}invalidate();returntrue;caseMotionEvent.ACTION_UP:if(Math.abs(mDeltX)>0&&Math.abs(mDeltX)<mMoveLength/2){mDeltX=0;invalidate();returntrue;}elseif(Math.abs(mDeltX)>mMoveLength/2&&Math.abs(mDeltX)<=mMoveLength){mDeltX=mDeltX>0?mMoveLength:-mMoveLength;mSwitchOn=!mSwitchOn;if(mListener!=null){mListener.onChange(this,mSwitchOn);}invalidate();mDeltX=0;returntrue;}elseif(mDeltX==0&&mFlag){//这时候得到的是不需要进行处理的,因为已经move过了mDeltX=0;mFlag=false;returntrue;}returnsuper.onTouchEvent(event);default:break;}invalidate();returnsuper.onTouchEvent(event);}publicvoidsetOnChangeListener(OnChangeListenerlistener){mListener=listener;}publicinterfaceOnChangeListener{publicvoidonChange(SwitchButtonsb,booleanstate);}@OverridepublicvoidonClick(Viewv){//TODOAuto-generatedmethodstubmDeltX=mSwitchOn?mMoveLength:-mMoveLength;mSwitchOn=!mSwitchOn;if(mListener!=null){mListener.onChange(this,mSwitchOn);}invalidate();mDeltX=0;}

MainActivity:

packagecom.example.switchbutton;importcom.example.switchbutton.SwitchButton.OnChangeListener;importandroid.app.Activity;importandroid.os.Bundle;importandroid.util.Log;importandroid.view.Menu;importandroid.widget.Toast;publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);SwitchButtonsb=(SwitchButton)findViewById(R.id.wiperSwitch1);sb.setOnChangeListener(newOnChangeListener(){@OverridepublicvoidonChange(SwitchButtonsb,booleanstate){//TODOAuto-generatedmethodstubLog.d("switchButton",state?"开":"关");Toast.makeText(MainActivity.this,state?"开":"关",Toast.LENGTH_SHORT).show();}});}@OverridepublicbooleanonCreateOptionsMenu(Menumenu){//Inflatethemenu;thisaddsitemstotheactionbarifitispresent.getMenuInflater().inflate(R.menu.main,menu);returntrue;}}

activity_main.xml:

<LinearLayoutxmlns: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:orientation="vertical"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"><ImageViewandroid:id="@+id/imageView"android:layout_width="wrap_content"android:layout_height="wrap_content"/><com.example.switchbutton.SwitchButtonandroid:id="@+id/wiperSwitch1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="100dip"/></LinearLayout>
主要的代码在switchbutton类中,代码有什么不足还希望大家多提提意见,自己很少写。


参考:http://stackoverflow.com/questions/11838022/how-to-paint-with-alpha

http://blog.csdn.net/zenip/article/details/8766263


PS:以下为自己补充内容,如果想自己手动设置打开或者关闭状态,可以在SwitchButton中加上以下代码,调用即可。

publicvoidsetChecked(booleanchecked){mSwitchOn=checked;invalidate();}


更多相关文章

  1. Android(安卓)8.1隐藏状态栏图标的实例代码
  2. android内存泄露优化总结
  3. android 通知播放系统声音
  4. Android中ContentProvider的工作过程
  5. Android(安卓)代码中设置EditText的hint字体大小
  6. Android(安卓)状态栏下拉列表添加自定义item开关
  7. Android(安卓)Studio 构建变体(Build Variant)
  8. 免费Android客户端静态代码安全分析工具—Dexter
  9. Android(安卓)Studio开发界面自定义,更有利于开发

随机推荐

  1. Android上下文服务管理查询过程
  2. Android 警告提示:Activity has leaked wi
  3. Android之自定义ContentProvider详解
  4. android,java实现NanoHTTPD 轻量级 服务器
  5. Android 经典的魔塔游戏源码
  6. Google收购Motorola移动
  7. Android网络开发技术实战详解
  8. Android版本的RSA非对称加密实现
  9. 目录
  10. 解决 duplicate entry: com/android/voll