#Flutter手勢中的 Behavior

Flutter手勢中的behavior

前言:本雜文的閱讀者需要掌握Flutter界面布局基本技巧,會使用Widget組合界面,否則無法理解下文。

Flutter中的手勢事件Widget包括:Listener(監(jiān)聽觸摸,鼠標事件),MouseRegion(監(jiān)聽鼠標部分事件) 兩大基本類。

我們今天所說的behaivor屬性是HitTestBehavior,控制手勢點擊測試行為。它是一個枚舉。

/// How to behave during hit tests.
enum HitTestBehavior {
  /// Targets that defer to their children receive events within their bounds
  /// only if one of their children is hit by the hit test.
  deferToChild,

  /// Opaque targets can be hit by hit tests, causing them to both receive
  /// events within their bounds and prevent targets visually behind them from
  /// also receiving events.
  opaque,

  /// Translucent targets both receive events within their bounds and permit
  /// targets visually behind them to also receive events.
  translucent,
}
  • deferToChild:在子widget中點擊測試,有且只有一個子widget測試成功后,表明當(dāng)前Listener widget點擊測試成功,這是默認行為。

  • opaque :Listener 無條件點擊測試成功。子Widget 依然會先參與點擊測試,所以有整個區(qū)域都點擊測試成功的現(xiàn)象,點擊子Widget沒有占據(jù)的空白位置時,也會促發(fā)Listener手勢回調(diào)。

  • translucent:

    1. Listener無條件添加到響應(yīng)鏈中。
    2. Listener的子Widget 依然會參與點擊測試。
    3. 假設(shè)
      a . Listener點擊測試失敗.
      b. Listener還有兄弟Widget.
      c. 且點擊位置剛好也在Listener兄弟Widget大小范圍內(nèi).
      則依次尋找兄弟Widget是否能點擊測試成功,此場景也就是Stack 布局了多個Listener 子widget,產(chǎn)生一種點擊穿透的現(xiàn)象。上層的Listener設(shè)置behaivor為HitTestBehavior. translucent,底層的Listener設(shè)置behaivor為HitTestBehavior. deferToChild或者HitTestBehavior.opaque,當(dāng)點擊上層Listener時,有兩種情況:
      a.上層Listener的子Widget點擊測試成功,則直接返回,只有上層Listener響應(yīng)。
      b.如果上層Listener的子Widget點擊測試失敗,比如:點擊到了子widget沒有占有的“空白位置”,則上層Listener無法點擊測試成功,根據(jù)Stack的點擊測試規(guī)則:依次點擊測試子widget,直到有子widget點擊測試成功。那么下層Listener就有機會參與點擊測試,依此類推,那就形成了點擊穿透現(xiàn)象。

說明:此處的“空白位置”也就是FlutterChina中第八章中提到的“透明區(qū)域”,“透明區(qū)域”有些概念模糊。我已提出建議改成 hitTest測試失敗的組件,有人說按照“空白位置”的說法,這不是也不對嗎,其實不然,hitTest測試失敗的組件其實就是指的上層Listener組件,點擊測試失敗?!翱瞻孜恢谩笔窃贚istener內(nèi)部范圍說的概念,指Listener的子Widget沒有占據(jù)的范圍,解釋范圍不一樣。如果你在Listener內(nèi)部添加了等大小的透明mask 組件,比如透明的DecoratedBox,但是DecoratedBox點擊測試成功,這就無法實現(xiàn)translucent的點擊穿透的效果。

附上Listener 點擊測試相關(guān)源碼可以理解更透測:

  @override
  bool hitTest(BoxHitTestResult result, { Offset position }) {
    bool hitTarget = false;
    if (size.contains(position)) {
      hitTarget = hitTestChildren(result, position: position) || hitTestSelf(position);
      if (hitTarget || behavior == HitTestBehavior.translucent)
        result.add(BoxHitTestEntry(this, position));
    }
    return hitTarget;
  }

  @override
  bool hitTestSelf(Offset position) => behavior == HitTestBehavior.opaque;

說明:hitTarget,就是表明是否測試成功。首先得點擊Position 在Size范圍內(nèi)。然后優(yōu)先看子Widget是否點擊測試成功,不成功再看hitTestSelf 是否成功,此處就是 behavior == HitTestBehavior.opaque 就返回成功,對應(yīng)我們所說無條件點擊測試成功。
再就是根據(jù)hitTarget測試結(jié)果判斷是否把當(dāng)前Listener添加到相應(yīng)鏈result中,如果hitTarget == false,則判斷behavior 是否為 HitTestBehavior.translucent,若是則也添加到響應(yīng)鏈中,但是卻返回點擊測試失敗,這就和上面介紹的translucent相符。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容