Canvas的实际使用--自定义搜索效果
来源:互联网 发布:韩国抄袭知乎 编辑:程序博客网 时间:2024/05/20 09:26
上面效果是使用Canvas实现的一个搜索效果,涉及到三个部分的绘制:搜索放大镜的圆、放大镜的手柄、线条,根据属性动画执行的多少及移动的距离进行绘制;
1、extends View 并重写onDraw方法
public class MySearchView extends View{ private Paint mPaint; private BaseController mController; public MySearchView(Context context) { this(context,null); } public MySearchView(Context context, AttributeSet attrs) { this(context, attrs,0); } public MySearchView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint=new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStrokeWidth(5); mPaint.setColor(Color.RED); } public void setController(BaseController controller){ this.mController=controller; mController.setSearchView(this); invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mController.draw(canvas,mPaint); } /** * 开启动画 */ public void startAnimation(){ if(mController!=null){ mController.startAnim(); } } /** * 重置动画 */ public void resetAnimation(){ if(mController!=null){ mController.resetAnim(); } }}
在这里类里面会发现只有一个Paint画笔,开启动画,重置动画的方法,正真onDraw绘制的时候是在BaseController里面进行绘制;
public abstract class BaseController { private MySearchView mySearchView; public static final int STATE_ANIM_NONE = 0; public static final int STATE_ANIM_START = 1; public static final int STATE_ANIM_STOP = 2; public static final int DEFAULT_ANIM_TIME = 5000; public static final float DEFAULT_ANIM_STARTF = 0; public static final float DEFAULT_ANIM_ENDF = 1; public int mState = STATE_ANIM_NONE; private AnimatorListenter animatorListenter; /** * 开始动画 */ public void startAnim(){ } /** * 重置动画 */ public void resetAnim(){ } /** * 绘制 * @param canvas * @param paint */ public abstract void draw(Canvas canvas, Paint paint); public void setSearchView(MySearchView mySearchView){ this.mySearchView=mySearchView; } /** * 获取宽度 * @return 返回MySearchView的宽度 */ public int getWidth(){ return mySearchView.getWidth(); } /** * 获取高度 * @return 返回MySearchView的高度 */ public int getHeight(){ return mySearchView.getHeight(); } public float mpro=-1; /** * 设置动画效果 * @return 设置好的ValueAnimator */ public ValueAnimator startViewAnimation(){ ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); valueAnimator.setDuration(800l); //设置动画插值器 valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mpro = (float) animation.getAnimatedValue(); mySearchView.invalidate(); } }); //监听动画完成 valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); if(animatorListenter!=null){ animatorListenter.animatorListenter(); } } }); valueAnimator.start(); mpro=0; return valueAnimator; } public void addAnimatorFishListener(AnimatorListenter listenter){ this.animatorListenter=listenter; }}
这里的BaseController是一个抽象类,onDraw方法也是抽象方法,子类必须要实现,这里主要对ValueAnimator进行设置已经监听回调;真正的绘制动作还是在BaseController子类中完成;
public class SearchController extends BaseController{ private RectF mRectF; private String mColor="#4CAF50"; private int cx,cy,cr; private int j=15; public SearchController(){ mRectF=new RectF(); } @Override public void draw(Canvas canvas, Paint paint) { canvas.drawColor(Color.parseColor(mColor)); switch (mState){ case STATE_ANIM_NONE: drawNormalView(canvas,paint); break; case STATE_ANIM_START: drawStartAnimView(canvas,paint); break; case STATE_ANIM_STOP: drawStopAnimView(canvas,paint); break; } } /** * 绘制停止动画view * @param canvas * @param paint */ private void drawStopAnimView(Canvas canvas, Paint paint) { } /** * 绘制开启动画的view * @param canvas * @param paint */ private void drawStartAnimView(Canvas canvas, Paint paint) { canvas.save(); if(mpro<=0.5f){ /** * -360 ~ 0 需要变换的范围 * 0 ~ 0.5 mpro实际的变化范围 * 转换公式:360*(mpro*2-1), */ //绘制圆和把手 canvas.drawArc( mRectF, 45, 360*(mpro*2-1), false, paint ); canvas.drawLine( mRectF.right - j, mRectF.bottom - j, mRectF.right+cr-j, mRectF.bottom+cr-j, paint ); }else{ /** * 0 ~ 1 需要变换的范围 * 0.5 ~ 1 mpro实际的变化范围 * 转换公式:(mpro*2-1), */ //绘制把手 canvas.drawLine( mRectF.right - j + cr*(mpro*2-1), mRectF.bottom - j + cr*(mpro*2-1), mRectF.right - j + cr, mRectF.bottom+cr-j, paint); } //绘制下面的横线 canvas.drawLine( (mRectF.right - j + cr)*(1-mpro*0.8f), mRectF.bottom+cr-j, mRectF.right - j + cr, mRectF.bottom+cr-j, paint); canvas.restore(); mRectF.left = cx -cr + mpro*250; mRectF.right = cx + cr +mpro*250; mRectF.top = cy - cr; mRectF.bottom = cy + cr; } /** * 绘制普通view * @param canvas * @param paint */ private void drawNormalView(Canvas canvas, Paint paint) { cr=getWidth()/20; cx=getWidth()/2; cy=getHeight()/2; mRectF.left=cx-cr; mRectF.right=cx+cr; mRectF.top=cy-cr; mRectF.bottom=cy+cr; //保存画布 canvas.save(); //重置画笔 paint.reset(); //设置抗锯齿 paint.setAntiAlias(true); paint.setColor(Color.RED); paint.setStrokeWidth(5); paint.setStyle(Paint.Style.STROKE); //将画布选择45度 canvas.rotate(45,cx,cy); //绘制线条 canvas.drawLine(cx+cr,cy,cx+cr*2,cy,paint); canvas.drawArc( mRectF, 0, 360, false, paint ); canvas.restore(); } @Override public void startAnim() { super.startAnim(); mState = STATE_ANIM_START; startViewAnimation(); } @Override public void resetAnim() { super.resetAnim(); mState = STATE_ANIM_STOP; startViewAnimation(); } @Override public void addAnimatorFishListener(AnimatorListenter listenter) { super.addAnimatorFishListener(listenter); }}
SearchController是BaseController的子类,在SearchController的onDraw方法中进行绘制,如果需要不同的效果,直接写一个新的类 extends BaseController,调用就可以了,并不需要去修改SearchController里面的代码,具体的代码中都有注释;
2、使用
public class MainActivity extends AppCompatActivity { private MySearchView sv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sv = (MySearchView) findViewById(R.id.sv); SearchController searchController=new SearchController(); sv.setController(searchController); searchController.addAnimatorFishListener(new AnimatorListenter() { @Override public void animatorListenter() { Toast.makeText(MainActivity.this,"执行完毕",Toast.LENGTH_LONG).show(); } }); } public void start(View v){ sv.startAnimation(); }}
找到MySearchView,调用它的setController方法,将创建好的SearchController对象传入就可以了。
源码地址:
http://download.csdn.net/download/wangwo1991/9974198
阅读全文
0 0
- Canvas的实际使用--自定义搜索效果
- Canvas的实际使用
- Android自定义View使用canvas实现轮播图效果
- 使用canvas做出红包照片的效果
- Android自定义搜索效果的实现
- 【Android】自定义View之Canvas的使用
- Android自定义View,paint+canvas的使用
- Android PorterDuff.Mode与Canvas实际使用
- canvas 的粒子效果
- 【html5 canvas】使用Canvas做出橡皮擦效果
- 使用 Canvas 的Xfermode 实现 ImageView 圆形图片的实际步骤
- 图像搜索的实际应用
- 窗口风格的实际效果
- 窗口风格的实际效果
- 窗口风格的实际效果
- 做出一个SwitchButton的效果,并详细学习一下onDraw(Canvas canvas)方法的使用
- Android自定义View---前奏篇(Paint和Canvas的使用)
- 自定义控件玩套路以及canvas StaticLayout的使用
- 电商营销方式抢购,秒杀Redis原子出队列lpop方法作为剩余库存判断条件的实现方式(2)
- 爬虫之爬取微博
- 图论-存储&最短路
- 3226: [Sdoi2008]校门外的区间
- Maven modules 生产环境 开发环境搭建
- Canvas的实际使用--自定义搜索效果
- 电商营销方式抢购,秒杀Redis原子减decr方法作为剩余库存判断条件的实现方式(1)
- servlet 的接口简单应用和filter过滤 用户未登录
- 电商营销方式抢购,秒杀Redis原子减decr方法作为剩余库存判断条件的实现方式(1)
- permutohedral lattice
- 二叉平衡树-AVL
- Search in Rotated Sorted Array
- 9月11日笔记(Servlet,Ajax,Filter)
- ubuntu修改环境变量