Flutter 中 GestureDetector 的使用誤區

在實際開發中,我們通常需要實現某個組件的更多點擊事件。比如:原生的RaisedButton組件是無法響應諸如拖拽或是按下、抬起等細化的動作,它只有一個onPressed()方法來表示。當我們想實現這些細化事件時,通常使用的組件是GestureDetector。
我們先來看下面這段代碼:

GestureDetector(
    onTap: () {
        debugPrint("RaisedButton點擊阻斷");
    },
    child: RaisedButton(
    child: Text("點我試試"),
    onPressed: () {
        debugPrint("我被點擊了");
    })
)

各位覺得這端代碼的運行結果,當RaisedButton被點擊時,控制台將如何輸出呢?
再看下面這段代碼:

GestureDetector(
	behavior: HitTestBehavior.opaque,
    onTap: () {
        debugPrint("RaisedButton點擊阻斷");
    },
    child: RaisedButton(
    child: Text("點我試試"),
    onPressed: () {
        debugPrint("我被點擊了");
    })
)

和上面的問題一樣,當RaisedButton被點擊時,控制台將輸出什麼內容呢?
答案無一例外地,都輸出:

我被點擊了

可以看到,單純地使用GestureDetector並不能將子組件的點擊事件阻斷,即使添加了behavior,也無能為力。
所以,我們得到結論:當子組件可響應點擊事件時,GestureDetector是不能阻斷子組件響應點擊事件的
那麼,如果我們想阻斷子組件對點擊事件的響應,該怎麼辦呢?
正確的做法是:使用AbsorbPointer組件
我們來看下面這段代碼:

AbsorbPointer(
    child: RaisedButton(
    child: Text("點我試試"),
    onPressed: () {
        debugPrint("我被點擊了");
    })
)

再次點擊RaisedButton,控制台將不輸出任何內容。
那麼?如何讓GestureDetector可以作用在RaisedButton上呢?很簡單,只需要將RaisedButton變為不可響應點擊事件就可以了,其他控件同理。實現代碼如下:

GestureDetector(
    behavior: HitTestBehavior.opaque,
    onTap: () {
        debugPrint("RaisedButton點擊阻斷");
    },
    child: AbsorbPointer(
        child: RaisedButton(
        child: Text("點我試試"),
            onPressed: () {
                debugPrint("我被點擊了");
            }
        )
    )
)

再次點擊RaisedButton,控制台將輸出:

RaisedButton點擊阻斷

當然,如此一來,原有的按鈕點擊動畫也會失效。