欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android未讀消息拖動氣泡示例代碼詳解(附源碼)

 更新時間:2021年02月20日 14:21:29   作者:csdn小甌  
這篇文章主要介紹了Android未讀消息拖動氣泡示例代碼詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

前言

拖動清除未讀消息可以說在很多應(yīng)用中都很常見,也被用戶廣泛接受。本文是一個可以供參考的Demo,希望能有幫助。

提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

最終效果圖及思路

在這里插入圖片描述
在這里插入圖片描述

實現(xiàn)關(guān)鍵

氣泡中間的兩條邊,分別是以ab,cd為數(shù)據(jù)點,G為控制點的貝塞爾曲線。

步驟

繪制圓背景以及文本;連接情況繪制貝塞爾曲線;另外端點繪制一個圓

關(guān)鍵代碼

1.定義,初始化等

狀態(tài):靜止、連接、分離、消失
在onSizeChanged中初始化狀態(tài),固定氣泡以及可動氣泡的圓心

代碼如下(示例):

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 super.onSizeChanged(w, h, oldw, oldh);

 init(w, h);
}

private void init(int w, int h) {
 mBubbleState = BUBBLE_STATE_DEFAULT;

 //設(shè)置固定氣泡圓心初始坐標(biāo)
 if (mBubFixedCenter == null) {
 mBubFixedCenter = new PointF(w / 2, h / 2);
 } else {
 mBubFixedCenter.set(w / 2, h / 2);
 }
 //設(shè)置可動氣泡圓心初始坐標(biāo)
 if (mBubMovableCenter == null) {
 mBubMovableCenter = new PointF(w / 2, h / 2);
 } else {
 mBubMovableCenter.set(w / 2, h / 2);
 }
}

2.onDraw中繪制包括三樣繪制

第一樣:靜止,連接,分離狀態(tài)都需要繪制圓背景以及文本:

//靜止,連接,分離狀態(tài)都需要繪制圓背景以及文本
if (mBubbleState != BUBBLE_STATE_DISMISS) {
 canvas.drawCircle(mBubMovableCenter.x, mBubMovableCenter.y, mBubMovableRadius, mBubblePaint);
 mTextPaint.getTextBounds(mTextStr, 0, mTextStr.length(), mTextRect);
 canvas.drawText(mTextStr, mBubMovableCenter.x - mTextRect.width() / 2, mBubMovableCenter.y + mTextRect.height() / 2, mTextPaint);
}	

第二樣:連接狀態(tài)繪制貝塞爾曲線①。

if (mBubbleState == BUBBLE_STATE_CONNECT) {
 //繪制靜止的氣泡
 canvas.drawCircle(mBubFixedCenter.x, mBubFixedCenter.y, mBubFixedRadius, mBubblePaint);
 //計算控制點的坐標(biāo)
 int iAnchorX = (int) ((mBubMovableCenter.x + mBubFixedCenter.x) / 2);
 int iAnchorY = (int) ((mBubMovableCenter.y + mBubFixedCenter.y) / 2);

 float sinTheta = (mBubMovableCenter.y - mBubFixedCenter.y) / mDist;
 float cosTheta = (mBubMovableCenter.x - mBubFixedCenter.x) / mDist;

 //D
 float iBubFixedStartX = mBubFixedCenter.x - mBubFixedRadius * sinTheta;
 float iBubFixedStartY = mBubFixedCenter.y + mBubFixedRadius * cosTheta;
 //C
 float iBubMovableEndX = mBubMovableCenter.x - mBubMovableRadius * sinTheta;
 float iBubMovableEndY = mBubMovableCenter.y + mBubMovableRadius * cosTheta;

 //A
 float iBubFixedEndX = mBubFixedCenter.x + mBubFixedRadius * sinTheta;
 float iBubFixedEndY = mBubFixedCenter.y - mBubFixedRadius * cosTheta;
 //B
 float iBubMovableStartX = mBubMovableCenter.x + mBubMovableRadius * sinTheta;
 float iBubMovableStartY = mBubMovableCenter.y - mBubMovableRadius * cosTheta;

 mBezierPath.reset();
 mBezierPath.moveTo(iBubFixedStartX, iBubFixedStartY);
 mBezierPath.quadTo(iAnchorX, iAnchorY, iBubMovableEndX, iBubMovableEndY);

 mBezierPath.lineTo(iBubMovableStartX, iBubMovableStartY);
 mBezierPath.quadTo(iAnchorX, iAnchorY, iBubFixedEndX, iBubFixedEndY);
 mBezierPath.close();
 canvas.drawPath(mBezierPath, mBubblePaint);
}

第三樣:消失狀態(tài)執(zhí)行爆炸動畫

// 認(rèn)為是消失狀態(tài),執(zhí)行爆炸動畫
if (mBubbleState == BUBBLE_STATE_DISMISS && mCurDrawableIndex < mBurstBitmapsArray.length) {
 mBurstRect.set(
  (int) (mBubMovableCenter.x - mBubMovableRadius),
  (int) (mBubMovableCenter.y - mBubMovableRadius),
  (int) (mBubMovableCenter.x + mBubMovableRadius),
  (int) (mBubMovableCenter.y + mBubMovableRadius));
 canvas.drawBitmap(mBurstBitmapsArray[mCurDrawableIndex], null, mBurstRect, mBubblePaint);
}

3.onTouchEvent中

按下:區(qū)分靜止?fàn)顟B(tài)和連接狀態(tài)

case MotionEvent.ACTION_DOWN:
 if (mBubbleState != BUBBLE_STATE_DISMISS) {
 mDist = (float) Math.hypot(event.getX() - mBubFixedCenter.x, event.getY() - mBubFixedCenter.y);
 if (mDist < mBubbleRadius + MOVE_OFFSET) {
  //加上MOVE_OFFSET是為了方便拖拽
  mBubbleState = BUBBLE_STATE_CONNECT;
 } else {
  mBubbleState = BUBBLE_STATE_DEFAULT;
 }
 }
 break;

移動:判斷是否到了分離狀態(tài)

case MotionEvent.ACTION_MOVE:
 if (mBubbleState != BUBBLE_STATE_DEFAULT) {
 mDist = (float) Math.hypot(event.getX() - mBubFixedCenter.x, event.getY() - mBubFixedCenter.y);
 mBubMovableCenter.x = event.getX();
 mBubMovableCenter.y = event.getY();
 if (mBubbleState == BUBBLE_STATE_CONNECT) {
  if (mDist < mMaxDist - MOVE_OFFSET) {
  mBubFixedRadius = mBubbleRadius - mDist / 8;
  } else {
  mBubbleState = BUBBLE_STATE_APART;
  }
 }
 invalidate();
 }
 break;

彈起:判斷是否已經(jīng)到了分離狀態(tài),分離狀態(tài)爆炸,未分離反彈

case MotionEvent.ACTION_UP:
 if (mBubbleState == BUBBLE_STATE_CONNECT) {
 // 橡皮筋動畫
 startBubbleRestAnim();
 } else if (mBubbleState == BUBBLE_STATE_APART) {
 if (mDist < 2 * mBubbleRadius){
  //反彈動畫
  startBubbleRestAnim();
 }else{
  // 爆炸動畫
  startBubbleBurstAnim();
 }
 }
 break;

4.反彈和爆炸動畫

/**
 * 連接狀態(tài)下松開手指,執(zhí)行類似橡皮筋動畫
 */
private void startBubbleRestAnim() {
 ValueAnimator anim = ValueAnimator.ofObject(new PointFEvaluator(),
  new PointF(mBubMovableCenter.x, mBubMovableCenter.y),
  new PointF(mBubFixedCenter.x, mBubFixedCenter.y));
 anim.setDuration(200);
 anim.setInterpolator(new OvershootInterpolator(5f));
 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
 @Override
 public void onAnimationUpdate(ValueAnimator animation) {
  mBubMovableCenter = (PointF) animation.getAnimatedValue();
  invalidate();
 }
 });
 anim.addListener(new AnimatorListenerAdapter() {
 @Override
 public void onAnimationEnd(Animator animation) {
  super.onAnimationEnd(animation);
  mBubbleState = BUBBLE_STATE_DEFAULT;
 }
 });
 anim.start();
}
/**
 * 爆炸動畫
 */
 private void startBubbleBurstAnim() {
 //將氣泡改成消失狀態(tài)
 mBubbleState = BUBBLE_STATE_DISMISS;
 ValueAnimator animator = ValueAnimator.ofInt(0, mBurstBitmapsArray.length);
 animator.setInterpolator(new LinearInterpolator());
 animator.setDuration(500);
 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
  public void onAnimationUpdate(ValueAnimator animation) {
  mCurDrawableIndex = (int) animation.getAnimatedValue();
  invalidate();
  }
 });
 animator.start();
 }

總結(jié)

注:①貝塞爾曲線參考博文

本文完,有需要參考的同學(xué)→文中Demo下載地址

本系列文章引導(dǎo)頁點擊這里

到此這篇關(guān)于Android未讀消息拖動氣泡示例代碼詳解的文章就介紹到這了,更多相關(guān)Android未讀消息拖動氣泡內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android ANR原理分析

    Android ANR原理分析

    ANR即Application Not Responding,顧名思義就是應(yīng)用程序無響應(yīng)。在Android中,一般情況下,四大組件均是工作在主線程中的,Android會隨時監(jiān)控應(yīng)用程序的響應(yīng)情況,如果因為一些耗時操作,那么系統(tǒng)就會顯示ANR對話框提示用戶對應(yīng)的應(yīng)用處于無響應(yīng)狀態(tài)
    2021-06-06
  • Android利用HelloChart繪制曲線

    Android利用HelloChart繪制曲線

    這篇文章主要為大家詳細(xì)介紹了Android利用HelloChart繪制曲線,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Android 不同Activity間數(shù)據(jù)的傳遞 Bundle對象的應(yīng)用

    Android 不同Activity間數(shù)據(jù)的傳遞 Bundle對象的應(yīng)用

    本篇文章小編為大家介紹,Android 不同Activity間數(shù)據(jù)的傳遞 Bundle對象的應(yīng)用。需要的朋友參考下
    2013-04-04
  • Android UI自定義ListView實現(xiàn)下拉刷新和加載更多效果

    Android UI自定義ListView實現(xiàn)下拉刷新和加載更多效果

    這篇文章主要介紹了Android UI自定義ListView實現(xiàn)下拉刷新和加載更多效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • PopupWindow自定義位置顯示的實現(xiàn)代碼

    PopupWindow自定義位置顯示的實現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了PopupWindow自定義位置顯示,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android實現(xiàn)跟隨手指拖動并自動貼邊的View樣式(實例demo)

    Android實現(xiàn)跟隨手指拖動并自動貼邊的View樣式(實例demo)

    本文通過實例代碼給大家介紹了android實現(xiàn)跟隨手指拖動并自動貼邊的View樣式,效果非常棒,具有參考借鑒價值,需要的朋友參考下吧
    2017-01-01
  • Android Jetpack架構(gòu)組件Lifecycle詳解

    Android Jetpack架構(gòu)組件Lifecycle詳解

    這篇文章主要介紹了Android Jetpack架構(gòu)組件Lifecycle詳解,Lifecycle是Jetpack架構(gòu)組件中用來感知生命周期的組件,使用Lifecycles可以幫助我們寫出和生命周期相關(guān)更簡潔更易維護的代碼。對此感興趣的小伙伴可以來學(xué)習(xí)一下
    2020-07-07
  • Android自定義View仿華為圓形加載進度條

    Android自定義View仿華為圓形加載進度條

    這篇文章主要為大家詳細(xì)介紹了Android自定義View仿華為圓形加載進度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • android使用百度地圖SDK獲取定位信息示例

    android使用百度地圖SDK獲取定位信息示例

    這篇文章主要介紹了android使用百度地圖SDK獲取定位信息示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • android實現(xiàn)音樂播放器

    android實現(xiàn)音樂播放器

    這篇文章主要為大家詳細(xì)介紹了android實現(xiàn)音樂播放器,擁有播放、暫停、重新播放和停止等功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04

最新評論