Android -- TouchDelegate

設計規定

Android4.0設計規定的有效可觸摸的UI元素標準是48dp,這是一個用戶手指能準確而且溫馨觸摸的區域。java

以下圖所示,你的UI元素可能小於48dp,圖標僅有32dp,按鈕僅有40dp,可是他們的實際可操做焦點區域最好都應達到48dp的大小。android

TouchDelegate

假設有兩個View,分別是v1,v2,咱們能夠經過v1的setTouchDelegate(bounds, v2)來委派觸摸事件,其中bounds是一個Rect。v1中,落在這個範圍的TouchEvent都會傳給v2。ide

解決

爲使小的UI區域得到良好的觸摸交互,根據View的特性,目前碰到了兩種狀況:post

  1. 如ImageView,設置其padding值,可觸摸區域將向外擴展;
  2. 如Button,設置其padding值,可觸摸區域不變,其內內容顯示區域向內壓縮;

狀況1的控件,可直接設置其padding值達到目的,如 android:padding="10dp"  .net

狀況2的控件,可以使用TouchDelegate動態修改其觸摸區域,達到擴大點擊範圍的效果設計

/** 
     * 擴大View的觸摸和點擊響應範圍,最大不超過其父View範圍 
     *  
     * @param view 
     * @param top 
     * @param bottom 
     * @param left 
     * @param right 
     */  
    public static void expandViewTouchDelegate(final View view, final int top,  
            final int bottom, final int left, final int right) {  

        ((View) view.getParent()).post(new Runnable() {  
            @Override  
            public void run() {  
                Rect bounds = new Rect();  
                view.setEnabled(true);  
                view.getHitRect(bounds);  

                bounds.top -= top;  
                bounds.bottom += bottom;  
                bounds.left -= left;  
                bounds.right += right;  

                TouchDelegate touchDelegate = new TouchDelegate(bounds, view);  

                if (View.class.isInstance(view.getParent())) {  
                    ((View) view.getParent()).setTouchDelegate(touchDelegate);  
                }  
            }  
        });  
    }

採起此種方法的兩點注意:rest

  1. 若View的自定義觸摸範圍超出Parent的大小,則超出的那部分無效。
  2. 一個Parent只能設置一個View的TouchDelegate,設置多個時只有最後設置的生效。若是但願一個view能設置多個委派,須要再自定義parent,具體方法可參考:http://cyrilmottier.com/2012/02/16/listview-tips-tricks-5-enlarged-touchable-areas/

若須要恢復該View的觸摸範圍:code

/** 
     * 還原View的觸摸和點擊響應範圍,最小不小於View自身範圍 
     *  
     * @param view 
     */  
    public static void restoreViewTouchDelegate(final View view) {  

        ((View) view.getParent()).post(new Runnable() {  
            @Override  
            public void run() {  
                Rect bounds = new Rect();  
                bounds.setEmpty();  
                TouchDelegate touchDelegate = new TouchDelegate(bounds, view);  

                if (View.class.isInstance(view.getParent())) {  
                    ((View) view.getParent()).setTouchDelegate(touchDelegate);  
                }  
            }  
        });  
    }

使用TouchDelegate擴大View的觸摸響應範圍是一種比較靈活的方法,有時可與設置padding的方式結合使用。blog

使用post runnable的方式去設置Delegate區域大小的緣由是,如該View是在Activity的OnCreate()或Fragment的OnCreateView()中繪製,此時UI界面還沒有開始繪製,沒法得到正確的座標;事件

若將此法應用在ListView的getView()中繪製每一個ItemView時,則Delegate的設置將部分失效,緣由是ListView的繪製較特殊,可能沒法獲取到部分還未繪製出的View的正確座標,能夠參考:http://cyrilmottier.com/2012/02/16/listview-tips-tricks-5-enlarged-touchable-areas/

我是天王蓋地虎的分割線

參考:http://blog.csdn.net/sgwhp/article/details/10963383

相關文章
相關標籤/搜索