日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Android 實現仿QQ拖拽氣泡效果的示例

瀏覽:185日期:2022-06-06 08:00:29
效果圖:

Android 實現仿QQ拖拽氣泡效果的示例

一、實現思路

在列表中默認使用自定義的TextView控件來展示消息氣泡,在自定義的TextView控件中重寫onTouchEvent方法,然后在DOWN、MOVE、UP事件中分別處理拖拽效果。

整個拖拽效果我們可以拆分成以下幾步來實現:1.默認狀態2.兩氣泡相連狀態3.兩氣泡分離狀態4.氣泡消失狀態

二、功能實現

默認狀態:用來做一個狀態的標識,無需特別處理。

兩氣泡相連狀態:繪制一個固定圓和一個移動圓,使用兩條貝塞爾曲線來實現兩氣泡連接的曲線,兩條貝塞爾曲線共用同一個控制點,然后根據MOVE事件中的坐標不斷重繪移動圓。

實現兩氣泡連接的效果,需要先計算出一些點的坐標,這也是整個拖拽氣泡效果的核心部分,具體如下圖:

Android 實現仿QQ拖拽氣泡效果的示例

如圖,A點到B點是一條二階貝塞爾曲線,C點到D點也是一條二階貝塞爾曲線,它們共用同一個控制點,所以我們要計算出A點、B點、C點、D點以及控制點的坐標。

首先來計算控制點的坐標,控制點的坐標和容易計算出,也就是固定圓的x坐標加上移動圓的x坐標,再除以2,固定圓的y坐標同理得出。

int controlX = (int) ((mBubStillCenter.x + mBubMoveCenter.x) / 2);int controlY = (int) ((mBubStillCenter.y + mBubMoveCenter.y) / 2);

根據圖中所標注的信息得知,∠a=∠d,∠b=∠c,∠a=∠θ,由此可知,我們求出∠θ所在的直角三角形的sin和cos值,就可以計算出A點、B點、C點、D點的坐標。

sin值可以通過移動圓的y坐標減去固定圓的y坐標,再除以兩圓心的距離,也就是O1到O2的距離。

cos值可以通過移動圓的x坐標減去固定圓的x坐標,再除以兩圓心的距離。

float sin = (mBubMoveCenter.y - mBubStillCenter.y) / mDist;float cos = (mBubMoveCenter.x - mBubStillCenter.x) / mDist;

有了sin和cos值,對應的A點、B點、C點、D點的坐標就好計算了

// A點float bubbleStillStartX = mBubStillCenter.x + mBubbleStillRadius * sin;float bubbleStillStartY = mBubStillCenter.y - mBubbleStillRadius * cos;// B點float bubbleMoveStartX = mBubMoveCenter.x + mBubbleMoveRadius * sin;float bubbleMoveStartY = mBubMoveCenter.y - mBubbleMoveRadius * cos;// C點float bubbleMoveEndX = mBubMoveCenter.x - mBubbleMoveRadius * sin;float bubbleMoveEndY = mBubMoveCenter.y + mBubbleMoveRadius * cos;// D點float bubbleStillEndX = mBubStillCenter.x - mBubbleStillRadius * sin;float bubbleStillEndY = mBubStillCenter.y + mBubbleStillRadius * cos;

接下來就是把這些貝塞爾曲線和直線連起來,就實現了兩氣泡相連的效果。

兩氣泡分離狀態:當拖拽的移動圓超出固定圓一定范圍時,就進入了兩氣泡分離狀態,此時我們只需要繪制移動圓即可。當拖拽的移動圓回到固定圓一定范圍時,此時會進入兩氣泡相連狀態,并且需要實現一個氣泡還原的效果。(這里會有個難點,就是移動圓我們可以在屏幕上任意拖動而不被遮擋,這里放到后面來實現。)

public void move(float curX, float curY) { mBubMoveCenter.x = curX; mBubMoveCenter.y = curY; mDist = (float) Math.hypot(curX - mBubStillCenter.x, curY - mBubStillCenter.y); if(mBubbleState == BUBBLE_STATE_CONNECT){ if(mDist < mMaxDist - MOVE_OFFSET){ mBubbleStillRadius = mBubbleRadius - mDist / 10; }else { mBubbleState = BUBBLE_STATE_APART; } } invalidate();}

mDist就是兩圓心的距離。

/** * 氣泡還原動畫 */private void startBubbleRestAnim() { mBubbleStillRadius = mBubbleRadius; ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(), new PointF(mBubMoveCenter.x, mBubMoveCenter.y), new PointF(mBubStillCenter.x, mBubStillCenter.y)); animator.setDuration(200); animator.setInterpolator(input -> { float factor = 0.4f; return (float) (Math.pow(2, -10 * factor) * Math.sin((input - factor / 4) * (2 * Math.PI) / factor) + 1); }); animator.addUpdateListener(animation -> { mBubMoveCenter = (PointF) animation.getAnimatedValue(); invalidate(); }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mBubbleState = BUBBLE_STATE_DEFAULT; removeDragView(); if(mDragListener != null){mDragListener.onRestore(); } } }); animator.start();}

分享一個可視化插值器的網站,其中內置了一些插值器公式,還可以查看動畫演示效果。http://inloop.github.io/interpolator/

氣泡消失狀態:當拖拽的移動圓超出一定范圍時,并且松開了手指后,此時進入氣泡消失狀態,此時我們需要實現一個爆炸的動畫。

爆炸的動畫通過繪制一組圖片來實現

if(mBubbleState == BUBBLE_STATE_DISMISS){ if(mIsBurstAnimStart){ mBurstRect.set((int)(mBubMoveCenter.x - mBubbleMoveRadius), (int)(mBubMoveCenter.y - mBubbleMoveRadius),(int)(mBubMoveCenter.x + mBubbleMoveRadius), (int)(mBubMoveCenter.y + mBubbleMoveRadius)); canvas.drawBitmap(mBurstBitmapArray[mCurDrawableIndex], null, mBurstRect, mBurstPaint); }}

mCurDrawableIndex是圖片的索引,是通過屬性動畫來改變

/** * 氣泡爆炸動畫 */private void startBubbleBurstAnim() { ValueAnimator animator = ValueAnimator.ofInt(0, mBurstDrawablesArray.length); animator.setInterpolator(new LinearInterpolator()); animator.setDuration(1000); animator.addUpdateListener(animation -> { mCurDrawableIndex = (int) animator.getAnimatedValue(); invalidate(); }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mIsBurstAnimStart = false; if(mDragListener != null){mDragListener.onDismiss(); } } }); animator.start();}三、全屏拖拽效果實現

首先在DOWN事件中獲取當前觸摸位置在全屏所在位置,然后將當前view緩存為bitmap,并把此bitmap添加到rootview中,拖動的時候直接繪制此bitmap。

//獲得當前View在屏幕上的位置int[] cLocation = new int[2];getLocationOnScreen(cLocation);if(rootView instanceof ViewGroup){ mDragDotView = new DragDotView(getContext()); //設置固定圓和移動圓的圓心坐標 mDragDotView.setDragPoint(cLocation[0] + mWidth / 2, cLocation[1] + mHeight / 2, mRawX, mRawY); Bitmap bitmap = getBitmapFromView(this); if(bitmap != null){ mDragDotView.setCacheBitmap(bitmap); ((ViewGroup) rootView).addView(mDragDotView); setVisibility(INVISIBLE); }}/** * 將當前view緩存為bitmap,拖動的時候直接繪制此bitmap * @param view * @return */public Bitmap getBitmapFromView(View view){ Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); view.draw(canvas); return bitmap;}

至此,整個消息氣泡拖拽效果的核心部分就實現了

源碼地址:

https://github.com/loren325/CustomerView

以上就是Android 實現仿QQ拖拽氣泡效果的示例的詳細內容,更多關于Android 實現仿QQ拖拽氣泡效果的資料請關注好吧啦網其它相關文章!

標簽: qq
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日韩三级一区| 久久亚洲图片| 在线视频亚洲| 中文欧美日韩| 日韩精品欧美大片| 国产日本精品| 精品一区二区三区中文字幕| 国产成人精品一区二区三区免费| 国产一区二区三区四区五区| 欧美日韩尤物久久| 国产高清一区| 亚洲日本在线观看视频| 国产亚洲字幕| 中文字幕在线看片| 亚洲精品电影| 欧美日韩午夜| 水蜜桃久久夜色精品一区| 精品捆绑调教一区二区三区 | 日韩不卡一区| 亚洲精品在线影院| 日韩在线观看一区二区| 日韩一区二区三区四区五区| 国产日韩欧美一区二区三区在线观看| 国产第一亚洲| 蜜桃av一区| 国产极品一区| 久久久影院免费| 欧美一区二区三区免费看| 日韩av有码| 在线亚洲成人| 国产探花在线精品| 蜜桃av在线播放| 亚洲一区二区三区久久久| 国产精品中文字幕亚洲欧美| av资源亚洲| 日韩一区欧美二区| 精品国产欧美日韩一区二区三区| 亚洲福利国产| 国产亚洲精品精品国产亚洲综合| 日韩在线欧美| 香蕉久久一区| 欧美不卡高清一区二区三区| 亚久久调教视频| 国产高清不卡| 日本在线不卡视频| 久久久久国产| 国产精品任我爽爆在线播放| 蜜桃tv一区二区三区| 国产精品nxnn| 六月天综合网| 日本不良网站在线观看| 美国三级日本三级久久99| 国产a久久精品一区二区三区| 亚洲在线一区| 日韩欧美不卡| 欧美视频二区| 好吊视频一区二区三区四区| 成人在线免费观看网站| 亚洲欧洲av| 欧美va天堂在线| 欧美激情 亚洲a∨综合| 亚洲黄页一区| 久草免费在线视频| 国产日韩视频| 日韩在线一区二区| 欧美日韩色图| 岛国av免费在线观看| 日韩一区二区三区精品视频第3页 日韩一区二区三区免费视频 | 红桃视频欧美| 日韩在线中文| 日韩国产欧美在线播放| 成人午夜国产| 麻豆91在线播放| 日韩av一区二区在线影视| 鲁大师影院一区二区三区| 欧美香蕉视频| 国产+成+人+亚洲欧洲在线| 亚洲精品进入| 日韩专区在线视频| 99riav1国产精品视频| 久久精品不卡| 国产在线看片免费视频在线观看| 国产精品中文| 国产剧情在线观看一区| 婷婷五月色综合香五月| 夜夜嗨网站十八久久| 久久国产中文字幕| 欧美丝袜一区| 欧美精品资源| 欧美日韩精品免费观看视完整| 欧美激情99| 国产区精品区| 国产精品美女午夜爽爽| 日韩av一区二区在线影视| 亚洲精品乱码久久久久久蜜桃麻豆| 影音国产精品| 久久亚洲欧洲| 奇米狠狠一区二区三区| 91精品国产自产在线丝袜啪| 欧美日韩国产一区二区在线观看| 婷婷视频一区二区三区| 欧美一级网址| 捆绑调教美女网站视频一区| 精品国产美女a久久9999| 激情视频网站在线播放色| 国产美女高潮在线观看| 岛国av免费在线观看| 99久久精品网| 三级在线观看一区二区| 日韩高清三区| 国产精品久久久一区二区| 久久影视三级福利片| 国产一区二区三区四区| 成人羞羞在线观看网站| 黑丝一区二区三区| 免费成人在线视频观看| 日韩欧美中文字幕一区二区三区| 日本特黄久久久高潮| 美腿丝袜亚洲三区| av资源亚洲| 欧美中文日韩| 国产欧美日韩一区二区三区在线| 久久久91麻豆精品国产一区| av高清一区| 伊人精品久久| 精品资源在线| 激情婷婷久久| 午夜久久av| 国产福利电影在线播放| 欧美午夜不卡| 一区二区国产精品| 国产精品videosex极品| 中文另类视频| 少妇精品久久久| 成人一区而且| 国产亚洲毛片| 国产精品一线| 久久伦理在线| 欧美亚洲免费| 婷婷成人在线| 国产美女精品视频免费播放软件| 亚洲三级欧美| 免费成人在线视频观看| 美女久久久精品| 夜夜嗨一区二区| 国产精品videossex久久发布| 亚洲不卡av不卡一区二区| 婷婷综合国产| 999久久久精品国产| 91九色综合| 91精品成人| 精品伊人久久久| 免费精品视频在线| 国产成人黄色| 婷婷综合电影| 欧美日韩在线观看视频小说| 91福利精品在线观看| 久久精品国产亚洲夜色av网站| 久久精品凹凸全集| 亚洲大全视频| 久久不卡国产精品一区二区| 亚洲成人免费| 国产精品成人a在线观看| 只有精品亚洲| 国内精品福利| 麻豆国产精品一区二区三区| 在线精品观看| 99久久亚洲精品| 精品伊人久久久| 日本午夜精品| 日韩专区一卡二卡| 在线视频观看日韩| 激情不卡一区二区三区视频在线| 免费人成精品欧美精品| 久久久精品久久久久久96 | 亚州av日韩av| 欧洲激情综合| 天堂中文在线播放| 国产精品高潮呻吟久久久久| 一区二区不卡| 亚洲国产一区二区在线观看| 在线观看精品| 久久久久久久欧美精品| 美女久久99| 久久激情五月婷婷| 日本大胆欧美人术艺术动态| 久久影视一区| 视频二区不卡| 亚洲黄色免费看| 国产999精品在线观看| 国产精品中文| 日本不卡视频在线| 亚洲一区国产| 欧美 日韩 国产精品免费观看| 国产第一亚洲| 高清精品久久| 欧美国产一级| 日韩国产欧美一区二区| 国产一区丝袜| 久久久久九九精品影院|