安卓自定義控件 一個(gè)指示用的箭頭

  • 需求:隨著手指滑動(dòng)喘垂,出現(xiàn)一個(gè)指示用的箭頭禾酱,向這樣的

    [圖片上傳失敗...(image-57ef8e-1574057435378)]

    畫一條線很簡單全释,用onTouchEvent()即可已骇,難點(diǎn)在畫那個(gè)小箭頭上面孝凌,看著簡單方咆,畫起來各種角度、坐標(biāo)系蟀架,畫的欲仙欲死的···

  1. 首先確定2個(gè)點(diǎn)的位置瓣赂,并傳給自定義控件arrowView
         private ArrowView av;
         private float startX;
         private float startY;
     @Override
         public boolean onTouchEvent(MotionEvent event) {
             int action = event.getAction();
             switch (action) {
                 case MotionEvent.ACTION_DOWN:
                     //記下按下去的初始位置榆骚,actionbarHeight和statusHeight是toolBar和狀態(tài)欄的高度
                     startX = event.getX();
                     startY = event.getY()-actionBarHeight-statusHeight;
                     break;
                 case MotionEvent.ACTION_MOVE:
                     float moveX = event.getX();
                     float moveY = event.getY()-actionBarHeight-statusHeight;
                     av.clear();                                 //每次移動(dòng)的時(shí)候都先清空一次path
                     av.setPath(startX,startY,moveX,moveY);  //將2個(gè)點(diǎn)的位置傳給arrowView
                     break;
                 case MotionEvent.ACTION_UP:
                     //do something
                     }
                     break;
             }    
             return super.onTouchEvent(event);
         }
  • ArrowView來了
       package com.aidebar.intentdemo;

       import android.content.Context;
       import android.graphics.Canvas;
       import android.graphics.Color;
       import android.graphics.Paint;
       import android.graphics.Path;
       import android.util.AttributeSet;
       import android.view.View;

       /**
        * @author xzj
        * @date 2016/10/26 14:59.
        */

       public class ArrowView extends View {
           private Paint paint;
           private Path path;
           private Paint arrowPaint;
           private Path arrowPath;
           private float startX;
           private float startY;
           private float endX;
           private float endY;

           public ArrowView(Context context) {
               super(context);
               init();
           }

           public ArrowView(Context context, AttributeSet attrs) {
               super(context, attrs);
               init();
           }

           public ArrowView(Context context, AttributeSet attrs, int defStyleAttr) {
               super(context, attrs, defStyleAttr);
               init();
           }

           private void init() {
               paint = new Paint();
               arrowPaint = new Paint();
               arrowPaint.setAntiAlias(true);
               arrowPaint.setColor(Color.RED);
               arrowPaint.setStrokeWidth(5);
               arrowPaint.setStyle(Paint.Style.FILL);//箭頭是個(gè)實(shí)心三角形,所以用fill
               arrowPath = new Path();
               path = new Path();
               paint.setAntiAlias(true);
               paint.setColor(Color.RED);
               paint.setStrokeWidth(5);
               paint.setStyle(Paint.Style.STROKE);
           }

           @Override
           protected void onDraw(Canvas canvas) {
               setArrowPath();
               canvas.drawPath(path, paint);
               canvas.drawPath(arrowPath, arrowPaint);
           }

           /**
            * 畫箭頭
            */
           public void setArrowPath() {
               double H = 18; // 箭頭高度     
               double L = 13.5; // 底邊的一半     

               double angle = Math.atan(L / H); // 箭頭角度     
               double arrowLength = Math.sqrt(L * L + H * H); // 箭頭的長度    
               //箭頭就是個(gè)三角形煌集,我們已經(jīng)有一個(gè)點(diǎn)了妓肢,根據(jù)箭頭的角度和長度,確定另外2個(gè)點(diǎn)的位置
               double[] point1 = rotateVec(endX - startX, endY - startY, angle, arrowLength);      
               double[] point2 = rotateVec(endX - startX, endY - startY, -angle, arrowLength);
               double point1_x = endX - point1[0]; 
               double point1_y = endY - point1[1];
               double point2_x = endX - point2[0];      
               double point2_y = endY - point2[1];
               int x3 = (int) point1_x;
               int y3 = (int) point1_y;
               int x4 = (int) point2_x;
               int y4 = (int) point2_y;
               // 畫線     
               arrowPath.moveTo(endX, endY);
               arrowPath.lineTo(x3, y3);
               arrowPath.lineTo(x4, y4);
               arrowPath.close();
           }
           // 計(jì)算   
           /**
            * @param diffX  X的差值
            * @param diffY  Y的差值
            * @param angle    箭頭的角度(箭頭三角形的線與直線的角度)
            * @param arrowLength 箭頭的長度
            */
           public double[] rotateVec(float diffX, float diffY, double angle, double arrowLength) {
               double arr[] = new double[2];
               // 下面的是公式苫纤,得出的是以滑動(dòng)出的線段末點(diǎn)為中心點(diǎn)旋轉(zhuǎn)angle角度后,線段起點(diǎn)的坐標(biāo)碉钠,這個(gè)旋轉(zhuǎn)后的線段也就是“變長了的箭頭的三角形的一條邊”
               //推導(dǎo)見注釋1 
               double x = diffX * Math.cos(angle) - diffY * Math.sin(angle);
               double y = diffX * Math.sin(angle) + diffY * Math.cos(angle);
               double d = Math.sqrt(x * x + y * y);
               //根據(jù)相似三角形,得出真正的箭頭三角形頂點(diǎn)坐標(biāo)方面,這里見注釋2
               x = x / d * arrowLength;
               y = y / d * arrowLength;
               arr[0] = x;
               arr[1] = y;
               return arr;
           }
           public void setPath(float startX, float startY, float endX, float endY) {
               path.moveTo(startX,startY);
               path.lineTo(endX,endY);
               this.startX = startX;
               this.startY = startY;
               this.endX = endX;
               this.endY = endY;
               invalidate();
           }
           public void clear() {
               path.reset();
               arrowPath.reset();
           }
       }

注釋1:前方高能放钦,初中數(shù)學(xué)老師來臨
一個(gè)點(diǎn)坐標(biāo)為(x1,y1),與x軸夾角為A,與原點(diǎn)距離為r恭金,那么
x1 = r *cosA ————–①
y1 = r *sinA ————–②
以原點(diǎn)為圓心操禀,將該點(diǎn)旋轉(zhuǎn)B度后,得到點(diǎn)(x2,y2)
x2 = r *cos(A+B)= r *(cosAcosB - sinAsinB)
y2 = r *sin(A+B)= r *(sinAcosB + cosAsinB)
將①②式帶入可得:
x2 = x1cosB - y1sinB
y2 = y1cosB + x1sinB
注釋2:前方高能横腿,初中數(shù)學(xué)老師又來


x/x1=arrowLength/d
x = x1 / d * arrowLength

EOF ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颓屑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子耿焊,更是在濱河造成了極大的恐慌揪惦,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件罗侯,死亡現(xiàn)場離奇詭異器腋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)钩杰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門纫塌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人讲弄,你說我怎么就攤上這事措左。” “怎么了避除?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵怎披,是天一觀的道長。 經(jīng)常有香客問我瓶摆,道長凉逛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任群井,我火速辦了婚禮鱼炒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己昔瞧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布菩佑。 她就那樣靜靜地躺著自晰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪稍坯。 梳的紋絲不亂的頭發(fā)上酬荞,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音瞧哟,去河邊找鬼混巧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛勤揩,可吹牛的內(nèi)容都是我干的咧党。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼陨亡,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼傍衡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起负蠕,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤蛙埂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后遮糖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绣的,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年欲账,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了屡江。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡敬惦,死狀恐怖盼理,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俄删,我是刑警寧澤宏怔,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站畴椰,受9級(jí)特大地震影響臊诊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜斜脂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一抓艳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帚戳,春花似錦玷或、人聲如沸儡首。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔬胯。三九已至,卻和暖如春位他,著一層夾襖步出監(jiān)牢的瞬間氛濒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國打工鹅髓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舞竿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓窿冯,卻偏偏與公主長得像骗奖,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子靡菇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容