自定義View之游戲搖桿鍵盤實現(xiàn)(二)

前言

去年開發(fā)項目,需要實現(xiàn)一個遙感按鈕眠蚂,控制公司機(jī)器人行走,于是通過自定義SurfaceView實現(xiàn)了該功能昔脯,想了解的話笛臣,傳送門在這自定義View之游戲搖桿鍵盤實現(xiàn),但由于傳輸指令過程中對時間準(zhǔn)確度要求較高静陈,調(diào)試后發(fā)現(xiàn),自定義繪制過程中時間不穩(wěn)定拐格,性能較差。于是決定不自定義SurfaceView捏浊,改而采用自定義View實現(xiàn)撞叨。

最終效果

此版本相對于之前自定義SurfaceView版本,增加角度之間的計算热康,以及指針的跟隨劣领。根據(jù)公司需求铁材,方向分為八個,除了常規(guī)的上下左右外著觉,還有上左,上右趁桃,下左肄鸽,下右。如圖

方向.png

實際開發(fā)使用后蟀苛,性能逮诲,穩(wěn)定性,都優(yōu)于上一版本裆甩,上最后效果圖

未觸摸狀態(tài)下
未觸摸.jpg
觸摸狀態(tài)下
觸摸狀態(tài)下.png

實現(xiàn)

效果圖中嗤栓,實現(xiàn)遙感按鈕所需圖片分為:中心懸浮球蝶念,外層圖芋绸,內(nèi)部方向背景圖摔敛,因此全封,先獲圖片,注意避免重復(fù)實例化

    //外層圖
    bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.control_rocker_arrow);
    //中心懸浮球
    bitmapInner = BitmapFactory.decodeResource(getResources(), R.mipmap.control_rocker_paws);
    //外層圓形帶指針圖
    bitmap1 = BitmapFactory.decodeResource(getResources(), R.mipmap.control_rocker_bg);
    bitmap2 = BitmapFactory.decodeResource(getResources(), R.mipmap.control_rocker_not_active);

獲取之后刹悴,指定相關(guān)圖片的繪制區(qū)域(例如圖片的左上角區(qū)域)

    src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
    srcNoActive = new Rect(0, 0, bitmap2.getWidth(), bitmap2.getHeight());
    srcInner = new Rect(0, 0, bitmapInner.getWidth(), bitmapInner.getHeight());

在onMeasure測量時土匀,通過bitmap寬高,獲取外層圖片的顯示區(qū)域(指定圖片在屏幕上顯示的區(qū)域)就轧,

   //觸摸
    dst = new Rect((int) mWidth / 2 - bitmap.getWidth() / 2, (int) mHeight / 2 - bitmap.getHeight() / 2,
    (int) mWidth / 2 + bitmap.getWidth() / 2, (int) mHeight / 2 + bitmap.getHeight() / 2);

    //未觸摸
    dstNoActive = new Rect((int) mWidth / 2 - bitmap2.getWidth() / 2, (int) mHeight / 2 - bitmap2.getHeight() / 2, 
    (int) mWidth / 2 + bitmap2.getWidth() / 2, (int) mHeight / 2 + bitmap2.getHeight() / 2);

測量完后,在onDraw進(jìn)行繪制妒御,在這過程中,對中心懸浮球送讲,實時測量繪制區(qū)域惋啃,避免中心球顯示不全

dstInner = new Rect((int) posX - minRadius, (int) posY - minRadius, (int) posX + minRadius, (int) posY + minRadius);

通過Matrix矩陣移動及旋轉(zhuǎn),計算控制外層指針的旋轉(zhuǎn)角度魄宏,實現(xiàn)跟隨手指方向

    matrix.reset();
    matrix.setTranslate(mWidth / 2 - bitmap1.getWidth() / 2, mHeight / 2 - bitmap1.getHeight() / 2);
    if (tempRad != 0) {
        matrix.preRotate(tempRad + 90, (float) bitmap1.getWidth() / 2, (float) bitmap1.getHeight() / 2);  //要旋轉(zhuǎn)的角度
    } else {
        matrix.preRotate(tempRad);
    }
    if (isStart) {
        canvas.drawBitmap(bitmap1, matrix, null);
    } else {
        canvas.drawBitmap(bitmap2, srcNoActive, dstNoActive, null);
    }
    matrix.reset();

注意判斷觸摸狀態(tài)宠互,以及Matrix的reset椭坚,否則下次繪制時,圖片便會偏移善茎。到此,遙感按鈕已經(jīng)實現(xiàn)

方向判斷

上面提到的烁焙,公司項目實際使用的遙感分為八個方向,因此需將遙感分為8個區(qū)域膳殷,這里給出相應(yīng)的角度,弧度計算赚窃,根據(jù)個人需求更改岔激。

弧度計算
   /***
 * 兩點弧度
 */
public float getRad(float px1, float py1, float px2, float py2) {
    float x = px2 - px1;

    float y = py1 - py2;
    //斜邊的長
    float z = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
    float cosAngle = x / z;
    float rad = (float) Math.acos(cosAngle);

    if (py2 < py1) {
        rad = -rad;
    }
    return rad;
}
角度計算
    private float getAngle(float xTouch, float yTouch) {
    RockerCircleX = mWidth / 2;
    RockerCircleY = mHeight / 2;
    return (float) (getRad(RockerCircleX, RockerCircleY, xTouch, yTouch) * 180f / Math.PI);
    }

這里我采用用接口傳遞虑鼎,將計算出的角度傳遞給Activity或者Fragment

    public interface RemoteListener {
    void onRemoteListener(int cmd);
    }

最后

在xml文件中使用即可

   <com.by.happydog.view.RemoteControlView
    android:id="@+id/remote_view"
    android:layout_width="270dp"
    android:layout_height="270dp"
    android:layout_marginLeft="15dp"
    android:layout_marginTop="60dp" />

如果你有其他思路,可以留言交流

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掀鹅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子戚丸,更是在濱河造成了極大的恐慌,老刑警劉巖夺颤,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件世澜,死亡現(xiàn)場離奇詭異,居然都是意外死亡寥裂,警方通過查閱死者的電腦和手機(jī)案疲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诺舔,“玉大人低飒,你說我怎么就攤上這事∪焐蓿” “怎么了车要?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長崭倘。 經(jīng)常有香客問我翼岁,道長,這世上最難降的妖魔是什么司光? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任琅坡,我火速辦了婚禮,結(jié)果婚禮上残家,老公的妹妹穿的比我還像新娘榆俺。我一直安慰自己,他們只是感情好坞淮,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布茴晋。 她就那樣靜靜地躺著,像睡著了一般回窘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上烁涌,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音舷丹,去河邊找鬼颜凯。 笑死装获,一個胖子當(dāng)著我的面吹牛穴豫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播秤涩,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼黎烈,長吁一口氣:“原來是場噩夢啊……” “哼照棋!你這毒婦竟也來了烈炭?” 一聲冷哼從身側(cè)響起符隙,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤霹疫,失蹤者是張志新(化名)和其女友劉穎丽蝎,沒想到半個月后征峦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡臊泰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了需频。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昭殉。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡蹂风,死狀恐怖惠啄,靈堂內(nèi)的尸體忽然破棺而出任内,到底是詐尸還是另有隱情死嗦,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站铜跑,受9級特大地震影響骡澈,放射性物質(zhì)發(fā)生泄漏肋殴。R本人自食惡果不足惜护锤,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一驱入、第九天 我趴在偏房一處隱蔽的房頂上張望亏较。 院中可真熱鬧雪情,春花似錦巡通、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窘行。三九已至罐盔,卻和暖如春救崔,著一層夾襖步出監(jiān)牢的瞬間六孵,已是汗流浹背劫窒。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工冠息, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留逛艰,地道東北人瓮孙。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓脸甘,卻偏偏與公主長得像丹诀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沿猜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

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