【开源项目解析】QQ“一键下班”功能实现解析

早在很久很久以前,QQ就实现了“一键下班”功能。何为“一键下班”?当你QQ有信息时,下部会有信息数量提示红点,点击拖动之后,就会出现“一键下班”效果。本文将结合github上关于此功能的一个简单实现,介绍这个功能的基本实现思路。

项目地址

https://github.com/chenupt/BezierDemo

最终实现效果

实现原理解析

我个人感觉,这个效果实现的很漂亮啊!那么咱们就来看看实现原理是什么~

注:下面内容请参照项目源码观看。

其实如果从代码来看,实现的过程并不复杂,重点需要掌握的就是

path的用法贝塞尔曲线的使用。

这个项目的核心就是BezierView,继承自FrameLayout,拖动的时候,相当于覆盖在屏幕上一样。在init()方法中主要进行了以下操作

private void init(){path = new Path();paint = new Paint();paint.setAntiAlias(true);paint.setStyle(Paint.Style.FILL_AND_STROKE);paint.setStrokeWidth(2);paint.setColor(Color.RED);LayoutParams params = new LayoutParams(ViewGroup_CONTENT);exploredImageView = new ImageView(getContext());exploredImageView.setLayoutParams(params);exploredImageView.setImageResource(R.drawable.tip_anim);exploredImageView.setVisibility(View.INVISIBLE);tipImageView = new ImageView(getContext());tipImageView.setLayoutParams(params);tipImageView.setImageResource(R.drawable.skin_tips_newmessage_ninetynine);addView(tipImageView);addView(exploredImageView);}

初始化了Path和Paint对象,然后动态生成了两个ImageView

exploredImageView 主要用来实现爆炸效果,默认不可见tipImageView 手指进行拖动时的红色图标

exploredImageView设置的图片资源是一个AnimationDrawable,下面是res中的声明,控制每张图片的播放顺序和持续时间,这也很好理解

<?xml version=”1.0″ encoding=”utf-8″?><animation-list ======>

我们在学习这种自定义控件的时候,可以按照View的绘制过程,对代码进行重点的查看,比如说,我们可以从 下面这个顺序来对这个项目进行学习。

因为这个项目没有重写onMeasure(),所以我们直接从onLayout看看做了什么

(boolean changed, int left, int top, int right, int bottom) {exploredImageView.setX(startX – exploredImageView.getWidth()/2);exploredImageView.setY(startY – exploredImageView.getHeight()/2);tipImageView.setX(startX – tipImageView.getWidth()/2);tipImageView.setY(startY – tipImageView.getHeight()/2);super.onLayout(changed, left, top, right, bottom);}

代码还是非常还理解的,无非就是初始化了ImageView的位置,在这里出现了两个变量,startX和startY,这两个变量控制的是红点的初始化坐标,在整个过程中不会发生改变。

那么onDraw()呢?

@Overrideprotected void onDraw(Canvas canvas){if(isAnimStart || !isTouch){canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.OVERLAY);}else{calculate();canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.OVERLAY);canvas.drawPath(path, paint);canvas.drawCircle(startX, startY, radius, paint);canvas.drawCircle(x, y, radius, paint);}super.onDraw(canvas);}

onDraw()里面的操作也并不复杂,如果正在执行动画或者是没有在触摸模式,就画一个透明的颜色,否则,就开始画真正的界面了。calculate()这个方法是一个重点,从命名来看应该是计算了一些坐标值,然后开始画了两个圆,这两个圆的坐标,一个是(startX,startY),另一个是(x,y),颜色和半径都是相同的,这个是为了简化计算,所以将两个圆的半径设置成相同的啦。

我们先继续看一下在onTouchEvent()里面进行了什么操作

@Overridepublic boolean onTouchEvent(MotionEvent event) {if(event.getAction() == MotionEvent.ACTION_DOWN){// 判断触摸点是否在tipImageView中Rect rect = new Rect();int[] location = new int[2];tipImageView.getDrawingRect(rect);tipImageView.getLocationOnScreen(location);rect.left = location[0];rect.top = location[1];rect.right = rect.right + location[0];rect.bottom = rect.bottom + location[1];if (rect.contains((int)event.getRawX(), (int)event.getRawY())){isTouch = true;}}else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){isTouch = false;tipImageView.setX(startX – tipImageView.getWidth()/2);tipImageView.setY(startY – tipImageView.getHeight()/2);}invalidate();if(isAnimStart){return super.onTouchEvent(event);}anchorX = (event.getX() + startX)/2;anchorY = (event.getY() + startY)/2;x = event.getX();y = event.getY();return true;}发光并非太阳的专利,你也可以发光

【开源项目解析】QQ“一键下班”功能实现解析

相关文章:

你感兴趣的文章:

标签云: