這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)怎么在android應(yīng)用中利用view實(shí)現(xiàn)一個(gè)拖拽刪除功能,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
專注于為中小企業(yè)提供成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)芒市免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了千余家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。功能有以下幾個(gè)特點(diǎn):
在開始的時(shí)候點(diǎn)擊圓以外的區(qū)域不會(huì)觸發(fā)拖動(dòng)事件
點(diǎn)擊圓的時(shí)候可以拖拽,此時(shí)會(huì)有一個(gè)拉伸效果,連接大圓和小圓
拉伸到一定距離(自己設(shè)定)以后兩個(gè)圓會(huì)斷開,此時(shí)即使再拖拽進(jìn)距離之內(nèi)的時(shí)候也不會(huì)再產(chǎn)生已經(jīng)斷開的連接
在距離之內(nèi)松手的時(shí)候會(huì)回彈會(huì)原位置,并伴有一個(gè)彈跳動(dòng)畫
介紹了這么多,看過我前邊文章的朋友應(yīng)該會(huì)有一個(gè)基本思路。
暴露接口
這個(gè)模擬功能共分為三部分,一個(gè)是那個(gè)小圓,固定的位置,一個(gè)是那個(gè)大圓,可以移動(dòng),還有一部分就是中間的連接部分,會(huì)跟隨大圓一起延伸。
首先看一下都有哪些接口可以調(diào)用:
public void setMinR(float minR) { this.minR = minR; } public void setMaxR(float maxR) { this.maxR = maxR; } public void setBrokeDistance(float distance) { this.brokeDistance = distance; }
第一個(gè)setMinR是設(shè)置小圓的半徑,第二個(gè)setMaxR是設(shè)置大圓的半徑,第三個(gè)setBrokeDistance是設(shè)置斷開的距離,也就是小圓和大圓的圓心之間的大連接距離。
初始化
public Buble(Context context) { super(context); init(); } public Buble(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); }
簡(jiǎn)單的看一下初始化方法。
private void init() { paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.GREEN); paint.setAntiAlias(true); }
其實(shí)只有一個(gè)畫筆,這里可以為各個(gè)區(qū)域分別設(shè)置畫筆。
繪制圖形
protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawOriginalCircle(canvas); if (!canBroke) { drawMoveCircle(canvas); drawBCurve(canvas); } }
這三個(gè)方法相對(duì)簡(jiǎn)單,drawOriginalCircle是畫中心的小圓,然后canBroke是一個(gè)開關(guān),控制是否執(zhí)行畫移動(dòng)的圓和畫弧線。
private void drawOriginalCircle(Canvas canvas) { canvas.drawCircle(getWidth() / 2, getHeight() / 2, minR, paint); } private void drawMoveCircle(Canvas canvas) { canvas.drawCircle(moveX, moveY, maxR, paint); } private void drawBCurve(Canvas canvas) { canvas.drawPath(path, paint); }
注意,moveX, moveY和path都是變化的,所以在他們的值發(fā)生改變以后千萬不要忘記invalidate。
path的連接
關(guān)于path的文章網(wǎng)上一大堆。
此處的難點(diǎn)主要是大圓和小圓之間的連接。用一張圖簡(jiǎn)單表示一下:
基本就是這個(gè)樣子,path的路徑就是那個(gè)黑色的類似于漏斗一樣的東西。此處要計(jì)算的角度需要用到三角函數(shù)關(guān)系式,簡(jiǎn)單表示一下:
圖中標(biāo)出的兩個(gè)角度是相等的
double angle = Math.atan((offsetX - minCircleX) / (offsetY - minCircleY));
求出這個(gè)角度(offsetX是移動(dòng)圓心的坐標(biāo))。
這樣就可以算出四個(gè)點(diǎn)的坐標(biāo)了。
private void setPath(float offsetX, float offsetY) { float minCircleX = (float) getWidth() / 2; float minCircleY = (float) getHeight() / 2; double angle = Math.atan((offsetX - minCircleX) / (offsetY - minCircleY)); float x1 = (float) (minCircleX + Math.cos(angle) * minR); float y1 = (float) (minCircleY - Math.sin(angle) * minR); float x2 = (float) (offsetX + Math.cos(angle) * maxR); float y2 = (float) (offsetY - Math.sin(angle) * maxR); float x3 = (float) (offsetX - Math.cos(angle) * maxR); float y3 = (float) (offsetY + Math.sin(angle) * maxR); float x4 = (float) (minCircleX - Math.cos(angle) * minR); float y4 = (float) (minCircleY + Math.sin(angle) * minR); float centerX = minCircleX + (offsetX - minCircleX) / 2; float centerY = minCircleY + (offsetY - minCircleY) / 2; path.reset(); path.moveTo(minCircleX, minCircleY); path.lineTo(x1, y1); path.quadTo(centerX, centerY, x2, y2); path.lineTo(x3, y3); path.quadTo(centerX, centerY, x4, y4); path.lineTo(minCircleX, minCircleY); path.close(); }
注意quadTo的四個(gè)參數(shù)的意義,前兩個(gè)是你的錨點(diǎn)的坐標(biāo),后兩個(gè)是你要移動(dòng)到那個(gè)點(diǎn)的位置的坐標(biāo)。
觸摸事件
這個(gè)直接上代碼來實(shí)現(xiàn)思路吧,沒什么好講的。
switch (event.getAction()) { case MotionEvent.ACTION_DOWN: this.canBroke = false; moveX = event.getX(); moveY = event.getY(); touchArea = !setCanBroke(moveX, moveY, maxR); break; case MotionEvent.ACTION_MOVE: if (touchArea) { moveX = event.getX(); moveY = event.getY(); if (setCanBroke(moveX, moveY, brokeDistance)) { touchArea = false; this.canBroke = true; } else { setPath(moveX, moveY); } invalidate(); } break; case MotionEvent.ACTION_UP: Log.d("aaa", "actionUp" + touchArea); if (touchArea) { resetCircle(event.getX(), event.getY()); } break; } return true;
這里主要說明一下這個(gè)setCanBroke:
private boolean setCanBroke(float offsetX, float offsetY, float brokeDistance) { float minCircleX = (float) getWidth() / 2; float minCircleY = (float) getHeight() / 2; return (offsetX - minCircleX) * (offsetX - minCircleX) + (offsetY - minCircleY) * (offsetY - minCircleY) > brokeDistance * brokeDistance; }
這個(gè)表示是否超出了大移動(dòng)距離,超出則返回真,未超出則返回假。同時(shí)在touchArea的設(shè)定中它也用用到了,主要是判斷點(diǎn)擊區(qū)域是否在圓圈上。
最后還要講一下這個(gè)resetCicle,這個(gè)是一個(gè)屬性動(dòng)畫來控制返回原點(diǎn)的彈性動(dòng)畫:
private void resetCircle(float x, float y) { valueAnimatorX = ValueAnimator.ofFloat(x, (float) getWidth() / 2); valueAnimatorY = ValueAnimator.ofFloat(y, (float) getHeight() / 2); valueAnimatorX.removeAllUpdateListeners(); valueAnimatorY.removeAllUpdateListeners(); valueAnimatorX.setInterpolator(new BounceInterpolator()); valueAnimatorY.setInterpolator(new BounceInterpolator()); valueAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { tempX = (float) animation.getAnimatedValue(); moveX = tempX; } }); valueAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { tempY = (float) animation.getAnimatedValue(); moveY = tempY; setPath(tempX, tempY); postInvalidate(); } }); set.playTogether(valueAnimatorX, valueAnimatorY); set.start(); }
上述就是小編為大家分享的怎么在android應(yīng)用中利用view實(shí)現(xiàn)一個(gè)拖拽刪除功能了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
當(dāng)前標(biāo)題:怎么在android應(yīng)用中利用view實(shí)現(xiàn)一個(gè)拖拽刪除功能-創(chuàng)新互聯(lián)
當(dāng)前地址:http://jinyejixie.com/article28/dipojp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、靜態(tài)網(wǎng)站、用戶體驗(yàn)、云服務(wù)器、做網(wǎng)站、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容