Space+onTouchEvent=Hitarea:像Flash那樣在Android中擴大點擊區(qū)域

1 思考

我是一個資深的Flash迷鲫咽,小學開始學習做動畫撮躁,本科時寫下了第一行ActionScript 3代碼永部。在Android開發(fā)中經(jīng)常遇到點擊區(qū)域太小的問題叉谜,我思考著能不能像ActionScirpt 3那樣給一個Sprite設置一個hitArea Sprite悟狱,所有在hitArea Sprite上的鼠標事件都會被傳遞到Sprite上理肺。

2 TouchDelegate

Android中可以通過對View的parent設置TouchDelegate來實現(xiàn)這個功能析蝴,但是必須在代碼中實現(xiàn)懂诗,且一個Parent最多只能有一個TouchDelegate蜓堕,非常不方便抛虏,靈活性也有欠缺。

3 Space + onTouchEvent

Android 4.0引入了Space作為省略繪圖功能的空白區(qū)域套才,它將自身設置為INVISIBLE迂猴,并且重寫了View的draw函數(shù),所以Space比較輕量級背伴,代碼如下:

public final class Space extends View {

    public Space(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        if (getVisibility() == VISIBLE) {
            setVisibility(INVISIBLE);
        }
    }

    /**
     * Draw nothing.
     *
     * @param canvas an unused parameter.
     */
    @Override
    public void draw(Canvas canvas) {
    }
    ...
}

在這個基礎上沸毁,我們重寫Space的onTouchEvent函數(shù)峰髓,同時為了接收到TouchEvent事件,把View設置為VISIBLE息尺,在接收到的事件時做一下坐標轉化并傳遞給目標View携兵,這樣就誕生了Hitarea。

4 如何做坐標的轉化搂誉?

我們知道Hitarea measure后的寬高徐紧,目標View measure后的寬高,利用這個寬高炭懊,生成一個scale矩陣并级,代碼如下:

private void updateTransformMatrix(HitareaDelegate delegate) {
    if ( mTransformMatrix == null ){
        mTransformMatrix = new Matrix();
    }
    View hitarea = delegate.getHitareaView();
    float scaleX = mTargetView.getMeasuredWidth() * 1.0f / hitarea.getMeasuredWidth();
    float scaleY = mTargetView.getMeasuredHeight() * 1.0f / hitarea.getMeasuredHeight();
    mTransformMatrix.setScale(scaleX,scaleY);
}

隨后,對于Android4.0及以上的版本侮腹,MotionEvent有一個MotionEvent#transform方法可以直接完成坐標轉換嘲碧;對于4.0以下版本,用Matrix#mapPoints方法做坐標轉換父阻,然后用MotionEvent#setLocation設置新的坐標點愈涩,代碼如下:

private void transformMotionEvent(MotionEvent event){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        event.transform(mTransformMatrix);
    } else {
        if ( mPointSrc == null ){
            mPointSrc = new float[2];
            mPointDst = new float[2];
        }
        mPointSrc[0] = event.getX();
        mPointSrc[1] = event.getY();
        mTransformMatrix.mapPoints(mPointDst,mPointSrc);
        event.setLocation(mPointDst[0],mPointDst[1]);
    }
}

5 Demo

HitareaPreview.gif

6 用法

6.1 引入庫

compile 'com.asha:hitarealib:0.1'

6.2 Hitarea

目標View和Hitarea可以是同級關系,對Hitarea指定app:targetId=@id/buttonTest即可:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <Button
        android:id="@+id/buttonTest"
        android:text="list view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <com.asha.Hitarea
        app:debug="true"
        app:targetId="@id/buttonTest"
        android:layout_width="match_parent"
        android:layout_height="50dp" />
</FrameLayout>

也可以是比較深層次的關系:

<FrameLayout
    android:layout_marginTop="5dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <com.asha.hitarea.DemoView
        android:id="@+id/test"
        android:background="#CCCCCC"
        android:layout_width="200dp"
        android:layout_height="70dp" />
</FrameLayout>
<com.asha.Hitarea
    app:targetId="@id/test"
    app:debug="true"
    android:layout_width="match_parent"
    android:layout_height="120dp" />

6.3 HitareaWrapper

有時候我們只需要對一個button增加點擊區(qū)域至非,但是父容器是LinaerLayout的情況下非常難把Hitarea區(qū)域與目標View重合钠署,這個時候可以使用HitareaWrapper。HitareaWrapper繼承自RelativeLayout荒椭,布局上靈活自如谐鼎。HitareaWrapper默認會選擇子View中的第一個View作為目標View,用法如下:

<com.asha.HitareaWrapper
        app:debug="true"
        android:layout_marginTop="5dp"
        android:layout_width="200dp"
        android:layout_height="200dp">
    <com.asha.hitarea.DemoView
        android:layout_gravity="center"
        android:background="#CCCCCC"
        android:layout_width="100dp"
        android:layout_height="100dp" />
</com.asha.HitareaWrapper>

當然也可以在HitareaWrapper中包含多個View趣惠,它會尋找所有子View中tag值為@string/tag_hitarea的View作為目標View狸棍,用法如下:

<com.asha.HitareaWrapper
        app:debug="true"
        android:layout_marginTop="5dp"
        android:layout_width="200dp"
        android:layout_height="200dp">
    <com.asha.hitarea.DemoView
        android:tag="@string/tag_hitarea"
        android:layout_gravity="center"
        android:background="#CCCCCC"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    <Button
        android:text="other"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</com.asha.HitareaWrapper>

6.4 Debug Mode

com.asha.Hitareacom.asha.HitareaWrapper都有一個屬性app:debug,如果設置為true味悄,運行時會繪制出Hitarea區(qū)域草戈,方便調(diào)試。

7 Github

https://github.com/ashqal/Hitarea
這個庫非常簡單侍瑟,但是希望對大家有所幫助_

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末唐片,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子涨颜,更是在濱河造成了極大的恐慌费韭,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庭瑰,死亡現(xiàn)場離奇詭異星持,居然都是意外死亡,警方通過查閱死者的電腦和手機弹灭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門督暂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來揪垄,“玉大人,你說我怎么就攤上這事逻翁〖⑴” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵卢未,是天一觀的道長肪凛。 經(jīng)常有香客問我,道長辽社,這世上最難降的妖魔是什么伟墙? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮滴铅,結果婚禮上戳葵,老公的妹妹穿的比我還像新娘。我一直安慰自己汉匙,他們只是感情好拱烁,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著噩翠,像睡著了一般戏自。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伤锚,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天擅笔,我揣著相機與錄音,去河邊找鬼屯援。 笑死猛们,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的狞洋。 我是一名探鬼主播弯淘,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吉懊!你這毒婦竟也來了庐橙?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤借嗽,失蹤者是張志新(化名)和其女友劉穎怕午,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淹魄,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年堡距,在試婚紗的時候發(fā)現(xiàn)自己被綠了甲锡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兆蕉。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖缤沦,靈堂內(nèi)的尸體忽然破棺而出虎韵,到底是詐尸還是另有隱情,我是刑警寧澤缸废,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布包蓝,位于F島的核電站,受9級特大地震影響企量,放射性物質(zhì)發(fā)生泄漏测萎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一届巩、第九天 我趴在偏房一處隱蔽的房頂上張望硅瞧。 院中可真熱鬧,春花似錦恕汇、人聲如沸腕唧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枣接。三九已至,卻和暖如春缺谴,著一層夾襖步出監(jiān)牢的瞬間但惶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工瓣赂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留榆骚,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓煌集,卻偏偏與公主長得像妓肢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子苫纤,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,180評論 25 707
  • 3.4 View詳解 3.10.1 概述 View系統(tǒng)定義了從用戶輸入消息到消息處理的全過程:用戶通過觸摸屏或者鍵...
    jianhuih閱讀 607評論 0 0
  • layout: postdate: 2016-01-08title: Android開發(fā)藝術探索-第三章-View...
    KuTear閱讀 1,890評論 2 18
  • 今天上班碉钠,一個妹妹和我吐槽:昨晚她們部門聚餐,她的領導一直在灌她白酒卷拘,把她給氣死了喊废。她一邊罵罵咧咧,一邊又很無奈栗弟,...
    言吾小姐閱讀 543評論 0 0
  • 腰痛腿麻二十年污筷,遷延不愈路難行。 輾轉求醫(yī)三五家乍赫,療效不佳念俱灰瓣蛀。 他人介紹慕名來陆蟆,手術治療果不凡。 術后三年再無...
    徐一村閱讀 415評論 0 5