网上很多自定义View的例子都非常详细讲解了如何写出一个高效实用的自定义View,但是这些由于过于详细,给予一些新手的学习造成了一定的困难,比如说,当初我要学习如何自定义下拉刷新控件,结果,很多大神顺便把一些在我看来 学习自定义View非必要的技术带了进来,如数据结构啊,事件分发机制啊.这些东西不是说不必要,但是他们应该放到别的文章里面,否则对新手来说,让他们去思考这些繁杂的机制,而容易陷入细节不能自拔.这些技术在这篇文章里,他们只是充当辅助的角色,不是我们的主角,我们的主角就是在ondraw里面花时间,然后写出来一个自定义View.这样我们就能更加专注写出一个View,在此基础上,我们再谈扩展和高效.
我们首先观察一下,这个按钮在打开和关闭时的状态,最终可以发现,他只是一些简单的几何组合,所以我们可以通过代码来实现这个效果,
public class SwithcButton extends View { private Paint mPaint; public int state=1; //状态,0位开,1位关.默认为关闭状态 public SwithcButton(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub mPaint=new Paint(); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) { case MotionEvent.ACTION_DOWN: postInvalidate(); isAnim=true; break; default: break; } return true; } boolean isAnim; //是否在播放动画 float scale=0.9f; //画布缩放比例 float offsetX=0; //按钮X轴偏移量 @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub if(state==1){ mPaint.setColor(0xffcccccc); }else{ mPaint.setColor(Color.GREEN); } mPaint.setShadowLayer(0, 0, 0, Color.GRAY); RectF mRectF=new RectF(0, 0, 100,50); canvas.drawRoundRect(mRectF, 50, 50, mPaint); mPaint.setColor(0xffffffff); canvas.save(); canvas.scale(scale, scale, 50, 25); canvas.drawRoundRect(mRectF, 50, 50, mPaint); canvas.restore(); if(state==1 && isAnim){ scale-=0.1; offsetX+=5; invalidate(); if(scale<=0.01){ isAnim=false; state=0; scale=0.01f; offsetX=50; Log.i("test", "open"); } } if(state==0 && isAnim){ scale+=0.1; offsetX-=5; invalidate(); if(scale>=0.9f){ isAnim=false; state=1; scale=0.9f; offsetX=0; Log.i("test", "close"); } } mPaint.setColor(0xffdddddd); mPaint.setShadowLayer(10, 0, 0, Color.GRAY); canvas.save(); canvas.translate(offsetX, 0); canvas.drawRoundRect(new RectF(1,1,48,48), 48, 48,mPaint); canvas.restore(); } }