這篇文章主要為大家展示了“Android如何擴大View的點擊區(qū)域”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Android如何擴大View的點擊區(qū)域”這篇文章吧。
創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站制作、成都做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè)、金城江網(wǎng)絡(luò)推廣、重慶小程序開發(fā)公司、金城江網(wǎng)絡(luò)營銷、金城江企業(yè)策劃、金城江品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供金城江建站搭建服務(wù),24小時服務(wù)熱線:18982081108,官方網(wǎng)址:chinadenli.net
為了更清楚的說明整個機制,采用如下的視圖來說明點擊的事件分發(fā)機制。下圖是一個 FrameLayout (ViewGroup) 里面包含著一個 ImageView (View)。

先自定義一個 MyFrameLayout,繼承FrameLayout,并實現(xiàn)兩個點擊相關(guān)的接口;具體代碼如下:
public class MyFrameLayout extends FrameLayout implements OnClickListener, OnTouchListener {
private static final String TAG = "Event";
public MyFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(TAG, "MyFrameLayout init");
setOnClickListener(this);
setOnTouchListener(this);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d(TAG, "MyFrameLayout dispatchTouchEvent " + event.getAction());
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "MyFrameLayout onTouchEvent " + event.getAction() );
return super.onTouchEvent(event);
}
@Override
public void onClick(View view) {
Log.d(TAG, "MyFrameLayout onClick");
}
@Override
public boolean onTouch(View view, MotionEvent event) {
Log.d(TAG, "MyFrameLayout onTouch " + event.getAction());
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "MyFrameLayout onInterceptTouchEvent " + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
}接著,對于 ImageView 也做類似的操作,具體代碼如下:
public class MyImageView extends ImageView implements OnClickListener, OnTouchListener {
private static final String TAG = "Event";
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(TAG, "MyImageView init");
setOnClickListener(this);
setOnTouchListener(this);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d(TAG, "MyImageView dispatchTouchEvent "+ event.getAction());
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "MyImageView onTouchEvent "+ event.getAction());
return super.onTouchEvent(event);
}
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
Log.d(TAG, "MyImageView onTouch " + arg1.getAction());
return false;
}
@Override
public void onClick(View arg0) {
Log.d(TAG, "MyImageView onClick");
}
}這里要說明的是,只有ViewGroup才有 onInterceptTouchEvent 方法的,普通的 View 是沒有的,它是不能對事件進行攔截的。
那這時候,如果我們點擊里面的 ImageView,會有怎樣的輸出呢?結(jié)果如下圖。

那如果點擊外層呢?

0,1,2分別是代表 ACTION_DOWN,ACTION_UP,ACTION_MOVE;從中也可以看出一個點擊動作包含一個Down,一個Up,還有多個Move操作。
再來看一段源碼:
public boolean dispatchTouchEvent(MotionEvent ev){
boolean consume = false;
if(onInterceptTouchEvent(ev)){
consume = onTouchEvent(ev);
} else{
consume = child.dispatchTouchEvent(ev);
}
return consume;
}上述的代碼把三者的關(guān)系說得很清楚了,對于一個對于一個 ViewGroup 來說,點擊事件產(chǎn)生后,首先會傳遞給它,這時候會調(diào)用 dispatchTouchEvent,如果這個 ViewGroup 的 onInterceptTouchEvent 返回 true ,則表示它要攔截該事件,也就會交給它的 onTouchEvent 來進行處理。如果這個 ViewGroup 的 onInterceptTouchEvent 返回 false 則會傳給子元素,子元素的 dispatchTouchEvent 就會被調(diào)用,如此反復(fù)循環(huán)。這與上面一張圖打出的結(jié)果是一致的。
這里還有說明的是,如果代碼設(shè)置了 OnTouchListener,那么就會先調(diào)用 onTouch 方法,然后在調(diào)用 onTouchEvent。OnClickListener 是優(yōu)先級最低的,所以最后才會調(diào)用 onClick。
因此,從第二張結(jié)果圖也可以看出,當存在 onTouch 之后,onTouchEvent 和 onClick 兩個方法都不會在調(diào)用了。
相信到這里,大家對于View的事件分發(fā)機制有一定的了解了。
這里回到開頭提的那個問題,那么有什么辦法可以擴大 View 的點擊區(qū)域呢?
答案:在父 View 設(shè)置 OnTouchListener 對點擊事件進行攔截,通過判斷點擊的位置,來決定是相應(yīng)子 View 的事件,還是父 View 的事件。
具體實現(xiàn)代碼如下:
public class TouchFactory {
/** 擴展垂直方向點擊區(qū)域尺寸 */
private static final int EXT_V_SIZE = 200;
public static View.OnTouchListener creatTouchListener(){
return new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (expendTouchSize(v, event)) {
return true;
}
return false;
}
};
}
public static boolean expendTouchSize(View root, MotionEvent event) {
if (root instanceof MyFrameLayout) {
ImageView view = ((MyFrameLayout) root).getMyImageView();
if (view != null && view.getVisibility() == View.VISIBLE) {
Rect touchRect = new Rect();
view.getGlobalVisibleRect(touchRect);
int action = event.getAction();
float x = event.getRawX();
float y = event.getRawY();
if ((y >= touchRect.top - EXT_V_SIZE) && (y <= touchRect.bottom + EXT_V_SIZE)) {
if (x >= touchRect.left) {
if (action == MotionEvent.ACTION_UP) {
Toast.makeText(view.getContext(), "touch", Toast.LENGTH_SHORT).show();
}
return true;
}
}
}
}
return false;
}
}TouchFactory 對點擊事件進行了封裝,并通過對點擊區(qū)域的判斷,來決定要不要攔截點擊事件。
下面是 MyFrameLayout 的具體實現(xiàn)。由于是一個自定義 view, 因此,變量 myImageView 是一定為空的,所以要對其進行賦值。
public class MyFrameLayout extends FrameLayout {
private static final String TAG = "Event";
private MyImageView myImageView;
public MyFrameLayout(Context context) {
this(context, null);
}
public MyFrameLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyFrameLayout(Context context, AttributeSet attrs, int def) {
super(context, attrs, def);
init();
}
public void init() {
this.setOnTouchListener(TouchFactory.creatTouchListener());
}
public MyImageView getMyImageView() {
if (myImageView == null) {
myImageView = findViewById(R.id.mImage);
}
return myImageView;
}
}注意事項: 當對子 View 設(shè)置 OnClickListener,點擊區(qū)域剛好是子 View 內(nèi)部的時候,就會消耗此事見,父 View 的攔截處理就無效了,因此,一旦選擇攔截來擴大點擊區(qū)域,就不要再去子 View 設(shè)置點擊回調(diào)來消耗點擊事件了。
以上是“Android如何擴大View的點擊區(qū)域”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
本文題目:Android如何擴大View的點擊區(qū)域
鏈接地址:http://chinadenli.net/article2/jpsgoc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、服務(wù)器托管、關(guān)鍵詞優(yōu)化、ChatGPT、網(wǎng)站設(shè)計、網(wǎng)站維護
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)