概述

#

ScrollBehavior 現在會在桌面平臺(Mac、Windows 和 Linux)上自動為滾動控制元件應用 Scrollbar

背景

#

在此更改之前,Scrollbar 需要由開發者在所有平臺上手動應用於滾動控制元件。這與使用者在桌面平臺上執行 Flutter 應用程式時的預期不符。

現在,繼承的 ScrollBehavior 會自動將 Scrollbar 應用於大多數滾動控制元件。這類似於 ScrollBehavior 建立 GlowingOverscrollIndicator 的方式。少數豁免此行為的控制元件列在下方。

為了更好地管理和控制此功能,ScrollBehavior 也得到了更新。用於應用 GlowingOverscrollIndicatorbuildViewportChrome 方法已被棄用。取而代之的是,ScrollBehavior 現在支援用於裝飾視口的獨立方法:buildScrollbarbuildOverscrollIndicator。可以覆蓋這些方法來控制滾動區域周圍的內容。

此外,ScrollBehavior 的子類 MaterialScrollBehaviorCupertinoScrollBehavior 已公開,允許開發者擴充套件和構建框架中其他現有的 ScrollBehavior。這些子類以前是私有的。

變更說明

#

以前的方法要求開發者在所有平臺上建立自己的 Scrollbar。在某些用例中,需要將 ScrollController 提供給 Scrollbar 和滾動控制元件。

dart
final ScrollController controller = ScrollController();
Scrollbar(
  controller: controller,
  child: ListView.builder(
    controller: controller,
    itemBuilder: (BuildContext context, int index) {
      return Text('Item $index');
    }
  )
);

ScrollBehavior 現在在桌面平臺上執行時會自動應用 Scrollbar,併為您處理將 ScrollController 提供給 Scrollbar 的操作。

dart
final ScrollController controller = ScrollController();
ListView.builder(
  controller: controller,
  itemBuilder: (BuildContext context, int index) {
   return Text('Item $index');
 }
);

框架中的一些控制元件豁免了此自動 Scrollbar 應用。它們是:

  • EditableText,當 maxLines 為 1 時。
  • ListWheelScrollView
  • PageView
  • NestedScrollView

由於這些控制元件手動覆蓋了繼承的 ScrollBehavior 以移除 Scrollbar,因此所有這些控制元件現在都具有 scrollBehavior 引數,以便可以提供一個來代替覆蓋。

此更改在開發過程中沒有導致任何測試失敗、崩潰或錯誤訊息,但如果您正在桌面平臺上手動新增 Scrollbar,則可能會導致應用程式中渲染兩個 Scrollbar

如果您在應用程式中看到此情況,有幾種方法可以控制和配置此功能。

  • 在桌面執行時,從應用程式中移除手動應用的 Scrollbar

  • 擴充套件 ScrollBehaviorMaterialScrollBehaviorCupertinoScrollBehavior 來修改預設行為。

    • 有了您自己的 ScrollBehavior,您可以透過設定 MaterialApp.scrollBehaviorCupertinoApp.scrollBehavior 將其應用於整個應用程式。
    • 或者,如果您只想將其應用於特定元件,請在相關元件上方新增一個 ScrollConfiguration,並使用您的自定義 ScrollBehavior

您的滾動控制元件將繼承此設定並反映此行為。

  • 與建立自己的 ScrollBehavior 不同,更改預設行為的另一種選擇是複製現有的 ScrollBehavior,然後切換所需的設定。
    • 在您的元件樹中建立一個 ScrollConfiguration,並使用 copyWith 提供當前上下文中現有 ScrollBehavior 的修改副本。

遷移指南

#

移除桌面上手動 Scrollbar

#

遷移前的程式碼

dart
final ScrollController controller = ScrollController();
Scrollbar(
  controller: controller,
  child: ListView.builder(
    controller: controller,
    itemBuilder: (BuildContext context, int index) {
      return Text('Item $index');
    }
  )
);

遷移後的程式碼

dart
final ScrollController controller = ScrollController();
final Widget child = ListView.builder(
  controller: controller,
  itemBuilder: (BuildContext context, int index) {
    return Text('Item $index');
  }
);
// Only manually add a `Scrollbar` when not on desktop platforms.
// Or, see other migrations for changing `ScrollBehavior`.
switch (currentPlatform) {
  case TargetPlatform.linux:
  case TargetPlatform.macOS:
  case TargetPlatform.windows:
    return child;
  case TargetPlatform.android:
  case TargetPlatform.fuchsia:
  case TargetPlatform.iOS:
    return Scrollbar(
      controller: controller,
      child: child;
    );
}

為應用程式設定自定義 ScrollBehavior

#

遷移前的程式碼

dart
// MaterialApps previously had a private ScrollBehavior.
MaterialApp(
  // ...
);

遷移後的程式碼

dart
// MaterialApps previously had a private ScrollBehavior.
// This is available to extend now.
class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // Override behavior methods like buildOverscrollIndicator and buildScrollbar
}

// ScrollBehavior can now be configured for an entire application.
MaterialApp(
  scrollBehavior: MyCustomScrollBehavior(),
  // ...
);

為特定元件設定自定義 ScrollBehavior

#

遷移前的程式碼

dart
final ScrollController controller = ScrollController();
ListView.builder(
  controller: controller,
  itemBuilder: (BuildContext context, int index) {
   return Text('Item $index');
 }
);

遷移後的程式碼

dart
// MaterialApps previously had a private ScrollBehavior.
// This is available to extend now.
class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // Override behavior methods like buildOverscrollIndicator and buildScrollbar
}

// ScrollBehavior can be set for a specific widget.
final ScrollController controller = ScrollController();
ScrollConfiguration(
  behavior: MyCustomScrollBehavior(),
  child: ListView.builder(
    controller: controller,
    itemBuilder: (BuildContext context, int index) {
     return Text('Item $index');
    }
  ),
);

複製並修改現有 ScrollBehavior

#

遷移前的程式碼

dart
final ScrollController controller = ScrollController();
ListView.builder(
  controller: controller,
  itemBuilder: (BuildContext context, int index) {
   return Text('Item $index');
 }
);

遷移後的程式碼

dart
// ScrollBehavior can be copied and adjusted.
final ScrollController controller = ScrollController();
ScrollConfiguration(
  behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
  child: ListView.builder(
    controller: controller,
    itemBuilder: (BuildContext context, int index) {
     return Text('Item $index');
    }
  ),
);

時間線

#

已登陸版本:2.2.0-10.0.pre
穩定版釋出:2.2.0

參考資料

#

API 文件

相關問題

相關 PR