platty

Flutter 不会尝试为特定平台提供熟悉的控件(与 React Native、ionic 和其他跨平台工具不同)。这对于所有平台上的统一渲染、最大的灵活性以及消除为每个平台进行测试和调试的整个类别的问题具有巨大的好处。虽然这很棒,但在许多场景下我们希望我们的应用程序看起来和感觉都像 Android 或 iOS 应用程序。Platty 允许您通过最小的努力和最大的控制在一个统一的 API 中渲染类似 iOS(Cupertino)和 Android(Material)的控件。

不再需要在渲染块中检查平台以渲染 CupertinoButton 或 FlatButton,让 platty 为您处理逻辑!想在您的应用程序中使用底部标签页,这些标签页会解析为特定于平台的 UI?没问题!

入门

使用 platty 来统一渲染特定于平台的 API。该库利用 BuildContext 主题 API 将平台
信息传播到 Widgets。

默认情况下,所有小部件都符合默认的 TargetPlatform。它会查找其默认的 Theme.of(context).platform
同样,所有小部件都提供一个 renderPlatform 属性,允许您选择要渲染的那个(如果您愿意)。

MaterialAppCupertinoApp 替换为 PlatformApp


class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return PlatformApp(
      title: 'Flutter Demo',
      // specify our app theme here. We do the leg work of bridging it to Cupertino.
      unifiedTheme: ThemeData(
            primarySwatch: Colors.lightBlue,
            bottomAppBarColor: Colors.red,
          ),
      home: ExamplePage(),
    );
  }
}

PlatformApp 统一了 MaterialAppCupertinoApp 之间的所有相同属性,以便在层次结构中同时存在这两种小部件实例,并
根据平台切换样式。

现在,您可以用我们库中包含的 "P" 对应物替换小部件

Button/CupertinoButton -> PButton

Material Raised Button
Cupertino Button

来源

FlatButton/CupertinoButton -> PFlatButton

Material Flat Button
Cupertino Flat Button

来源

AppBar/CupertinoNavigationBar -> PNavigationBar

Android Nav
iOS Nav

来源

SliverAppBar/CupertinoSliverNavigationBar -> PSliverNavigationBar

Slider/CupertinoSlider -> PSlider

Sliders

来源

Switch/CupertinoSwitch -> PSwitch

Switch

来源

BottomNavigationBar/CupertinoTabBar -> PTabBar

Bottom Navigation Android
Bottom Navigation iOS

来源

Scaffold/CupertinoScaffold -> PScaffold

CircularProgressIndicator/CupertinoActivityIndicator -> PActivityIndicator

Progress

来源

BackButton/CupertinoNavigationBarBackButton -> PBackButton

AlertDialog/CupertinoAlertDialog -> PAlertDialog

Android Alert

来源

特定于平台的属性带有前缀

任何具有 iOS 特定或 Android 特定对应项的小部件,它们会相应地被加上 android/ios 前缀

例如,PButtonandroidShape 适用于 RaisedButton.shape 属性。在 CupertinoButton 上不存在。
但是 CupertinoButton 有一个 borderRadiuspressedOpacity。这两个属性变成了 iosBorderRadiusiosPressedOpacity

助手

此库捆绑了一些标准函数,可以轻松返回特定于平台的代码。而不是检查
并切换 Theme.of(context).targetPlatform 的结果,请使用以下方法

特定平台实例

要让特定的 P-Widget 只使用特定的平台主题,例如 Material 或 Cupertino,您可以将其包装在
PTheme 实例中

PTheme(
  data: PThemeData(
    platform: TargetPlatform.android,  // or iOS
    child: child,
  ),
);

或者,更简单地,使用助手方法

PTheme.ios(child);
PTheme.android(child);

同样,所有 P-Widgets 和方法都允许您使用构造函数中的 renderPlatform 参数来覆盖 PTheme
或调用方法

PButton("Hello Android", 
  renderPlatform: TargetPlatform.Android,
)

这将把渲染切换到此特定小部件的 Material 小部件。

注意:使用 PTheme 包装小部件会将该实例传播到小部件的层次结构中,因此比
为每个单独的小部件手动指定 renderPlatform 效果更好。

创建您自己的平台适应性小部件

我们可以扩展此库中包含的逻辑来构建我们自己强大的平台适应性小部件。
库中包含 PlatformAdaptingWidget 基类,它继承自 StatelessWidget

class SamplePlatformWidget extends PlatformAdaptingWidget {
  final Color color;

  SamplePlatformWidget({Key key, @required this.color, TargetPlatform renderPlatform}) // should allow consumers to choose TargetPlatform
      : super(key: key, renderPlatform: renderPlatform);

  /// Render a material widget here. Most Material widgets require a Material Theme instance above it.
  @override
  get renderMaterial => (BuildContext context) {
        return BackButton(
          color: color,
        );
      };

  /// Render a cupertino widget here.
  @override
  get renderCupertino => (BuildContext context) {
        return CupertinoNavigationBarBackButton(
          color: color,
        );
      };
  
  /// Render a fuchsia widget here. (defaults to material)
    @override
    get renderFuchsia => (BuildContext context) {
          return BackButton(
            color: color,
          );
        };
}

平台特定的逻辑

此库提供了几种实现基于平台行为的标准方法。
您可以使用 platformWrap,它允许您指定一个 child,并在 1 个或所有平台上将其包装
在另一个小部件中

platformWrap(
      context,
      child: PButton(
        padding: EdgeInsets.all(0.0),
        child: Text(title),
        color: Colors.red,
        onPressed: () {
          Navigator.push(context, PlatformRoute.of(context, builder: page));
        },
      ),
      renderCupertino: (context, child) => Padding(
            padding: EdgeInsets.only(bottom: 8.0),
            child: child,
          ),
    );

您可以指定 renderCupertinorenderMaterialrenderFuschia(或都不指定)。
任何未指定的渲染方法都默认为 child

同样,platformSelect 是一个助手,它能够以统一的方式返回基于平台的不同对象。
在我们的 PlatformAdaptingWidget 中,我们使用它来根据平台返回不同的小部件。您可以使用它来返回任何
基于平台的返回类型


Column(
  children: [
    platformSelect(context, 
      renderMaterial: (context) => Text("I am android"),
      renderCupertino: (context) => Text("I am iOS"),
      renderFuchsia: (context) => Text("I am FUCHSIA")) 
  ],
),

renderMaterialrenderCupertino 是必需的。renderFuchsia 默认为 material。

或者您可以返回非小部件

Column(
  children: [
    Text(platformSelect(context, 
      renderMaterial: (context) => "I am android"),
      renderCupertino: (context) => "I am iOS",
      renderFuchsia: (context) => "I am FUCHSIA")) 
  ],
),

GitHub

https://github.com/fuzz-productions/platty