hadss_adaptive_layout 1.0.0-rc.3 copy "hadss_adaptive_layout: ^1.0.0-rc.3" to clipboard
hadss_adaptive_layout: ^1.0.0-rc.3 copied to clipboard

A responsive component plug-in library for multi-device adaptation.

hadss_adaptive_layout #

介绍 #

这是一个旨在解决Flutter多设备适配问题的三方库,为不同设备类型(包括折叠屏、平板、手机等)提供了便捷的支持。该库包含的接口和开箱即用的组件,使开发者能够轻松应对各种设备的布局适配需求。

目前该库提供的组件如下:

  1. 断点相关组件:使用ArkUI断点能力开发的断点管理组件,能够让开发者直接使用ArkUI断点能力。
  2. 自适应显隐容器:对标ArkUI的自适应显隐布局开发的容器,使开发者能够轻松的完成自适应显隐布局能力的开发。
  3. 侧边栏组件:对标ArkUI的SideBarContainer组件开发的Flutter侧边栏组件,使开发者能够轻松的完成侧边栏相关布局能力的开发。
  4. 自适应分栏组件:参考ArkUI的Navigation组件开发的Flutter分栏组件,使开发者能够轻松的完成分栏及路由跳转能力的开发。
  5. 栅格组件:对标ArkUI的GridRow/GridCol开发的Flutter栅格组件,提供基础的栅格布局能力,使开发能够直接使用ArkUI栅格布局能力。

工程目录 #

.
├─example                             // example工程
│  └─lib
│     ├─pages
│     │   ├─breakpoint_page.dart        // 横纵向断点效果演示页
│     │   ├─grid_page.dart              // 栅格组件效果演示页
│     │   ├─display_priority_col_page.dart        // 自适应显隐组件纵向排列效果演示页
│     │   ├─display_priority_row_page.dart        // 自适应显隐组件横向排列效果演示页
│     │   ├─display_priority_page.dart            // 自适应显隐组件效果演示入口页
│     │   ├─navigation_split_page.dart            // 自适应导航分栏组件效果演示入口页
│     │   ├─side_bar_container_page.dart        // 自适应侧边栏组件效果演示入口页
│     │   └─home_page.dart              // 首页
│     ├─routes         
│     │   └─routers.dart                   // 路由配置   
│     ├─utils       
│     │   └─measure_size.dart              // 测量组件尺寸工具类    
│     └─main.dart                          // 工程入口              
│                   
├─lib
│  ├─src
│  │  ├─breakpoint           // 断点类
│  │  ├─grid                 // 栅格组件
│  │  ├─display_priority     // 自适应显隐组件
│  │  ├─navigation_split_container     // 自适应分栏组件
│  │  └─slider_bar_container           // 自适应侧边栏组件
│  └─multidevice_layout.dart                  // 多设备布局库

安装与使用 #

请拉取flutter_multidevice_layout_scenepkg 代码仓并执行flutter pub get。

进入到工程目录并输入以下命令:

运行前准备

flutter pub get
cd example

移动设备运行

flutter run

Web端运行

flutter run -d chrome --web-hostname=127.0.0.1

API #

说明: OpenHarmony: API >= 12 flutter版本: >= 3.7.12

断点 #

BreakpointManager断点管理单例

方法名 参数 返回值 说明
init void Future 初始化断点,注册窗口尺寸变化监听,并返回当前断点值
destroy void void 销毁窗口尺寸变化监听,清空所有添加的回调函数
addBreakpointCallback Function(BreakpointData) callback bool 添加断点状态变化回调函数,添加成功返回true
removeBreakpointCallback {Function(BreakpointData)? callback} bool 删除断点状态变化回调函数,不传值时删除所有,删除成功返回true
setWidthBreakpointRange WidthBreakpointRange range void 设置横向断点区间之后,OpenHarmony不再采用动态断点
setHeightBreakpointRange HeightBreakpointRange range void 设置纵向断点区间,OpenHarmony不再采用动态断点
getWindowWidthBreakpoint void WidthBreakpoint 获取窗口横向断点状态
getWindowHeightBreakpoint void HeightBreakpoint 获取窗口纵向断点状态

说明: 在ohos设备上,且api >= 13采用ohos动态断点能力,因此设置横向和纵向的断点区间将无效。

WidthBreakpoint 横向断点枚举

参数 描述 区间
xs 超小屏幕 (0, xs)
sm 小屏幕 [xs, sm)
md 中屏 [sm, md)
lg 大屏幕 [md, lg)
xl 超大屏幕 [lg, xl)
unknown 未知的屏幕大小 未知区间

HeightBreakpoint 横向断点枚举

参数 描述 区间
sm 小屏幕 [0, sm)
md 中屏 [sm, md)
lg 大屏幕 [md, lg)
unknown 未知的屏幕大小 未知区间

WidthBreakpointRange横向断点区间,设置值为右边界

参数 属性类型 默认值
xs double 0
sm double 0
md double 0
lg double 0
xl double 0

HeightBreakpointRange纵向断点区间,设置值为右边界

参数 属性类型 默认值
sm double 0
md double 0
lg double 0

BreakpointData断点数据对象

属性 类型 描述
widthBreakpoint WidthBreakpoint 当前宽度断点
heightBreakpoint HeightBreakpoint 当前高度断点

下面的代码展示了断点库的使用方式:

/// 断点状态变量管理
class BreakpointProvider extends ChangeNotifier {
  WidthBreakpoint _widthBreakpoint = WidthBreakpoint.unknown;
  HeightBreakpoint _heightBreakpoint = HeightBreakpoint.unknown;

  BreakpointProvider() {
    _initBreakpoint();
  }

  Future<void> _initBreakpoint() async {
    final BreakpointData data = await BreakpointManager().init();
    _widthBreakpoint = data.widthBreakpoint;
    _heightBreakpoint = data.heightBreakpoint;
    BreakpointManager().addBreakpointCallback((breakpointData) {
      _widthBreakpoint = breakpointData.widthBreakpoint;
      _heightBreakpoint = breakpointData.heightBreakpoint;
      notifyListeners();
    });
  }

  WidthBreakpoint get widthBreakpoint => _widthBreakpoint;

  HeightBreakpoint get heightBreakpoint => _heightBreakpoint;
}

/// main文件初始化断点
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  final breakpointProvider = BreakpointProvider();
  runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (context) => RouteManager()),
      ChangeNotifierProvider(create: (context) => breakpointProvider)
    ],
    child: const MyApp(),
  ));
}

/// 断点页面使用刷新参数
@override
Widget build(BuildContext context) {
  return Consumer<BreakpointProvider>(
    builder: (context, provider, child) {
      _widthBp = provider.widthBreakpoint;
      _heightBp = provider.heightBreakpoint;
      blueCol = _widthMap[_widthBp]!;
      redCol = _heightMap[_heightBp]!;
      return _mainView(context);
    },
  );
}

栅格组件 #

参数 属性 说明
gridCols List 单元格GridCol列表容器
columns int 栅格中的列数,其数值决定了内容的布局复杂度(默认值:12)
gutter Gutter 相邻的两个Column之间的距离,决定内容间的紧密程度(包括水平、垂直方向的距离)
margin EdgeInsetsGeometry 相对应用窗口、父容器的左右边缘的距离
breakpoints Breakpoints 设置断点值的断点数列和参考对象,默认情况下:非OpenHarmony,区间值[320, 600, 840]启用xs、sm、md、lg,OpenHarmony采用动态断点,区间启用到xl

下面的代码展示了Flutter栅格组件的使用方式:

import 'package:flutter/material.dart';
import 'package:hadss_adaptive_layout/hadss_adaptive_layout.dart';

class MyGrid extends StatefulWidget {
  const MyGrid({super.key});

  @override
  State<MyGrid> createState() => _MyGridState();
}

class _MyGridState extends State<MyGrid> with WidgetsBindingObserver {
  double _currentWidth = 0;
  List<GridCol> childList = [];

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    childList.add(
      GridCol(
        span: SpanOption(xs: 1,
            sm: 1,
            md: 3,
            lg: 4,
            xl: 5,
            xxl: 6),
        offset: 0,
        order: 0,
        child: Container(
          color: Colors.blue,
          width: double.infinity,
          alignment: Alignment.center,
          child: const Text('1'),
        ),
      ),
    );
    for (int i = 0; i < 20; i++) {
      childList.add(
        GridCol(
          span: 1,
          offset: 0,
          order: (i + 1) % 3,
          child: Container(
            color: Colors.blue,
            width: double.infinity,
            alignment: Alignment.center,
            child: Text((i + 2).toString()),
          ),
        ),
      );
    }
    updateScreenSize();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeMetrics() {
    updateScreenSize();
  }

  void updateScreenSize() {
    final Size size = WidgetsBinding.instance.window.physicalSize;
    final double ratio = WidgetsBinding.instance.window.devicePixelRatio;
    setState(() {
      _currentWidth = size.width / ratio;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('栅格组件示例'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Text('当前屏幕宽度:$_currentWidth'),
            GridRow(
              gridCols: childList,
              columns: 12,
              gutter: const Gutter(x: 10, y: 8),
              margin: const EdgeInsets.all(0),
              range: BreakpointRange(
                list: [0, 320, 600, 840, 1440, 2000],
              ),
            )
          ],
        ),
      ),
    );
  }
}

自适应显隐组件 #

自适应显隐容器

属性名 类型 必填 默认值 说明
direction Axis 定义子组件排列的方向。可以是水平排列(Axis.horizontal)或垂直排列(Axis.vertical)。
mainAxisAlignment MainAxisAlignment MainAxisAlignment.start 定义主轴方向上子组件的对齐方式。
crossAxisAlignment CrossAxisAlignment CrossAxisAlignment.center 定义交叉轴方向上子组件的对齐方式。
displayPriorityList List 显隐优先级对象的列表。
textDirection TextDirection TextDirection.ltr 确定文本和子组件的布局方向。
verticalDirection VerticalDirection VerticalDirection.down 定义垂直方向上子组件的排列顺序。

显隐容器属性配置类

属性名 类型 必填 默认值 说明
displayPriority int 1 设置当前组件在布局容器中显示的优先级。默认值:1。说明:仅在DisplayPriorityBox组件中生效。
child Widget 子组件

下面的代码展示了自适应显隐组件的使用方式:

import 'package:flutter/material.dart';
import 'package:hadss_adaptive_layout/hadss_adaptive_layout.dart';

class DisplayPriorityRowPage extends StatefulWidget {
  const DisplayPriorityRowPage({super.key});

  @override
  State<DisplayPriorityRowPage> createState() => _DisplayPriorityRowPageState();
}

class _DisplayPriorityRowPageState extends State<DisplayPriorityRowPage> {
  List<DisplayPriorityObject> childList = [];

  @override
  void initState() {
    super.initState();
    for (int i = 0; i < 60; i++) {
      childList.add(
        DisplayPriorityObject(
          displayPriority: i % 3 + 1,
          child: Text(
            (i % 3 + 1).toString(),
            style: const TextStyle(color: Colors.red, fontSize: 50),
          ),
        ),
      );
    }
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('显隐组件:水平效果'),
      ),
      body: SafeArea(
        child: DisplayPriorityBox(
          direction: Axis.horizontal,
          displayPriorityList: childList,
        ),
      ),
    );
  }
}

侧边栏组件 #

SideBarContainer

属性名 类型 必填 默认值 说明
sideBar Widget SizedBox.shrink() 侧边栏区域。
content Widget SizedBox.shrink() 内容区域。
type SideBarContainerType SideBarContainerType.embed 侧边栏显示模式。
showSideBar bool true 设置是否显示侧边栏。
showControlButton bool true 是否显示控制按钮。
sideBarWidth double 240.0 设置侧边栏的宽度。受最小宽度和最大宽度限制,不在限制区域内取最近的点。约束:值不能小于0。
minSideBarWidth double 240.0 设置侧边栏最小宽度。值不能超过侧边栏容器本身宽度,超过使用侧边栏容器本身宽度。约束:值不能小于0。
maxSideBarWidth double 280.0 设置侧边栏最大宽度。值不能超过侧边栏容器本身宽度,超过使用侧边栏容器本身宽度。约束:值不能小于0。
minContentWidth double 360.0 设置SideBarContainer组件内容区可显示的最小宽度。约束:值不能小于0。
autoHide bool true 设置当侧边栏拖拽到小于最小宽度后,是否自动隐藏。受minSideBarWidth属性方法影响,minSideBarWidth属性方法未设置值使用默认值。
sideBarPosition SideBarPosition SideBarPosition.start 设置侧边栏显示位置。
controlButton ButtonStyle ButtonStyle() 设置侧边栏控制按钮的属性。
divider DividerStyle DividerStyle(strokeWidth: 1) 设置分割线的样式。
onChange Function(bool) Null 当侧边栏的状态在显示和隐藏之间切换时触发回调。

SideBarContainerType

名称 说明
embed 侧边栏嵌入到组件内,和内容区并列显示。组件尺寸小于minContentWidth + minSideBarWidth,并且未设置showSideBar时,侧边栏自动隐藏。未设置minSideBarWidth或者minContentWidth采用未设置接口的默认值进行计算。组件在自动隐藏后,如果通过点击控制按钮唤出侧边栏,则侧边栏悬浮在内容区上显示。
overlay 侧边栏浮在内容区上面。
auto 组件尺寸大于等于minSideBarWidth+minContentWidth时,采用embed模式显示。组件尺寸小于minSideBarWidth+minContentWidth时,采用overlay模式显示。未设置minSideBarWidth或minContentWidth时,会使用未设置接口的默认值进行计算,若计算的值小于600,则使用600做为模式切换的断点值。

SideBarContainerType

名称 说明
start 侧边栏位于容器左侧。
end 侧边栏位于容器右侧。

DividerStyle

名称 类型 说明
strokeWidth double 分割线的线宽。默认值:1
color Color 分割线的颜色。默认值:#000000,3%
startMargin double 分割线与侧边栏顶端的距离。默认值:0
endMargin double 分割线与侧边栏底端的距离。默认值:0

ButtonStyle

名称 类型 必填 说明
left double 设置侧边栏控制按钮距离容器左界限的间距。默认值:16
top double 设置侧边栏控制按钮距离容器上界限的间距。默认值:48
width double 设置侧边栏控制按钮的宽度。默认值:24
height double 设置侧边栏控制按钮的高度。默认值:24
icons {shown: Image;hidden:Image ;switching:Image? } 设置侧边栏控制按钮的图标:- shown: 设置侧边栏显示时控制按钮的图标。说明:资源获取错误时,使用默认图标。- hidden: 设置侧边栏隐藏时控制按钮的图标。- switching:设置侧边栏显示和隐藏状态切换时控制按钮的图标。

下面的代码展示了侧边栏组件的使用方式:

import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:hadss_adaptive_layout/hadss_adaptive_layout.dart';

class SliderBarContainerPage extends StatefulWidget {
  const SliderBarContainerPage({Key? key}) : super(key: key);

  @override
  State<SliderBarContainerPage> createState() => _SliderBarContainerPageState();
}

class _SliderBarContainerPageState extends State<SliderBarContainerPage> {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('SideBarContainer 示例'),
          ),
          body: SideBarContainer(
            sideBar: Container(
              color: Colors.blue,
              child: const Center(
                child: Text(
                  '侧边栏',
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 18.0,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
            content: Container(
              color: Colors.grey,
              child: const Center(
                child: Text(
                  '内容区',
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 18.0,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
            type: SideBarContainerType.auto,
            showControlButton: true,
            showSideBar: true,
            sideBarWidth: 50.0,
            minSideBarWidth: 75.0,
            maxSideBarWidth: 100.0,
            minContentWidth: 200.0,
            autoHide: true,
            sideBarPosition: SideBarPosition.start,
            controlButton: const ButtonStyle(
                left: 16.0,
                top: 16.0,
                icons: ButtonIcons(
                    shown: Image(image: AssetImage('assets/show_all.png')),
                    hidden: Image(image: AssetImage('assets/show_all.png')))),
            divider: const DividerStyle(
              strokeWidth: 1.0,
              color: Colors.black,
              startMargin: 10.0,
              endMargin: 10.0,
            ),
            onChange: (isVisible) {
              print('isVisible: $isVisible');
            },
          ),
        );
      },
    );
  }
}

自适应分栏组件 #

NavigationSplitContainer

属性名 类型 必填 默认值 说明
navBarWidth double 240 导航栏宽度。
minContentWidth double 360 最小主内容区域宽度。
navBarWidthRange List<double> [240,432] 导航栏最小和最大宽度。
最大默认值为组件宽度的40%,且不大于432,如果只设置一个值,该值为最大宽度,未设置的值按照默认值计算
mode NavigationSplitMode NavigationSplitMode.auto 导航栏的显示模式。
自适应:基于组件宽度自适应单栏和双栏
navBarPosition NavBarPosition NavBarPosition.start 导航栏位置。
navigationPane Widget SizeBox.shrink 导航栏内容。
mainContent Widget SizeBox.shrink 主内容。
onNavBarStateChange Function(bool isVisible) null 导航栏显示状态切换时触发该回调。isVisible为true时表示显示,为false时表示隐藏。
onNavigationModeChange Function(NavigationSplitMode mode) null 当navigationPane首次显示或者单双栏状态发生变化时触发该回调。
NavigationSplitMode.split:当前显示为双栏;
NavigationSplitMode.stack:当前显示为单栏

NavigationSplitMode

名称 说明
stack 导航栏与内容区独立显示,相当于两个页面。
split 导航栏与内容区分栏显示。
以下navBarWidthRange的值用[minNavBarWidth, maxNavBarWidth]表示
1.当navBarWidth值在navBarWidthRange范围以外时,navBarWidth按如下规则显示:
navBarWidth < minNavBarWidth时,navBarWidth修正为minNavBarWidth;
navBarWidth > maxNavBarWidth,且组件宽度 - minContentWidth - 分割线宽度(1) > maxNavBarWidth时,navBarWidth修正为maxNavBarWidth;
navBarWidth > maxNavBarWidth,且组件宽度 - minContentWidth - 分割线宽度(1) < minNavBarWidth时,navBarWidth修正为minNavBarWidth;
navBarWidth > maxNavBarWidth,且组件宽度 - minContentWidth - 分割线宽度(1);
在navBarWidthRange范围内,navBarWidth修正为组件宽度 - 分割线宽度(1) - minContentWidth。
2.当navBarWidth属性的值,在navBarWidthRange属性的值范围以内时,navBarWidth按如下规则显示:minNavBarWidth + minContentWidth + 分割线宽度(1) >= 组件宽度时,navBarWidth修正为minNavBarWidth;
minNavBarWidth + minContentWidth + 分割线宽度(1) < 组件宽度,且navBarWidth + minContentWidth + 分割线宽度(1) >= 组件宽度时,navBarWidth修正为组件宽度 - 分割线宽度(1) - minContentWidth;
minNavBarWidth + minContentWidth + 分割线宽度(1) < 组件宽度,且navBarWidth + minContentWidth + 分割线宽度(1) < 组件宽度时,navBarWidth为设置的值。
3.缩小组件尺寸时,先缩小内容区的尺寸至minContentWidth,然后再缩小导航栏的尺寸至minNavBarWidth。若继续缩小,先缩小内容区,内容区消失后再缩小导航栏。
4.设置导航栏为固定尺寸时,若持续缩小组件尺寸,导航栏最后压缩显示。
5.若只设置了navBarWidth属性,则导航栏宽度为navBarWidth,且分割线不可拖动。
auto 组件宽度 >= 600时,采用split模式显示;组件宽度 < 600时,采用stack模式显示, 600等于minNavBarWidth(240) + minContentWidth(360)

NavBarPosition

名称 说明
start 双栏显示时,导航栏显示在容器左侧
end 双栏显示时,导航栏显示在容器右侧

使用方式:

@override
Widget build(BuildContext context) {
  return NavigationSplitContainer(
      navBarWidth: 240,
      minContentWidth: 200,
      navBarWidthRange: const [200, 300],
      mode: NavigationSplitMode.auto,
      navBarPosition: NavBarPosition.start,
      navigationPane: const NavigationPage(),
      mainContent: const DetailsPage(),
      onNavBarStateChange: (bool isVisible) {
        print('onNavBarStateChange: $isVisible');
      },
      onNavigationModeChange: (NavigationSplitMode mode) {
        print('onNavigationModeChange: $mode');
      });
}
0
likes
125
points
17
downloads

Publisher

unverified uploader

Weekly Downloads

A responsive component plug-in library for multi-device adaptation.

Homepage
Repository

Topics

#adaptive #responsive #layout

Documentation

Documentation
API reference

License

Apache-2.0 (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on hadss_adaptive_layout

Packages that implement hadss_adaptive_layout