Flutter工作生活

一种flutter应用的跨平台适配解决方案

2019-07-03  本文已影响352人  buaashuai

采用flutter开发APP已经1年多了,平时开发的过程中踩过很多坑,今天想分享一个flutter应用跨平台适配的解决方案,目的是让你的flutter应用可以灵活高效的自动适配各种平台,实现UI最大化复用,业务逻辑代码在不同平台间能够共享。

下图描述了flutter-adapter的整体实现方案,我们在APP的入口处设置当前APP所运行的平台,这个平台可以在实际使用的时候动态设置,然后对于每个widget,我们只需要实现特定平台的样式适配即可。个别widget在不同平台的表现可能仅仅是部分属性的数值不同而已,对于属性值的垮平台适配我们提供了一个通用的函数superObjectAdapter去解决这个问题。

flutter-adapter跨平台解决方案

不同平台适配效果

手机 平板竖屏 平板横屏

使用方式

flutter_adapter插件内置了3类平台,分别是:手机(TEAdaptPlatform.phone)、pad横屏(TEAdaptPlatform.padLandscape)、pad竖屏(TEAdaptPlatform.padPortrait)
。如果你只适配部分平台,那么只需要对待适配的widget实现特定平台的build函数即可,其他未适配的平台默认会返回Phone的样式。

使用的时候只需要在APP的入口处采用ScreenAdaptWidget,然后设置当前APP需要适配的平台名称即可。

如果你需要扩展适配的平台,对于StatelessWidget只需要实现一个继承自FlexibleStatelessWidget的抽象类,然后实现新平台的build函数并注册该平台即可;对于StatefulWidget只需要实现一个继承自FlexibleState的抽象类,然后实现新平台的build函数并注册该平台即可。

插件使用示例:

ScreenAdaptWidget(
    platform: TEAdaptPlatform.phone.toString(),
    child: 任意widget
)),

如果你的某个StatelessWidget需要适配特定平台,只需要将该widget继承自FlexibleStatelessWidget,然后实现特定平台的build函数即可。

StatelessWidget适配示例:

class MyStatelessPage extends FlexibleStatelessWidget {

  @override
  Widget buildPhone(BuildContext context) {
    return Text('Phone',style: TextStyle(fontSize: 18.0),);
  }

  @override
  Widget buildPadPortrait(BuildContext context) {
    return Text('PadPortrait',style: TextStyle(fontSize: 22.0),);
  }

  @override
  Widget buildPadLandscape(BuildContext context) {
    return Text('PadLandscape',style: TextStyle(fontSize: 30.0),);
  }
}

StatefulWidget适配示例:

如果你的某个StatefulWidget需要适配特定平台,只需要将该StatefulWidget对应的的State继承自FlexibleState,然后实现特定平台的build函数即可,例如:

class MyStatefulPageState extends FlexibleState<MyStatefulPage> {

  @override
  Widget buildPhone(BuildContext context) {
    return Text('Phone',style: TextStyle(fontSize: 18.0),);
  }

  @override
  Widget buildPadPortrait(BuildContext context) {
    return Text('PadPortrait',style: TextStyle(fontSize: 22.0),);
  }

  @override
  Widget buildPadLandscape(BuildContext context) {
    return Text('PadLandscape',style: TextStyle(fontSize: 30.0),);
  }
}

普通Widget适配示例:

如果你的某个widget仅仅需要在不同平台中改变个别属性的值,那么只需要对特定的属性值进行跨平台适配即可,flutter_adapter提供了superObjectAdapter函数来解决属性值的跨平台适配难题。

class MyNormalPage extends StatelessWidget {
  final String textStr;

  MyNormalPage(this.textStr);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('page normal'),
      ),
      body: Column(
        children: <Widget>[
          Container(
            padding: EdgeInsets.all(10.0),
            margin: EdgeInsets.only(bottom: 30.0),
            width: double.infinity,
            height: 100.0,
            color: superObjectAdapter(context, {TEAdaptPlatform.phone.toString(): Colors.yellow, TEAdaptPlatform.padPortrait.toString(): Colors.greenAccent}),
            child: Center(
              child: Text(
                '$textStr ${superObjectAdapter(context, {
                  TEAdaptPlatform.phone.toString(): "[Phone]",
                  TEAdaptPlatform.padPortrait.toString(): "[PadPortrait]"
                })}',
                style: TextStyle(
                    fontSize: superObjectAdapter(context, {TEAdaptPlatform.phone.toString(): 18.0, TEAdaptPlatform.padPortrait.toString(): 38.0}),
                    color: Colors.black),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
属性跨平台适配-手机
属性跨平台适配-平板

扩展需要适配的平台:

插件内置的3个平台在实际使用的过程中可能不够用,因此我们提供了用户自定义平台的适配解决方案。

StatelessWidget适配新平台:

对于StatelessWidget只需要实现一个继承自FlexibleStatelessWidget的抽象类,然后实现新平台的build函数,之后注册该平台即可。

abstract class CustomFlexibleStatelessWidget extends FlexibleStatelessWidget {
  @protected
  Widget buildNewPlatform(BuildContext context) {
    return buildPhone(context); // by default, you can return the phone's style
  }

  @protected
  void initAdapter() {
    super.initAdapter();
    addAdapter(Constant.newPlatform, buildNewPlatform);// register new Platform
  }
}

StatelessWidget适配新平台示例:

class MyStatelessPage extends CustomFlexibleStatelessWidget {

  @override
  Widget buildPhone(BuildContext context) {
    return Text('Phone',style: TextStyle(fontSize: 18.0),);
  }

  @override
  Widget buildPadPortrait(BuildContext context) {
    return Text('PadPortrait',style: TextStyle(fontSize: 22.0),);
  }

  @override
  Widget buildNewPlatform(BuildContext context) {
    return Text('buildNewPlatform',style: TextStyle(fontSize: 30.0),);
  }
}

StatefulWidget适配新平台:

对于StatefulWidget只需要实现一个继承自FlexibleState的抽象类,然后实现新平台的build函数,之后注册该平台即可。

abstract class CustomFlexibleState<T extends StatefulWidget> extends FlexibleState<T> {
  @protected
  Widget buildNewPlatform(BuildContext context) {
    return buildPhone(context); // by default, you can return the phone's style
  }

  @protected
  void initAdapter() {
    super.initAdapter();
    addAdapter(Constant.newPlatform, buildNewPlatform);// register new Platform
  }
}

StatefulWidget适配新平台示例:

class MyStatefulPageState extends CustomFlexibleState<MyStatefulPage> {

  @override
  Widget buildPhone(BuildContext context) {
    return Text('Phone',style: TextStyle(fontSize: 18.0),);
  }

  @override
  Widget buildPadPortrait(BuildContext context) {
    return Text('PadPortrait',style: TextStyle(fontSize: 22.0),);
  }

  @override
  Widget buildNewPlatform(BuildContext context) {
    return Text('NewPlatform',style: TextStyle(fontSize: 30.0),);
  }
}
用户自定义平台

本项目已经开源,开源地址:flutter-adapter

上一篇 下一篇

猜你喜欢

热点阅读