模仿QQ拖动清除消息提示
来源:互联网 发布:阳光民间借贷网络借贷 编辑:程序博客网 时间:2024/06/03 18:52
首先感谢这两篇文章提供的思路和代码
http://blog.csdn.net/chenupt/article/details/41478303
http://blog.csdn.net/singwhatiwanna/article/details/42614953
首先看下效果图:
实现原理:
点击屏幕,遍历所有的view,匹配点击的屏幕坐标,是否在某个红点提示的view范围内,是的话,计算红点提示的view,在自定义的布局上对应的坐标位置,计算出来的这个坐标,当做其中的一个圆的圆心,在拖动的过程中,得到的另外的坐标,当做是另外一个圆的圆心,在拖动的过程中,半径变化,但两个圆始终保持半径一样,利用贝塞尔曲线,画出拖动的效果。
重要的代码,都有注释,代码也比较少,代码如下:
/** * @Title: DragTipsLayout.java * @Package com.eeb.dragredview * @Description: TODO(模仿QQ拖动消息提示) * @author luquan yebo0505@foxmail.com * @date 2015-1-4 上午11:57:48 * @version V1.0 */package com.eeb.dragtipslayout;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Rect;import android.graphics.RectF;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;public class DragTipsLayout extends LinearLayout {// 默认定点圆半径public static final float DEFAULT_RADIUS = 10;private int[] mLocationInScreen = new int[2];private Paint paint;private Path path;private boolean dragging;// 手势滑动是的动态坐标float touchX = 0;float touchY = 0;// 锚点坐标,两个圆圆心(手势滑动坐标和要拖动的bageview的中心)的中间点float anchorX = 0;float anchorY = 0;// 定点圆半径float radius = DEFAULT_RADIUS;// 要拖动的View的中心坐标private float mCenterX;private float mCenterY;private View targetView;public DragTipsLayout(Context context) {super(context);init();}public DragTipsLayout(Context context, AttributeSet attrs) {super(context, attrs);init();}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);this.getLocationOnScreen(mLocationInScreen);//DragTisLayout 在屏幕上的位置}@Overrideprotected void dispatchDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.dispatchDraw(canvas);if (dragging) {// 画拖动的效果,这里计算的是在拖动的过程中,半径变化,但两个圆始终保持半径一样,如果半径一大一小不同,需要另外计算float distance = (float) Math.sqrt(Math.pow(touchY - mCenterY, 2)+ Math.pow(touchX - mCenterX, 2));radius = -distance / 20 + DEFAULT_RADIUS;paint.setColor(Color.RED);if (radius > 5) {float offsetX = (float) (radius * Math.sin(Math.atan((touchY - mCenterY) / (touchX - mCenterX))));float offsetY = (float) (radius * Math.cos(Math.atan((touchY - mCenterY) / (touchX - mCenterX))));float x1 = mCenterX - offsetX;float y1 = mCenterY + offsetY;float x2 = touchX - offsetX;float y2 = touchY + offsetY;float x3 = touchX + offsetX;float y3 = touchY - offsetY;float x4 = mCenterX + offsetX;float y4 = mCenterY - offsetY;path.reset();path.moveTo(x1, y1);path.quadTo(anchorX, anchorY, x2, y2);path.lineTo(x3, y3);path.quadTo(anchorX, anchorY, x4, y4);path.lineTo(x1, y1);canvas.drawCircle(mCenterX, mCenterY, radius, paint);canvas.drawPath(path, paint);}if (targetView != null) {//计算字体所占的位置大小,获取拖动的badge大小,以确定在拖动过程中,字体居中,画出拖动的view跟badgeview一样String num = ((BadgeView) targetView).getText().toString();Rect rect = new Rect();paint.getTextBounds(num, 0, num.length(), rect);RectF rectF = new RectF(touchX-targetView.getWidth()/2,touchY-targetView.getHeight()/2,touchX+targetView.getWidth()/2,touchY+targetView.getHeight()/2);canvas.drawOval(rectF, paint);paint.setColor(Color.WHITE);canvas.drawText(num,touchX-rect.centerX(), touchY-rect.centerY(), paint);}}}private void init() {setWillNotDraw(false);path = new Path();paint = new Paint();paint.setAntiAlias(true);paint.setStyle(Paint.Style.FILL_AND_STROKE);paint.setStrokeWidth(1);paint.setColor(Color.RED);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:findTouchTarget(this, event.getRawX(), event.getRawY());touchX = event.getX();touchY = event.getY();anchorX = touchX;anchorY = touchY;break;case MotionEvent.ACTION_MOVE:touchX = event.getX();touchY = event.getY();anchorX = (mCenterX + touchX) / 2;anchorY = (mCenterY + touchY) / 2;break;case MotionEvent.ACTION_UP:if (radius > 5 && targetView != null)targetView.setVisibility(View.VISIBLE);dragging = false;break;}invalidate();//如果没有拖动, 事件分发不做处理,正常使用点击,长按事件,如果return true,可以理解为事件不传递到子类,各个子view的点击,滑动无效if(dragging)return true;elsereturn super.dispatchTouchEvent(event);}//遍历DragTipsLayout下所有的viewprivate void findTouchTarget(ViewGroup viewGrop, float x, float y) {for (int i = 0; i < viewGrop.getChildCount(); i++) {View temp = viewGrop.getChildAt(i);if (temp instanceof ViewGroup) {ViewGroup tempViewGrop = (ViewGroup) temp;findTouchTarget(tempViewGrop, x, y);//递归查找} else if (temp instanceof BadgeView&&isTouchBadgeView(temp, x, y)){//判断是否是BadgeView并且点击屏幕的坐标在BadgeView的区域范围内dragging = true;}}}private boolean isTouchBadgeView(View view, float x, float y) {int[] location = new int[2];view.getLocationOnScreen(location);int left = location[0];int top = location[1];int right = left + view.getMeasuredWidth();int bottom = top + view.getMeasuredHeight();if (view.getVisibility() == View.VISIBLE && y >= top && y <= bottom&& x >= left && x <= right) {//依据遍历找到的BadgeView,计算对应在DragTipsLayout上的坐标点mCenterX = (left + right) / 2 - - mLocationInScreen[0];mCenterY = (top+bottom)/2 - mLocationInScreen[1];targetView = view;view.setVisibility(View.INVISIBLE);return true;}return false;}}
完整代码下载
欢迎转载,但请说明出处http://blog.csdn.net/yebo0505/article/details/42779441
0 0
- 模仿QQ拖动清除消息提示
- 模仿QQ拖动清除消息提示
- 模仿QQ消息红点拖动效果
- 模仿MsN或QQ提示消息
- C# 模仿QQ右下角 消息闪烁提示
- 模仿QQ与MSN消息提示效果(message)
- C# 模仿QQ、MSN消息提示系列 一、基本原理
- C# 模仿QQ、MSN消息提示系列 一、基本原理
- 网页模仿QQ消息
- C# 模仿QQ、MSN消息提示系列 二、基本效果模仿包含代码
- C# 模仿QQ、MSN消息提示系列 二、基本效果模仿包含代码
- C# 模仿QQ、MSN消息提示系列 三、实现多个提示效果
- C# 模仿QQ、MSN消息提示系列 三、实现多个提示效果
- jquery模仿QQ消息框
- C# 模仿QQ、MSN消息提示系列 四、bug修改 效果优化
- C# 模仿QQ、MSN消息提示系列 四、bug修改 效果优化
- C# 模仿QQ、MSN消息提示系列 五、改进 只使用两个时间控件
- Android模仿QQ/微信未读消息显示
- 撒的撒的撒的
- 网站年终特惠
- Hibernate @temporal的使用说明
- java中强引用、软引用、弱引用和虚引用
- SDUT_2015寒假集训_结构体练习_G-最终排名
- 模仿QQ拖动清除消息提示
- NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证
- html5开发中常用meta标签
- 转战移动开发,新的起点
- C++ 单元测试
- 四则运算的C++实现
- java 常用按 开始日期 和 结束日期 查询处理
- http://linux.linuxidc.com/
- Android的第一天