[Android]關於Android子view超出父view無法響應點選事件

火車叨位qu發表於2020-10-15

摘要

  • 關於Android子view超出父view點選事件失效問題
  • 例如button超出父佈局之外的點選事件無效

標題首先看一下結構圖

在這裡插入圖片描述

我根佈局用的LinearLayout;
然後巢狀了一個一定高度的LinearLayout;為上圖頂部寬度撐滿父元素的矩形框;稱之為“線布2”;
線布2 裡又水平佈局了兩個線性佈局;
左邊的線性佈局不管; 右邊的線性佈局裡巢狀了4個button按鈕;

現在的問題是:

  1. 超出 線布2 的3個button按鈕無法顯示;
  2. 超出 線布2 的3個button按鈕無法響應點選事件;

對於問題一:

我們想要顯示溢位的3個button按鈕,在 線布2 裡的右佈局中;
所以我們讓這個右佈局能溢位顯示就好了;

相關程式碼

android:clipChildren="false"
android:clipToPadding="false"

官方對於第一行的解釋:

Defines whether a child is limited to draw inside of its bounds or not.
翻譯:定義一個子檢視是否侷限於它的範圍內。
所以我們設定為false,讓子檢視不侷限與自己;

官方對於第二行的解釋:

Defines whether the ViewGroup will clip its drawing surface so as to exclude the padding area.
翻譯:定義ViewGroup是否將剪輯其繪圖表面以排除填充區域。
由於筆者是Android新手,對此表示不太理解,也沒有去研究它
(剛入手Android開發一週,只為做一個作品參加學校比賽,不過這作品也是我用心良苦的設計,歡迎大家點選下方連結體驗^ _ ^);

  • 對此我們解決了第一個問題,不過筆者實驗了一番,發現把上述兩行程式碼加在 線布2 的xml裡,並沒有顯示 線布2 裡溢位的右佈局,也就是說那幾個button按鈕還是看不見;
  • 我搜尋問題時,說是上述兩行程式碼是作用於 孫子檢視 與 兒子檢視;在此不解釋孫子與兒子檢視;
  • 而我的 線布2 的父佈局正是根佈局,也就是說我需要在根佈局中使用這兩個引數,才可以使 線布2 裡的右佈局溢位於 線布2 顯示;
    實驗成功;

筆者專案中,該問題用了一下午才解決,其實主要是首次開發,佈局檔案過於混亂,所以致使上述引數不生效,(但是我在所有佈局標籤加上也不生效,這點很納悶)無奈之下,我把主要的佈局檔案分離開來,再使用include引入;
模組化確實方便,嘻嘻;

對於問題二:

  • 讓溢位的button按鈕可點選
  • 這個問題花費了我半天時間,一直搜找解決方案,遺憾的是,相關問題少,解決方案無用;
  • 所以我嘗試自己解決此問題,可謂是另闢蹊蹺;

先介紹我搜尋的解決方案,在此歸納成兩條:

1. 使用android:focusable="true"引數

android:focusable="true"
其解釋為:是否可聚焦,也是是否可點選
——
我把此引數在所有控制元件及佈局中放了個遍,也無法觸發溢位的按鈕
——
我也搜找到相關的引數,同樣無法點選。
——
我以為是下邊的佈局覆蓋掉了溢位的按鈕
——
然後我使用相對佈局作為根佈局,讓有button的佈局最後繪製,但結果是lose
——
我摸了摸禿頭,發現事態不對勁,遂重建test佈局,測試了一番;
——
發現沒有其他佈局的時候,也點選不了;
——
事情發展到這一步,我想我已經看破紅塵…哦不是看破Layout了、手動滑稽
——
杰倫–結論:
所有溢位父佈局的控制元件,無法響應事件,但通過引數可以顯示;

其實這個結論是我自己臆想的,但是我實在是找不到方法;

  • 這個世界的真理和公理,都是觀物者們眼中的事物;//突然哲學

2. 拒絕使用佈局進行巢狀

  • 這個方案就是取消 線布2 佈局,這樣就沒有佈局去限制 線布2 中的button了;
  • 但是,熱愛模組化的我怎麼會讓button組脫離組織呢;(其實我差點就屈服於這個方案了)
    這種方案就不做詳細解釋;讓我們直接進入下一環:另闢蹊蹺

另闢蹊蹺:

  • 我想著如果能在整個Activity視窗捕捉點選事件,就好辦了;

public boolean onTouchEvent(MotionEvent event);
果然,程式設計師的直覺
——
只需要在Activity程式碼區重寫此方法就好了;
不過他只返回布林值,其值含義為是否觸控了螢幕;
聰明的我怎能讓他只幹這件事;
遂:

@Override
public boolean onTouchEvent(MotionEvent event) {
    //首先定義一個陣列用來接收按鈕的座標xy值
    int[] xy = new int[2];
    
    //獲取按鈕的top/left xy值
    //button變數我在onCreat()函式中已經獲取了控制元件,具體按實際情況寫
    button.getLocationOnScreen(xy);

	//再定義一個陣列用來計算控制元件的bottom/right xy值
    int[] xy_end = new int[2];
    xy_end[0] = buttom.getWidth() + xy[0];
    xy_end[1] = buttom.getHeight() + xy[1];
	//現在我們已經得到了按鈕的左上座標和右下座標
	//兩個點可以確定一個矩形嘛

	//event裡包含了點選的資訊;
	//我們判斷點選的座標是否在按鈕座標內,實際就是判斷點選的xy值是否在上述矩形中;
    if (event.getX() >= xy[0] && event.getX() <= xy_end[0]
        && event.getY() >= xy[1] && event.getY() <= xy_end[1]) {
        //如果是,那麼就執行裡邊的程式碼,在這裡我們可以callOnClick()按鈕

		//這裡的程式碼說明
		//實際體驗了一番,發現輕點一下和長按均可以啟用按鈕;
		//但是,我的按鈕擁有animate()事件,所以連續點選會在動畫未完成時再次點選按鈕,
		//所以我做了個判斷,讓動畫未完成時不再執行點選,機制如我
		//實際中,讀者完全不用這兩行程式碼
		//讓我看看有哪些讀者看都不看直接複製程式碼--手動滑稽
		//雖說站在巨人肩膀上,但是也要搞懂其原理才不會摔下來。
        if (isMoreShow == false && xy[0] >= button.getHeight())
            return false;

		//我們callOnClick了按鈕,也就是模擬點選了按鈕;
        button.callOnClick();
        return false;
    }

    return super.onTouchEvent(event);
}
  • 就這短短几行程式碼,搞了我半天的心態,嚴格說還有一個晚上;

不足:

  • 不足之處還是有的
  1. 如果按鈕過多,就需要寫入更多的判斷,這非常的不優雅;可是總比無法點選要好;
  2. 如果按鈕有自定義點選背景(按下背景),將不顯示,身為強迫症的我怎麼能忍;
  3. 依舊沒有女朋友emmm;

展示:

在這裡插入圖片描述

結語

  • 軟體地址下載地址
  • 個人GitHub地址Fc-404
  • 同時筆者目前是在校應屆生,座標西安,外出找工作全是招聘轉招生,筆者心很累,就留校繼續學習技術,如有哪位老闆願意帶帶我,請發郵箱:2601721443@qq.com 或 gjl245869@gmail.com
  • 個人簡歷連結:https://pan.baidu.com/s/1cX6TC6iOGbQdoz9wiqEvLA
    提取碼:2333

相關文章