diff --git a/.github/workflows/preview-build.yml b/.github/workflows/preview-build.yml index 9d37794f8..c7988e8bf 100644 --- a/.github/workflows/preview-build.yml +++ b/.github/workflows/preview-build.yml @@ -90,147 +90,6 @@ jobs: repository: TDesignOteam/tdesign-flutter-generator path: ./example/tdesign-flutter-generator - - name: 重写脚本 - run: | - # AOPMarket.enable = true - yq e '.AOPMarket.enable = true' -i tdesign-component/example/pubspec.yaml - # 更新 tdesign-component/example/android/app/build.gradle - cd $GITHUB_WORKSPACE/tdesign-component/example/android/app - - # 使用 sed 更新 build.gradle 文件 - # 1. 添加 namespace 如果不存在 - if ! grep -q "namespace" build.gradle; then - sed -i '/^android {$/a\\ namespace '\''com.tdesign.tdesign_flutter_example'\''' build.gradle - fi - - # 2. 更新 compileSdkVersion 从 34 到 35 - sed -i 's/compileSdkVersion 34/compileSdkVersion 35/g' build.gradle - - # 3. 更新 minSdkVersion 从 21 到 23 - sed -i 's/minSdkVersion 21/minSdkVersion 23/g' build.gradle - - # 4. 更新 targetSdkVersion 从 31 到 35 - sed -i 's/targetSdkVersion 31/targetSdkVersion 35/g' build.gradle - - # 5. 将双引号改为单引号 (applicationId) - sed -i 's/applicationId "com.tdesign.tdesign_flutter_example"/applicationId '\''com.tdesign.tdesign_flutter_example'\''/g' build.gradle - - # 6. 添加 compileOptions 和 kotlinOptions 如果不存在 - if ! grep -q "compileOptions" build.gradle; then - # 在 buildTypes 块之后添加 compileOptions 和 kotlinOptions - awk ' - BEGIN { in_android = 0; buildtypes_done = 0 } - /^android \{/ { in_android = 1; print; next } - /^ buildTypes \{/ && in_android { print; in_buildtypes = 1; next } - /^ \}/ && in_buildtypes && in_android { - print - print "" - print " compileOptions {" - print " sourceCompatibility JavaVersion.VERSION_17" - print " targetCompatibility JavaVersion.VERSION_17" - print " }" - print "" - print " kotlinOptions {" - print " jvmTarget = '\''17'\''" - print " }" - in_buildtypes = 0 - buildtypes_done = 1 - next - } - /^}/ && in_android && buildtypes_done { in_android = 0 } - { print } - ' build.gradle > build.gradle.tmp && mv build.gradle.tmp build.gradle - fi - - echo "=== build.gradle 更新完成 ===" - echo "=== 显示更新后的 android 块 ===" - sed -n '/^android {/,/^}/p' build.gradle - # 重写 tdesign-component/example/android/build.gradle - cd $GITHUB_WORKSPACE/tdesign-component/example/android - - # 删除原文件并创建新文件 - rm -f build.gradle - - # 创建新的 build.gradle 文件内容 - echo "buildscript {" > build.gradle - echo " ext.kotlin_version = '1.7.10'" >> build.gradle - echo "" >> build.gradle - echo " ext {" >> build.gradle - echo " config = [" >> build.gradle - echo " // 蓝盾自带变量" >> build.gradle - echo " isCI : System.getenv(\"isCI\") ?: \"false\" // 是否在RMD的持续集成构建环境中" >> build.gradle - echo " , VersionCode : System.getenv(\"VersionCode\") ?: \"1\" // VersionCode,每次发版本+2" >> build.gradle - echo " , devopsUUID : System.getenv(\"uuid\") ?: \"local\" // 蓝盾构建UUID" >> build.gradle - echo " , MajorVersion : System.getenv(\"MajorVersion\") ?: \"1\" // 主版本号" >> build.gradle - echo " , MinorVersion : System.getenv(\"MinorVersion\") ?: \"0\" // 特性版本号" >> build.gradle - echo " , FixVersion : System.getenv(\"FixVersion\") ?: \"0\" // 修正版本号" >> build.gradle - echo " , BuildNo : System.getenv(\"BuildNo\") ?: \"0\" // 构建号" >> build.gradle - echo " , isPublish : System.getenv(\"isPublish\") ?: \"false\" // 是否是外发版本,用来控制调试入口等" >> build.gradle - echo " , isBeta : System.getenv(\"isBeta\") ?: \"false\" // 是否是灰度版本" >> build.gradle - echo " , gitVersion : System.getenv(\"gitVersion\") ?: \"local\" // git提交hash" >> build.gradle - echo " , keyAlias : System.getenv(\"keyAlias\") ?: \"debug\" // 签名信息" >> build.gradle - echo " , storePassword: System.getenv(\"storePassword\") ?: \"debug\" // storePassword" >> build.gradle - echo " , abi_filters : System.getenv(\"abi_filters\") ?: \"armeabi-v7a,arm64-v8a,x86,x86_64\" // abi类型配置" >> build.gradle - echo " ]" >> build.gradle - echo "" >> build.gradle - echo " def dir = System.getProperty(\"user.dir\")" >> build.gradle - echo " def file = new File(dir, 'local.properties')" >> build.gradle - echo " Properties properties = new Properties()" >> build.gradle - echo " if (file.exists()) {" >> build.gradle - echo " properties.load(file.newDataInputStream())" >> build.gradle - echo " }" >> build.gradle - echo " enableWatchman = Boolean.valueOf(properties.getProperty('enableWatchman', \"\"))" >> build.gradle - echo " }" >> build.gradle - echo "" >> build.gradle - echo " repositories {" >> build.gradle - echo " google()" >> build.gradle - echo " mavenCentral()" >> build.gradle - echo " }" >> build.gradle - echo "" >> build.gradle - echo " dependencies {" >> build.gradle - echo " classpath 'com.android.tools.build:gradle:7.0.1'" >> build.gradle - echo " classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:\$kotlin_version\"" >> build.gradle - echo " }" >> build.gradle - echo "}" >> build.gradle - echo "" >> build.gradle - echo "allprojects {" >> build.gradle - echo " repositories {" >> build.gradle - echo " google()" >> build.gradle - echo " mavenCentral()" >> build.gradle - echo " }" >> build.gradle - echo "}" >> build.gradle - echo "rootProject.buildDir = '../build'" >> build.gradle - echo "subprojects {" >> build.gradle - echo " project.buildDir = \"\${rootProject.buildDir}/\${project.name}\"" >> build.gradle - echo "}" >> build.gradle - echo "subprojects {" >> build.gradle - echo " project.evaluationDependsOn(':app')" >> build.gradle - echo "}" >> build.gradle - echo "tasks.register(\"clean\", Delete) {" >> build.gradle - echo " delete rootProject.buildDir" >> build.gradle - echo "}" >> build.gradle - - echo "=== android/build.gradle 重写完成 ===" - echo "=== 显示新的 android/build.gradle 内容 ===" - cat build.gradle - # 更新 tdesign-component/example/android/gradle/wrapper/gradle-wrapper.properties - cd $GITHUB_WORKSPACE/tdesign-component/example/android/gradle/wrapper - - # 更新 Gradle 版本从 7.6 到 8.4 - sed -i 's|distributionUrl=https\\://services.gradle.org/distributions/gradle-7.6-all.zip|distributionUrl=https\\://services.gradle.org/distributions/gradle-8.4-all.zip|g' gradle-wrapper.properties - - echo "=== gradle-wrapper.properties 更新完成 ===" - echo "=== 显示更新后的 gradle-wrapper.properties 内容 ===" - cat gradle-wrapper.properties - # 更新 tdesign-component/example/android/settings.gradle - cd $GITHUB_WORKSPACE/tdesign-component/example/android - - # 更新 Android Gradle Plugin 版本从 7.3.0 到 8.3.0 - sed -i 's|id "com.android.application" version "7.3.0" apply false|id "com.android.application" version "8.3.0" apply false|g' settings.gradle - - echo "=== settings.gradle 更新完成 ===" - echo "=== 显示更新后的 settings.gradle 内容 ===" - cat settings.gradle - name: Build Flutter apk run: | cd $GITHUB_WORKSPACE/tdesign-component/example @@ -314,7 +173,7 @@ jobs: run: | npm install --unsafe-perm npm run site - + - name: Build site Demo working-directory: ./tdesign-component/example run: | diff --git a/README.md b/README.md index 570844aed..573b007ff 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,10 @@ TDesign Flutter depends on the following component libraries. We appreciate the Contributing is welcome. Read [guidelines for contributing](CONTRIBUTING.md) before submitting your [Pull Request](https://github.com/Tencent/tdesign-flutter/pulls). + + + + # Feedback Create your [Github issues](https://github.com/Tencent/tdesign-flutter/issues) or scan the QR code below to join our user groups. diff --git a/README_zh_CN.md b/README_zh_CN.md index 4cfc3f577..5dd493b3f 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -88,9 +88,13 @@ TDesign Flutter 依赖以下组件库,感谢作者的开源贡献: - [flutter_slidable](https://pub-web.flutter-io.cn/packages/flutter_slidable) - [image_picker](https://pub-web.flutter-io.cn/packages/image_picker) -# Contributing +# 贡献 -Contributing is welcome. Read [guidelines for contributing](CONTRIBUTING.md) before submitting your [Pull Request](https://github.com/Tencent/tdesign-flutter/pulls). +欢迎贡献代码。在提交 [Pull Request](https://github.com/Tencent/tdesign-flutter/pulls) 之前,请先阅读[贡献指南]((CONTRIBUTING.md))。 + + + + # 反馈 diff --git a/tdesign-component/example/android/app/build.gradle b/tdesign-component/example/android/app/build.gradle index 925c7d952..754be2516 100644 --- a/tdesign-component/example/android/app/build.gradle +++ b/tdesign-component/example/android/app/build.gradle @@ -40,7 +40,19 @@ if (keystorePropertiesFile.exists()) { android { - compileSdkVersion 34 + // AGP 8.0+ 需要设置包命名空间 + namespace 'com.tdesign.tdesign_flutter_example' + + compileSdkVersion flutter.compileSdkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -49,8 +61,8 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.tdesign.tdesign_flutter_example" - minSdkVersion 21 - targetSdkVersion 31 + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion versionCode createVersionCode() versionName createVersionName() } diff --git a/tdesign-component/example/android/gradle/wrapper/gradle-wrapper.properties b/tdesign-component/example/android/gradle/wrapper/gradle-wrapper.properties index 02e5f5817..7aeeb11c6 100644 --- a/tdesign-component/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/tdesign-component/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/tdesign-component/example/android/settings.gradle b/tdesign-component/example/android/settings.gradle index fa3b8b140..cabc2fa06 100644 --- a/tdesign-component/example/android/settings.gradle +++ b/tdesign-component/example/android/settings.gradle @@ -20,8 +20,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" // 声明式加载插件 - id "com.android.application" version "7.3.0" apply false // 根据实际 AGP 版本调整 - id "org.jetbrains.kotlin.android" version "1.9.22" apply false // Kotlin 版本需兼容 AGP + id "com.android.application" version "8.6.0" apply false // 根据实际 AGP 版本调整 + id "org.jetbrains.kotlin.android" version "2.1.0" apply false // Kotlin 版本需兼容 AGP } include ":app" \ No newline at end of file diff --git a/tdesign-component/example/assets/img/empty.png b/tdesign-component/example/assets/img/empty.png index 70d00ae06..812b0ea4d 100644 Binary files a/tdesign-component/example/assets/img/empty.png and b/tdesign-component/example/assets/img/empty.png differ diff --git a/tdesign-component/example/assets/theme.json b/tdesign-component/example/assets/theme.json index 88dfcec04..c864be0e5 100644 --- a/tdesign-component/example/assets/theme.json +++ b/tdesign-component/example/assets/theme.json @@ -174,5 +174,114 @@ "grayColor13": "#242424", "grayColor14": "#181818" } + }, + "dark": { + "ref": { + "brandLightColor": "brandColor1", + "brandFocusColor": "brandColor1", + "brandDisabledColor": "brandColor3", + "brandHoverColor": "brandColor5", + "brandNormalColor": "brandColor8", + "brandActiveColor": "brandColor2", + "warningNormalColor": "warningColor5", + "warningHoverColor": "warningColor4", + "warningFocusColor": "warningColor2", + "warningActiveColor": "warningColor6", + "warningDisabledColor": "warningColor3", + "warningLightColor": "warningColor1", + "errorNormalColor": "errorColor6", + "errorHoverColor": "errorColor5", + "errorFocusColor": "errorColor2", + "errorActiveColor": "errorColor7", + "errorDisabledColor": "errorColor3", + "errorLightColor": "errorColor1", + "successNormalColor": "successColor5", + "successHoverColor": "successColor4", + "successFocusColor": "successColor2", + "successActiveColor": "successColor6", + "successDisabledColor": "successColor3", + "successLightColor": "successColor1", + "brandColorLightHover": "brandColor2", + "warningColorLightHover": "warningColor2", + "errorColorLightHover": "errorColor2", + "successColorLightHover": "successColor2", + "bgColorPage": "grayColor14", + "bgColorContainer": "grayColor13", + "bgColorContainerHover": "grayColor12", + "bgColorContainerActive": "grayColor10", + "bgColorContainerSelect": "grayColor9", + "bgColorSecondaryContainer": "grayColor12", + "bgColorSecondaryContainerHover": "grayColor11", + "bgColorSecondaryContainerActive": "grayColor9", + "bgColorComponent": "grayColor11", + "bgColorComponentHover": "grayColor10", + "bgColorComponentActive": "grayColor9", + "bgColorComponentDisabled": "grayColor12", + "componentStrokeColor": "grayColor11", + "componentBorderColor": "grayColor9", + "textColorPrimary": "fontWhColor1", + "textColorSecondary": "fontWhColor2", + "textColorPlaceholder": "fontWhColor3", + "textColorDisabled": "fontWhColor4", + "textColorAnti": "fontWhColor1", + "textColorBrand": "brandColor8", + "textColorLink": "brandColor8" + }, + "color": { + "brandColor1": "#1b2f51", + "brandColor2": "#173463", + "brandColor3": "#143975", + "brandColor4": "#103d88", + "brandColor5": "#0d429a", + "brandColor6": "#054bbe", + "brandColor7": "#2667d4", + "brandColor8": "#4582e6", + "brandColor9": "#699ef5", + "brandColor10": "#96bbf8", + "warningColor1": "#4f2a1d", + "warningColor2": "#582f21", + "warningColor3": "#733c23", + "warningColor4": "#a75d2b", + "warningColor5": "#cf6e2d", + "warningColor6": "#dc7633", + "warningColor7": "#e8935c", + "warningColor8": "#ecbf91", + "warningColor9": "#eed7bf", + "warningColor10": "#f3e9dc", + "errorColor1": "#472324", + "errorColor2": "#5e2a2d", + "errorColor3": "#703439", + "errorColor4": "#83383e", + "errorColor5": "#a03f46", + "errorColor6": "#c64751", + "errorColor7": "#de6670", + "errorColor8": "#ec888e", + "errorColor9": "#edb1b6", + "errorColor10": "#eeced0", + "successColor1": "#193a2a", + "successColor2": "#1a4230", + "successColor3": "#17533d", + "successColor4": "#0d7a55", + "successColor5": "#059465", + "successColor6": "#43af8a", + "successColor7": "#46bf96", + "successColor8": "#80d2b6", + "successColor9": "#b4e1d3", + "successColor10": "#deede8", + "grayColor1": "#f3f3f3", + "grayColor2": "#eeeeee", + "grayColor3": "#e7e7e7", + "grayColor4": "#dcdcdc", + "grayColor5": "#c5c5c5", + "grayColor6": "#a6a6a6", + "grayColor7": "#8b8b8b", + "grayColor8": "#77", + "grayColor9": "#5e5e5e", + "grayColor10": "#4b4b4b", + "grayColor11": "#383838", + "grayColor12": "#2c2c2c", + "grayColor13": "#242424", + "grayColor14": "#181818" + } } } \ No newline at end of file diff --git a/tdesign-component/example/l10n.yaml b/tdesign-component/example/l10n.yaml index 4e6692e55..281a5f8fc 100644 --- a/tdesign-component/example/l10n.yaml +++ b/tdesign-component/example/l10n.yaml @@ -1,3 +1,8 @@ +# 详见 https://docs.flutter.dev/release/breaking-changes/flutter-generate-i10n-source +# 新版可注释掉synthetic-package,使用旧版则保留 +# 也可参考上述文档执行 flutter config --explicit-package-dependencies +synthetic-package: false arb-dir: lib/l10n template-arb-file: app_en.arb -output-localization-file: app_localizations.dart \ No newline at end of file +output-localization-file: app_localizations.dart +#output-dir: lib/l10n \ No newline at end of file diff --git a/tdesign-component/example/lib/about.dart b/tdesign-component/example/lib/about.dart index 50b4f6fb8..1b7f12fec 100644 --- a/tdesign-component/example/lib/about.dart +++ b/tdesign-component/example/lib/about.dart @@ -10,7 +10,6 @@ class AboutPage extends StatefulWidget { } class _AboutPageState extends State { - String? version; String? publishTime; @@ -26,61 +25,27 @@ class _AboutPageState extends State { version = await rootBundle.loadString('assets/version'); setState(() {}); } - + Future _getPublishTime() async { var timeStamp = await rootBundle.loadString('assets/publish_time'); - var exactTime = DateTime.fromMillisecondsSinceEpoch(int.parse(timeStamp.trim())); + var exactTime = + DateTime.fromMillisecondsSinceEpoch(int.parse(timeStamp.trim())); publishTime = '${exactTime.year}-${exactTime.month}-${exactTime.day}'; setState(() {}); } - @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: TDTheme.of(context).grayColor1, - appBar: AppBar(title: TDText('关于我们', textColor: TDTheme.of(context).whiteColor1,),), - body: SingleChildScrollView( - child: Column( - children: [ - demoRow(context, '版本号:',desc: version), - demoRow(context, '发版日期:', desc: publishTime) - ], - ), + appBar: AppBar(title: const Text('关于我们')), + body: TDCellGroup( + title: 'TDesign Flutter', + theme: TDCellGroupTheme.cardTheme, + cells: [ + TDCell(title: '版本号', note: version), + TDCell(title: '发版日期', note: publishTime), + ], ), ); } - - Widget demoRow( - BuildContext context, - String? title, { - String? desc, - bool on = true, - bool enable = true, - Color? onColor, - Color? offColor, - }) { - final theme = TDTheme.of(context); - Widget current = Row( - children: [ - Expanded( - child: TDText( - title, - textColor: theme.fontGyColor1, - )), - TDText( - desc ?? '', - textColor: theme.grayColor6, - forceVerticalCenter: true, - ), - ], - ); - current = Container( - color: TDTheme.of(context).whiteColor1, - padding: const EdgeInsets.only(left: 16, right: 16, bottom: 1, top: 1), - child: current, - height: 44, - ); - return current; - } } diff --git a/tdesign-component/example/lib/base/api_widget.dart b/tdesign-component/example/lib/base/api_widget.dart index e197a2d6b..41f0cc861 100644 --- a/tdesign-component/example/lib/base/api_widget.dart +++ b/tdesign-component/example/lib/base/api_widget.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; @@ -16,22 +15,22 @@ class ApiPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: TDText('${model?.text} API', textColor: TDTheme.of(context).whiteColor1,),), + appBar: AppBar(title: Text('${model?.text} API')), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16), - child: ApiWidget(apiName: model?.name, visible: true,), + child: ApiWidget(apiName: model?.name), ), ), ); } } - class ApiWidget extends StatefulWidget { - const ApiWidget({Key? key, required this.apiName, this.visible = false}) : super(key: key); - - final bool visible; + const ApiWidget({ + Key? key, + required this.apiName, + }) : super(key: key); final String? apiName; @@ -40,21 +39,18 @@ class ApiWidget extends StatefulWidget { } class _ApiWidgetState extends State { - String? result; String? lastApiName; @override Widget build(BuildContext context) { - return Visibility( - visible: widget.visible, - child: FutureBuilder( + return FutureBuilder( future: getApiData(), builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { return Container( margin: const EdgeInsets.only(bottom: 64), - child: Markdown( + child: Markdown( padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, @@ -67,13 +63,17 @@ class _ApiWidgetState extends State { ), ); } else { - return Container( - alignment: Alignment.topLeft, - child: const TDText('加载中…'), + return const Center( + child: TDLoading( + size: TDLoadingSize.large, + icon: TDLoadingIcon.circle, + text: '加载中…', + axis: Axis.horizontal, + ), ); } }, - )); + ); } Future getApiData() async { @@ -82,16 +82,18 @@ class _ApiWidgetState extends State { 暂无对应api '''; - if(widget.apiName == lastApiName && result != null && result != defaultResult){ + if (widget.apiName == lastApiName && + result != null && + result != defaultResult) { return result!; } try { var apiName = widget.apiName ?? 'default'; - result = await rootBundle.loadString('assets/api/${apiName}_api.md'); + result = await rootBundle.loadString('assets/api/${apiName}_api.md'); lastApiName = widget.apiName; } catch (e) { print('getApiData error: $e'); } return result ?? defaultResult; } -} \ No newline at end of file +} diff --git a/tdesign-component/example/lib/base/example_widget.dart b/tdesign-component/example/lib/base/example_widget.dart index d0a8deaed..bc3ea6fe8 100644 --- a/tdesign-component/example/lib/base/example_widget.dart +++ b/tdesign-component/example/lib/base/example_widget.dart @@ -25,7 +25,7 @@ class ExamplePage extends StatefulWidget { this.desc = '', this.children = const [], this.padding, - this.backgroundColor, + @deprecated this.backgroundColor, required this.exampleCodeGroup, this.test = const [], this.showSingleChild = false, @@ -101,8 +101,6 @@ class _ExamplePageState extends State { Widget build(BuildContext context) { return Scaffold( floatingActionButton: widget.floatingActionButton, - backgroundColor: - widget.backgroundColor ?? TDTheme.of(context).grayColor1, body: ScrollbarTheme( data: ScrollbarThemeData( trackVisibility: MaterialStateProperty.all(true)), @@ -114,63 +112,72 @@ class _ExamplePageState extends State { child: widget.showSingleChild && widget.singleChild != null ? _singleChild() : MediaQuery( - // 去掉底部安全区域,保证示例展示正常 - data: MediaQuery.of(context).copyWith(padding: EdgeInsets.zero), - child: ListView.builder( - controller: widget.scrollController, - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.only(top: 24, bottom: 24), - itemCount: widget.children.length + 3, - itemBuilder: (context, index) { - if (index == 0) { - return _buildHeader(context); - } - if (index == widget.children.length + 2) { - return WebMdTool.needGenerateWebMd - ? Container( - margin: const EdgeInsets.only(top: 24), - child: Column( - children: [ - TDButton( - text: '生成Web使用md', - type: TDButtonType.fill, - onTap: () => WebMdTool.generateWebMd( - model: model, - description: widget.desc, - exampleCodeGroup: - widget.exampleCodeGroup, - exampleModuleList: - widget.children, - testList: widget.test, - singleChild: - widget.showSingleChild - ? widget.singleChild - : null), - ), - TDButton( - text: '返回首页', - type: TDButtonType.fill, - onTap: () => Navigator.of(context).maybePop(), - ), - ], - ), - ) - : Container(); - } - ExampleModule data; - if (index <= widget.children.length) { - data = widget.children[index - 1]; - } else { - data = ExampleModule(title: '单元测试', children: [ - _buildTestExampleItem(), - ...widget.test - ]); - } - return _buildModule(index, data, context); - }, - ), - )), + // 去掉底部安全区域,保证示例展示正常 + data: MediaQuery.of(context) + .copyWith(padding: EdgeInsets.zero), + child: ListView.builder( + controller: widget.scrollController, + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + padding: + const EdgeInsets.only(top: 24, bottom: 24), + itemCount: widget.children.length + 3, + itemBuilder: (context, index) { + if (index == 0) { + return _buildHeader(context); + } + if (index == widget.children.length + 2) { + return WebMdTool.needGenerateWebMd + ? Container( + margin: + const EdgeInsets.only(top: 24), + child: Column( + children: [ + TDButton( + text: '生成Web使用md', + type: TDButtonType.fill, + onTap: () => + WebMdTool.generateWebMd( + model: model, + description: + widget.desc, + exampleCodeGroup: widget + .exampleCodeGroup, + exampleModuleList: + widget.children, + testList: widget.test, + singleChild: widget + .showSingleChild + ? widget.singleChild + : null), + ), + TDButton( + text: '返回首页', + type: TDButtonType.fill, + onTap: () => + Navigator.of(context) + .maybePop(), + ), + ], + ), + ) + : Container(); + } + ExampleModule data; + if (index <= widget.children.length) { + data = widget.children[index - 1]; + } else { + data = ExampleModule( + title: '单元测试', + children: [ + _buildTestExampleItem(), + ...widget.test + ]); + } + return _buildModule(index, data, context); + }, + ), + )), ], ))); } @@ -199,7 +206,7 @@ class _ExamplePageState extends State { exampleModuleList: widget.children, testList: widget.test, singleChild: - widget.showSingleChild ? widget.singleChild : null), + widget.showSingleChild ? widget.singleChild : null), ), TDButton( text: '返回首页', @@ -267,11 +274,11 @@ class _ExamplePageState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - if(WebMdTool.needGenerateWebMd) const TDText('WebGenTag'), + if (WebMdTool.needGenerateWebMd) const TDText('WebGenTag'), TDText( widget.title, font: TDTheme.of(context).fontHeadlineSmall, - textColor: TDTheme.of(context).fontGyColor1, + textColor: TDTheme.of(context).textColorPrimary, ), Container( margin: const EdgeInsets.only( @@ -280,7 +287,7 @@ class _ExamplePageState extends State { child: TDText( widget.desc, font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2, + textColor: TDTheme.of(context).textColorSecondary, ), ), // Expanded(child: ), @@ -299,7 +306,7 @@ class _ExamplePageState extends State { child: TDText( '${index < 10 ? "0$index" : index} ${data.title}', font: TDTheme.of(context).fontTitleLarge, - textColor: TDTheme.of(context).fontGyColor1, + textColor: TDTheme.of(context).textColorPrimary, fontWeight: FontWeight.bold, ), ), @@ -333,14 +340,15 @@ class ExampleModule { /// 示例样例数据 class ExampleItem { - const ExampleItem( - {Key? key, - this.desc = '', - required this.builder, - this.methodName, - this.center = true, - this.ignoreCode = false, - this.padding}); + const ExampleItem({ + Key? key, + this.desc = '', + required this.builder, + this.methodName, + this.center = true, + this.ignoreCode = false, + this.padding, + }); final String desc; @@ -431,7 +439,7 @@ class _ExampleItemWidgetState extends State { child: TDText( widget.data.desc, font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2, + textColor: TDTheme.of(context).textColorSecondary, ), ), child @@ -473,6 +481,8 @@ class _CodeWrapperState extends State { String? codeString; + Brightness brightness = Brightness.light; + @override void initState() { super.initState(); @@ -490,6 +500,7 @@ class _CodeWrapperState extends State { .dependOnInheritedWidgetOfExactType(); exampleCodeGroup = modelTheme?.model.codePath ?? ''; apiVisible = modelTheme?.model.apiVisible ?? false; + brightness = Theme.of(context).brightness; }); if (WebMdTool.needGenerateWebMd && !widget.isFromItem) { @@ -577,7 +588,7 @@ class _CodeWrapperState extends State { return Container( alignment: Alignment.center, decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, + color: TDTheme.of(context).bgColorSecondaryContainer, borderRadius: BorderRadius.vertical( top: Radius.circular(TDTheme.of(context).radiusDefault))), height: 500, @@ -595,10 +606,15 @@ class _CodeWrapperState extends State { ${codeString} ``` '''; + + var syntaxHighlighterStyle = brightness == Brightness.light + ? SyntaxHighlighterStyle.lightThemeStyle() + : SyntaxHighlighterStyle.darkThemeStyle(); + return Container( alignment: Alignment.center, decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, + color: TDTheme.of(context).bgColorSecondaryContainer, borderRadius: BorderRadius.vertical( top: Radius.circular(TDTheme.of(context).radiusDefault))), height: height, @@ -607,7 +623,7 @@ ${codeString} padding: EdgeInsets.zero, selectable: false, shrinkWrap: true, - syntaxHighlighter: DartSyntaxHighlighter(), + syntaxHighlighter: DartSyntaxHighlighter(syntaxHighlighterStyle), data: mdText, extensionSet: md.ExtensionSet( md.ExtensionSet.gitHubWeb.blockSyntaxes, diff --git a/tdesign-component/example/lib/base/intl_resource_delegate.dart b/tdesign-component/example/lib/base/intl_resource_delegate.dart index 33c5ac400..62d802a45 100644 --- a/tdesign-component/example/lib/base/intl_resource_delegate.dart +++ b/tdesign-component/example/lib/base/intl_resource_delegate.dart @@ -1,7 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; -import '../localizations/app_localizations.dart'; +import '../l10n/app_localizations.dart'; /// 国际化资源代理 class IntlResourceDelegate extends TDResourceDelegate { @@ -162,4 +162,8 @@ class IntlResourceDelegate extends TDResourceDelegate { @override String get top => AppLocalizations.of(context)!.top; + + @override + String get emptyData => AppLocalizations.of(context)!.emptyData; + } diff --git a/tdesign-component/example/lib/base/notification_center.dart b/tdesign-component/example/lib/base/notification_center.dart index a9d0be006..8c88b7b69 100644 --- a/tdesign-component/example/lib/base/notification_center.dart +++ b/tdesign-component/example/lib/base/notification_center.dart @@ -3,6 +3,13 @@ import 'dart:collection'; typedef Observer = void Function(dynamic arguments); /// 广播工具 +/// +/// +/// todo bug +/// flutter: TNotification postNotificationCallHandler onApiVisibleChange_165563855 error: setState() called after dispose(): _CodeWrapperState#1423d(lifecycle state: defunct, not mounted) +/// This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. +/// The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree. +/// This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose(). class TNotification { static final Map> _eventMap = HashMap(); diff --git a/tdesign-component/example/lib/component_test/image_test.dart b/tdesign-component/example/lib/component_test/image_test.dart index 50b5f73f6..e7ad3ff0b 100644 --- a/tdesign-component/example/lib/component_test/image_test.dart +++ b/tdesign-component/example/lib/component_test/image_test.dart @@ -2,10 +2,12 @@ import 'package:flutter/material.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; void main() async { - runApp(ImageTestApp()); + runApp(const ImageTestApp()); } class ImageTestApp extends StatelessWidget { + const ImageTestApp({super.key}); + @override Widget build(BuildContext context) { return MaterialApp( @@ -21,12 +23,14 @@ class ImageTestApp extends StatelessWidget { class TestPage extends StatelessWidget { final GlobalKey _formKey = GlobalKey(); + TestPage({super.key}); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: TDText('TDImage Test Page'), + title: const TDText('TDImage Test Page'), ), body: Form( key: _formKey, @@ -38,9 +42,9 @@ class TestPage extends StatelessWidget { width: 335, fit: BoxFit.fitWidth, ), - SizedBox(height: 20), + const SizedBox(height: 20), - TDImage( + const TDImage( imgUrl: 'assets/img/image.png', type: TDImageType.fitHeight, height: 144, diff --git a/tdesign-component/example/lib/component_test/popup_test.dart b/tdesign-component/example/lib/component_test/popup_test.dart index 901f4c1ef..d81aff2ea 100644 --- a/tdesign-component/example/lib/component_test/popup_test.dart +++ b/tdesign-component/example/lib/component_test/popup_test.dart @@ -34,16 +34,16 @@ class _TestPageState extends State { slideTransitionFrom: SlideTransitionFrom.bottom, builder: (context) { return TDPopupBottomDisplayPanel( - title: "title", + title: 'title', radius: 20, - backgroundColor: Color(0xFFFAFFFC), + backgroundColor: const Color(0xFFFAFFFC), closeClick: () { Navigator.maybePop(context); }, child: Container( - padding: EdgeInsets.only(left: 20, right: 20, bottom: 33), - decoration: BoxDecoration(color: Colors.white), - child: Column( + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 33), + decoration: const BoxDecoration(color: Colors.white), + child: const Column( children: [ Center( child: Text("立即拨打"), diff --git a/tdesign-component/example/lib/component_test/step_test.dart b/tdesign-component/example/lib/component_test/step_test.dart index b37246cf4..9f5975d43 100644 --- a/tdesign-component/example/lib/component_test/step_test.dart +++ b/tdesign-component/example/lib/component_test/step_test.dart @@ -2,10 +2,12 @@ import 'package:flutter/material.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; void main() async { - runApp(StepTestApp()); + runApp(const StepTestApp()); } class StepTestApp extends StatelessWidget { + const StepTestApp({super.key}); + @override Widget build(BuildContext context) { return MaterialApp( @@ -21,6 +23,8 @@ class StepTestApp extends StatelessWidget { class TestPage extends StatelessWidget { final GlobalKey _formKey = GlobalKey(); + TestPage({super.key}); + @override Widget build(BuildContext context) { // 创建水平步骤条的数据 @@ -56,7 +60,7 @@ class TestPage extends StatelessWidget { return Scaffold( appBar: AppBar( - title: TDText('TDSteps Test Page'), + title: const TDText('TDSteps Test Page'), ), body: Form( key: _formKey, diff --git a/tdesign-component/example/lib/component_test/tabbar_test.dart b/tdesign-component/example/lib/component_test/tabbar_test.dart index 1bd118624..c0030c23c 100644 --- a/tdesign-component/example/lib/component_test/tabbar_test.dart +++ b/tdesign-component/example/lib/component_test/tabbar_test.dart @@ -2,7 +2,6 @@ import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; -import 'package:tdesign_flutter/src/util/string_util.dart'; // import 'package:xjy_study/utils/color_util.dart'; class StudyDetail extends StatefulWidget { @@ -51,10 +50,10 @@ class _StudyDetailState extends State with SingleTickerProviderStateMixin { ), body: ExtendedNestedScrollView( onlyOneScrollInBody: true, - physics: ClampingScrollPhysics(), + physics: const ClampingScrollPhysics(), headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return [ - SliverToBoxAdapter( + const SliverToBoxAdapter( child: _CourseItemDetail(), ) ]; @@ -115,7 +114,7 @@ class _CourseItemDetail extends StatelessWidget { height: 16.h, alignment: Alignment.center, padding: EdgeInsets.symmetric(horizontal: 6.w), - decoration: BoxDecoration( + decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(4)), gradient: LinearGradient(colors: [ Color(0xFFFFB442), diff --git a/tdesign-component/example/lib/component_test/tag_test.dart b/tdesign-component/example/lib/component_test/tag_test.dart index 45e11c1bf..c1d8fb3ba 100644 --- a/tdesign-component/example/lib/component_test/tag_test.dart +++ b/tdesign-component/example/lib/component_test/tag_test.dart @@ -2,10 +2,12 @@ import 'package:flutter/material.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; void main() async { - runApp(TagTestApp()); + runApp(const TagTestApp()); } class TagTestApp extends StatelessWidget { + const TagTestApp({super.key}); + @override Widget build(BuildContext context) { return MaterialApp( @@ -13,17 +15,19 @@ class TagTestApp extends StatelessWidget { theme: ThemeData( primarySwatch: Colors.blue, ), - home: TestPage(), + home: const TestPage(), ); } } class TestPage extends StatelessWidget { + const TestPage({super.key}); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: TDText('TDTag 宽度测试'), + title: const TDText('TDTag 宽度测试'), ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), @@ -40,15 +44,15 @@ class TestPage extends StatelessWidget { } Widget _buildSection(BuildContext context) { - return Column( + return const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TDText('不带宽度测试', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - const SizedBox(height: 12), + SizedBox(height: 12), Wrap( spacing: 12, runSpacing: 12, - children: const [ + children: [ TDTag('1', theme: TDTagTheme.primary, size: TDTagSize.medium, @@ -61,21 +65,21 @@ class TestPage extends StatelessWidget { ), ], ), - const SizedBox(height: 24), + SizedBox(height: 24), ], ); } Widget _buildFixedWidthSection(BuildContext context) { - return Column( + return const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TDText('基础固定宽度测试', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - const SizedBox(height: 12), + SizedBox(height: 12), Wrap( spacing: 12, runSpacing: 12, - children: const [ + children: [ TDTag('1', fixedWidth: 80, theme: TDTagTheme.primary, @@ -91,7 +95,7 @@ class TestPage extends StatelessWidget { ), ], ), - const SizedBox(height: 24), + SizedBox(height: 24), ], ); } @@ -100,7 +104,7 @@ class TestPage extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - TDText('边界情况测试', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + const TDText('边界情况测试', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), const SizedBox(height: 12), const TDTag('超长文本测试超长文本测试超长文本测试超长文本测试', fixedWidth: 100, diff --git a/tdesign-component/example/lib/component_test/test_app.dart b/tdesign-component/example/lib/component_test/test_app.dart index 21c062d92..243da0aea 100644 --- a/tdesign-component/example/lib/component_test/test_app.dart +++ b/tdesign-component/example/lib/component_test/test_app.dart @@ -48,7 +48,7 @@ Padding body(BuildContext context) { mainAxisAlignment: MainAxisAlignment.center, children: [ - TDButton(text: "ixanshi ",onTap: (){ + TDButton(text: 'ixanshi ',onTap: (){ TDLoadingController.show(context); TDLoadingController.dismiss(); @@ -175,7 +175,7 @@ TDBottomTabBar _buildBottomTabBar() { ), TDBottomTabBarTabConfig( selectedIcon: Icon(TDIcons.user, size: iconSize, color: Colors.red), - unselectedIcon: Icon(TDIcons.user, size: iconSize, color: Color(0xFF383838)), + unselectedIcon: Icon(TDIcons.user, size: iconSize, color: const Color(0xFF383838)), tabText: '我的', selectTabTextStyle: TextStyle(fontSize: textSize, color: Colors.red), unselectTabTextStyle: TextStyle(fontSize: textSize, color: Colors.black), diff --git a/tdesign-component/example/lib/config.dart b/tdesign-component/example/lib/config.dart index 2ca80a677..ce857c490 100644 --- a/tdesign-component/example/lib/config.dart +++ b/tdesign-component/example/lib/config.dart @@ -29,12 +29,12 @@ import 'page/td_empty_page.dart'; import 'page/td_fab_page.dart'; import 'page/td_font_page.dart'; import 'page/td_footer_page.dart'; +import 'page/td_form_page.dart'; import 'page/td_icon_page.dart'; import 'page/td_image_page.dart'; import 'page/td_image_viewer_page.dart'; import 'page/td_indexes_page.dart'; import 'page/td_input_page.dart'; -import 'page/td_form_page.dart'; import 'page/td_link_page.dart'; import 'page/td_loading_page.dart'; import 'page/td_message_page.dart'; @@ -56,7 +56,6 @@ import 'page/td_slider_page.dart'; import 'page/td_stepper_page.dart'; import 'page/td_steps_page.dart'; import 'page/td_swipe_cell_page.dart'; -import 'page/td_steps_page.dart'; import 'page/td_swiper_page.dart'; import 'page/td_switch_page.dart'; import 'page/td_table_page.dart'; @@ -83,15 +82,29 @@ List examplePageList = []; Map> exampleMap = { '基础': [ ExamplePageModel( - text: 'Button 按钮', name: 'button', pageBuilder: _wrapInheritedTheme((context) => const TDButtonPage())), + text: 'Button 按钮', + name: 'button', + pageBuilder: _wrapInheritedTheme((context) => const TDButtonPage())), + ExamplePageModel( + text: 'Divider 分割线', + name: 'divider', + pageBuilder: _wrapInheritedTheme((context) => const TDDividerPage())), ExamplePageModel( - text: 'Divider 分割线', name: 'divider', pageBuilder: _wrapInheritedTheme((context) => const TDDividerPage())), + text: 'Fab 悬浮按钮', + name: 'fab', + pageBuilder: _wrapInheritedTheme((context) => const TDFabPage())), ExamplePageModel( - text: 'Fab 悬浮按钮', name: 'fab', pageBuilder: _wrapInheritedTheme((context) => const TDFabPage())), - ExamplePageModel(text: 'Icon 图标', name: 'icon', pageBuilder: _wrapInheritedTheme((context) => const TDIconPage())), + text: 'Icon 图标', + name: 'icon', + pageBuilder: _wrapInheritedTheme((context) => const TDIconPage())), ExamplePageModel( - text: 'Link 链接', name: 'link', pageBuilder: _wrapInheritedTheme((context) => const TDLinkViewPage())), - ExamplePageModel(text: 'Text 文本', name: 'text', pageBuilder: _wrapInheritedTheme((context) => const TDTextPage())), + text: 'Link 链接', + name: 'link', + pageBuilder: _wrapInheritedTheme((context) => const TDLinkViewPage())), + ExamplePageModel( + text: 'Text 文本', + name: 'text', + pageBuilder: _wrapInheritedTheme((context) => const TDTextPage())), ], '导航': [ ExamplePageModel( @@ -108,14 +121,27 @@ Map> exampleMap = { name: 'indexes', pageBuilder: _wrapInheritedTheme((context) => const TDIndexesPage())), ExamplePageModel( - text: 'NavBar 导航栏', name: 'navbar', pageBuilder: _wrapInheritedTheme((context) => const TDNavBarPage())), + text: 'NavBar 导航栏', + name: 'navbar', + pageBuilder: _wrapInheritedTheme((context) => const TDNavBarPage())), + ExamplePageModel( + text: 'SideBar 侧边栏', + name: 'side-bar', + pageBuilder: _wrapInheritedTheme((context) => const TDSideBarPage())), ExamplePageModel( - text: 'SideBar 侧边栏', name: 'side-bar',pageBuilder: _wrapInheritedTheme((context) => const TDSideBarPage())), - ExamplePageModel(text: 'Steps 步骤条', name: 'steps', pageBuilder: _wrapInheritedTheme((context) => const TDStepsPage())), + text: 'Steps 步骤条', + name: 'steps', + pageBuilder: _wrapInheritedTheme((context) => const TDStepsPage())), ExamplePageModel( - text: 'TabBar 标签栏', name: 'tab-bar', - pageName: 'bottom_tab_bar',pageBuilder: _wrapInheritedTheme((context) => const TDBottomTabBarPage())), - ExamplePageModel(text: 'Tabs 选项卡', name: 'tabs', pageBuilder: _wrapInheritedTheme((context) => const TDTabsPage())), + text: 'TabBar 标签栏', + name: 'tab-bar', + pageName: 'bottom_tab_bar', + pageBuilder: + _wrapInheritedTheme((context) => const TDBottomTabBarPage())), + ExamplePageModel( + text: 'Tabs 选项卡', + name: 'tabs', + pageBuilder: _wrapInheritedTheme((context) => const TDTabsPage())), ], '输入': [ ExamplePageModel( @@ -127,30 +153,51 @@ Map> exampleMap = { name: 'cascader', pageBuilder: _wrapInheritedTheme((context) => const TDCascaderPage())), ExamplePageModel( - text: 'Checkbox 多选框', name: 'checkbox', pageBuilder: _wrapInheritedTheme((context) => const TDCheckboxPage())), + text: 'Checkbox 多选框', + name: 'checkbox', + pageBuilder: _wrapInheritedTheme((context) => const TDCheckboxPage())), ExamplePageModel( text: 'DateTimePicker 时间选择器', name: 'date-time-picker', pageName: 'data_picker', - pageBuilder: _wrapInheritedTheme((context) => const TDDatePickerPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDDatePickerPage())), ExamplePageModel( - text: 'Form 表单', name: 'form', pageBuilder: _wrapInheritedTheme((context) => const TDFormPage())), + text: 'Form 表单', + name: 'form', + pageBuilder: _wrapInheritedTheme((context) => const TDFormPage())), ExamplePageModel( - text: 'Input 输入框', name: 'input', pageBuilder: _wrapInheritedTheme((context) => const TDInputViewPage())), + text: 'Input 输入框', + name: 'input', + pageBuilder: _wrapInheritedTheme((context) => const TDInputViewPage())), ExamplePageModel( - text: 'Picker 选择器', name: 'picker', pageBuilder: _wrapInheritedTheme((context) => const TDPickerPage())), + text: 'Picker 选择器', + name: 'picker', + pageBuilder: _wrapInheritedTheme((context) => const TDPickerPage())), ExamplePageModel( - text: 'Radio 单选框', name: 'radio', pageBuilder: _wrapInheritedTheme((context) => const TDRadioPage())), + text: 'Radio 单选框', + name: 'radio', + pageBuilder: _wrapInheritedTheme((context) => const TDRadioPage())), ExamplePageModel( - text: 'Rate 评分', name: 'rate', pageBuilder: _wrapInheritedTheme((context) => const TDRatePage())), + text: 'Rate 评分', + name: 'rate', + pageBuilder: _wrapInheritedTheme((context) => const TDRatePage())), ExamplePageModel( - text: 'Search 搜索框', name: 'search', pageBuilder: _wrapInheritedTheme((context) => const TDSearchBarPage())), + text: 'Search 搜索框', + name: 'search', + pageBuilder: _wrapInheritedTheme((context) => const TDSearchBarPage())), ExamplePageModel( - text: 'Slider 滑动选择器', name: 'slider', pageBuilder: _wrapInheritedTheme((context) => const TDSliderPage())), + text: 'Slider 滑动选择器', + name: 'slider', + pageBuilder: _wrapInheritedTheme((context) => const TDSliderPage())), ExamplePageModel( - text: 'Stepper 步进器', name: 'stepper', pageBuilder: _wrapInheritedTheme((context) => const TDStepperPage())), + text: 'Stepper 步进器', + name: 'stepper', + pageBuilder: _wrapInheritedTheme((context) => const TDStepperPage())), ExamplePageModel( - text: 'Switch 开关', name: 'switch', pageBuilder: _wrapInheritedTheme((context) => const TDSwitchPage())), + text: 'Switch 开关', + name: 'switch', + pageBuilder: _wrapInheritedTheme((context) => const TDSwitchPage())), ExamplePageModel( text: 'Textarea 多行文本框', name: 'textarea', @@ -159,7 +206,8 @@ Map> exampleMap = { text: 'TreeSelect 树形选择器', name: 'tree-select', pageName: 'tree_select', - pageBuilder: _wrapInheritedTheme((context) => const TDTreeSelectPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDTreeSelectPage())), ExamplePageModel( text: 'Upload 上传', name: 'upload', @@ -167,32 +215,49 @@ Map> exampleMap = { ], '数据展示': [ ExamplePageModel( - text: 'Avatar 头像', name: 'avatar', pageBuilder: _wrapInheritedTheme((context) => const TDAvatarPage())), + text: 'Avatar 头像', + name: 'avatar', + pageBuilder: _wrapInheritedTheme((context) => const TDAvatarPage())), ExamplePageModel( - text: 'Badge 徽标', name: 'badge', pageBuilder: _wrapInheritedTheme((context) => const TDBadgePage())), + text: 'Badge 徽标', + name: 'badge', + pageBuilder: _wrapInheritedTheme((context) => const TDBadgePage())), ExamplePageModel( - text: 'Cell 单元格', name: 'cell', pageBuilder: _wrapInheritedTheme((context) => const TDCellPage())), + text: 'Cell 单元格', + name: 'cell', + pageBuilder: _wrapInheritedTheme((context) => const TDCellPage())), ExamplePageModel( text: 'TimeCounter 计时器', name: 'time-counter', - pageBuilder: _wrapInheritedTheme((context) => const TDTimeCounterPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDTimeCounterPage())), ExamplePageModel( text: 'Collapse 折叠面板', name: 'collapse', pageBuilder: _wrapInheritedTheme((context) => const TDCollapsePage())), ExamplePageModel( - text: 'Empty 空状态', name: 'empty', pageBuilder: _wrapInheritedTheme((context) => const TDEmptyPage())), + text: 'Empty 空状态', + name: 'empty', + pageBuilder: _wrapInheritedTheme((context) => const TDEmptyPage())), ExamplePageModel( - text: 'Footer 页脚', name: 'footer', pageBuilder: _wrapInheritedTheme((context) => const TDFooterPage())), + text: 'Footer 页脚', + name: 'footer', + pageBuilder: _wrapInheritedTheme((context) => const TDFooterPage())), ExamplePageModel( - text: 'Grid 宫格', name: 'grid', isTodo: true, pageBuilder: _wrapInheritedTheme((context) => const TodoPage())), + text: 'Grid 宫格', + name: 'grid', + isTodo: true, + pageBuilder: _wrapInheritedTheme((context) => const TodoPage())), ExamplePageModel( - text: 'Image 图片', name: 'image', pageBuilder: _wrapInheritedTheme((context) => const TDImagePage())), + text: 'Image 图片', + name: 'image', + pageBuilder: _wrapInheritedTheme((context) => const TDImagePage())), ExamplePageModel( text: 'ImageViewer 图片预览', name: 'image-viewer', pageName: 'image_viewer', - pageBuilder: _wrapInheritedTheme((context) => const TDImageViewerPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDImageViewerPage())), ExamplePageModel( text: 'Progress 进度条', name: 'progress', @@ -211,58 +276,94 @@ Map> exampleMap = { isTodo: true, pageBuilder: _wrapInheritedTheme((context) => const TodoPage())), ExamplePageModel( - text: 'Swiper 轮播图', name: 'swiper', pageBuilder: _wrapInheritedTheme((context) => const TDSwiperPage())), - ExamplePageModel(text: 'Table 表格', name: 'table', pageBuilder: _wrapInheritedTheme((context) => const TDTablePage())), - ExamplePageModel(text: 'Tag 标签', name: 'tag', pageBuilder: _wrapInheritedTheme((context) => const TDTagPage())), + text: 'Swiper 轮播图', + name: 'swiper', + pageBuilder: _wrapInheritedTheme((context) => const TDSwiperPage())), + ExamplePageModel( + text: 'Table 表格', + name: 'table', + pageBuilder: _wrapInheritedTheme((context) => const TDTablePage())), + ExamplePageModel( + text: 'Tag 标签', + name: 'tag', + pageBuilder: _wrapInheritedTheme((context) => const TDTagPage())), ], '反馈': [ - ExamplePageModel( + ExamplePageModel( text: 'ActionSheet 动作面板', name: 'action-sheet', pageName: 'action_sheet', - pageBuilder: _wrapInheritedTheme((context) => const TDActionSheetPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDActionSheetPage())), ExamplePageModel( - text: 'Dialog 对话框', name: 'dialog', pageBuilder: _wrapInheritedTheme((context) => const TDDialogPage())), + text: 'Dialog 对话框', + name: 'dialog', + pageBuilder: _wrapInheritedTheme((context) => const TDDialogPage())), ExamplePageModel( text: 'DropdownMenu 下拉菜单', name: 'dropdown-menu', pageName: 'dropdown_menu', - pageBuilder: _wrapInheritedTheme((context) => const TDDropdownMenuPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDDropdownMenuPage())), ExamplePageModel( - text: 'Loading 加载', name: 'loading', pageBuilder: _wrapInheritedTheme((context) => const TDLoadingPage())), + text: 'Loading 加载', + name: 'loading', + pageBuilder: _wrapInheritedTheme((context) => const TDLoadingPage())), ExamplePageModel( - text: 'Message 全局提示', + text: 'Message 消息通知', name: 'message', pageBuilder: _wrapInheritedTheme((context) => const TDMessagePage())), ExamplePageModel( - text: 'NoticeBar 消息提醒', name: 'notice-bar', pageBuilder: _wrapInheritedTheme((context) => const TDNoticeBarPage())), + text: 'NoticeBar 公告栏', + name: 'notice-bar', + pageBuilder: _wrapInheritedTheme((context) => const TDNoticeBarPage())), ExamplePageModel( text: 'Overlay 遮罩层', name: 'overlay', isTodo: true, pageBuilder: _wrapInheritedTheme((context) => const TodoPage())), - ExamplePageModel(text: 'Popover 弹出气泡', name: 'popover', pageBuilder: _wrapInheritedTheme((context) => const TDPopoverPage())), ExamplePageModel( - text: 'Popup 弹出层', name: 'popup', pageBuilder: _wrapInheritedTheme((context) => const TDPopupPage())), + text: 'Popover 弹出气泡', + name: 'popover', + pageBuilder: _wrapInheritedTheme((context) => const TDPopoverPage())), + ExamplePageModel( + text: 'Popup 弹出层', + name: 'popup', + pageBuilder: _wrapInheritedTheme((context) => const TDPopupPage())), ExamplePageModel( text: 'PullDownRefresh 下拉刷新', name: 'pull-down-refresh', pageName: 'refresh', - pageBuilder: _wrapInheritedTheme((context) => const TdPullDownRefreshPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TdPullDownRefreshPage())), ExamplePageModel( text: 'Swipecell 滑动操作', name: 'swipe-cell', pageName: 'swipe_cell', pageBuilder: _wrapInheritedTheme((context) => const TDSwipeCellPage())), ExamplePageModel( - text: 'Toast 轻提示', name: 'toast', pageBuilder: _wrapInheritedTheme((context) => const TDToastPage())), + text: 'Toast 轻提示', + name: 'toast', + pageBuilder: _wrapInheritedTheme((context) => const TDToastPage())), ], '主题': [ ExamplePageModel( - text: '颜色', name: 'theme_colors', pageBuilder: _wrapInheritedTheme((context) => const TDThemeColorsPage())), - ExamplePageModel(text: '字体', name: 'font', pageBuilder: _wrapInheritedTheme((context) => const TDFontPage())), - ExamplePageModel(text: '圆角', name: 'radius', pageBuilder: _wrapInheritedTheme((context) => const TDRadiusPage())), - ExamplePageModel(text: '阴影', name: 'shadows', pageBuilder: _wrapInheritedTheme((context) => const TDShadowsPage())), + text: '颜色', + name: 'theme_colors', + pageBuilder: + _wrapInheritedTheme((context) => const TDThemeColorsPage())), + ExamplePageModel( + text: '字体', + name: 'font', + pageBuilder: _wrapInheritedTheme((context) => const TDFontPage())), + ExamplePageModel( + text: '圆角', + name: 'radius', + pageBuilder: _wrapInheritedTheme((context) => const TDRadiusPage())), + ExamplePageModel( + text: '阴影', + name: 'shadows', + pageBuilder: _wrapInheritedTheme((context) => const TDShadowsPage())), ], }; @@ -272,12 +373,14 @@ List sideBarExamplePage = [ name: 'SideBarPagination', isTodo: false, showAction: false, - pageBuilder: _wrapInheritedTheme((context) => const TDSideBarPaginationPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDSideBarPaginationPage())), ExamplePageModel( text: 'SideBar 锚点', name: 'SideBarAnchor', isTodo: false, - pageBuilder: _wrapInheritedTheme((context) => const TDSideBarAnchorPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDSideBarAnchorPage())), ExamplePageModel( text: 'SideBar 带图标', name: 'SideBarIcon', @@ -287,20 +390,24 @@ List sideBarExamplePage = [ text: 'SideBar 非通栏选项样式', name: 'SideBarOutline', isTodo: false, - pageBuilder: _wrapInheritedTheme((context) => const TDSideBarOutlinePage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDSideBarOutlinePage())), ExamplePageModel( text: 'SideBar 自定义样式', name: 'SideBarCustom', isTodo: false, - pageBuilder: _wrapInheritedTheme((context) => const TDSideBarCustomPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDSideBarCustomPage())), ExamplePageModel( text: 'SideBar 延迟加载', name: 'SideBarLoading', isTodo: false, - pageBuilder: _wrapInheritedTheme((context) => const TDSideBarLoadingPage())), + pageBuilder: + _wrapInheritedTheme((context) => const TDSideBarLoadingPage())), ExamplePageModel( text: 'SideBar 自定义未选中颜色', name: 'SideBarUnselectedColor', isTodo: false, - pageBuilder: _wrapInheritedTheme((context) => const TDSideBarUnSelectedColorPage())) + pageBuilder: _wrapInheritedTheme( + (context) => const TDSideBarUnSelectedColorPage())) ]; diff --git a/tdesign-component/example/lib/home.dart b/tdesign-component/example/lib/home.dart index 76003cfcb..40fb5e907 100644 --- a/tdesign-component/example/lib/home.dart +++ b/tdesign-component/example/lib/home.dart @@ -6,19 +6,25 @@ import 'base/example_base.dart'; import 'base/example_route.dart'; import 'base/web_md_tool.dart'; import 'config.dart'; -import 'localizations/app_localizations.dart'; +import 'l10n/app_localizations.dart'; var _kShowTodoComponent = false; /// 切换主题的回调 -typedef OnThemeChange = Function(TDThemeData themeData); +typedef OnThemeChange = Function(TDThemeData themeData, bool isDark); /// 切换语言的回调 typedef OnLocaleChange = Function(Locale locale); /// 示例首页 class MyHomePage extends StatefulWidget { - const MyHomePage({Key? key, required this.title, this.onThemeChange, this.locale, this.onLocaleChange,}) : super(key: key); + const MyHomePage({ + Key? key, + required this.title, + this.onThemeChange, + this.locale, + this.onLocaleChange, + }) : super(key: key); final String title; @@ -58,48 +64,49 @@ class _MyHomePageState extends State { // Here we take the value from the MyHomePage object that was created by // the App.build method, and use it to set our appbar title. backgroundColor: TDTheme.of(context).brandNormalColor, - titleTextStyle: TextStyle(color:TDTheme.of(context).whiteColor1, fontSize: TDTheme.of(context).fontTitleLarge?.size), + titleTextStyle: TextStyle( + color: TDTheme.of(context).whiteColor1, + fontSize: TDTheme.of(context).fontTitleLarge?.size), title: Text(widget.title), actions: ScreenUtil.isWebLargeScreen(context) ? null : [ - - GestureDetector( - child: Container( - alignment: Alignment.centerRight, - padding: const EdgeInsets.only( - right: 16, - ), - child: TDText( - widget.locale?.languageCode == 'en' ? '中文' : 'English', - textColor: TDTheme.of(context).whiteColor1, - ), - ), - onTap: () { - if(widget.locale?.languageCode == 'en') { - widget.onLocaleChange?.call(const Locale('zh')); - } else { - widget.onLocaleChange?.call(const Locale('en')); - } - }, - ), - GestureDetector( - child: Container( - alignment: Alignment.centerRight, - padding: const EdgeInsets.only( - right: 16, - ), - child: TDText( - AppLocalizations.of(context)?.about, - textColor: TDTheme.of(context).whiteColor1, - ), - ), - onTap: () { - focusNode.unfocus(); - Navigator.pushNamed(context, TDExampleRoute.aboutPath); - }, - ) - ], + GestureDetector( + child: Container( + alignment: Alignment.centerRight, + padding: const EdgeInsets.only( + right: 16, + ), + child: TDText( + widget.locale?.languageCode == 'en' ? '中文' : 'English', + textColor: TDTheme.of(context).whiteColor1, + ), + ), + onTap: () { + if (widget.locale?.languageCode == 'en') { + widget.onLocaleChange?.call(const Locale('zh')); + } else { + widget.onLocaleChange?.call(const Locale('en')); + } + }, + ), + GestureDetector( + child: Container( + alignment: Alignment.centerRight, + padding: const EdgeInsets.only( + right: 16, + ), + child: TDText( + AppLocalizations.of(context)?.about, + textColor: TDTheme.of(context).whiteColor1, + ), + ), + onTap: () { + focusNode.unfocus(); + Navigator.pushNamed(context, TDExampleRoute.aboutPath); + }, + ) + ], ), body: _buildBody(context), ); @@ -108,14 +115,14 @@ class _MyHomePageState extends State { Widget _buildBody(BuildContext context) { return SafeArea( child: Align( - alignment: Alignment.topCenter, - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: _buildChildren(context), - ), - ), - )); + alignment: Alignment.topCenter, + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: _buildChildren(context), + ), + ), + )); } List _buildChildren(BuildContext context) { @@ -127,39 +134,70 @@ class _MyHomePageState extends State { child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Container( - constraints: BoxConstraints(minWidth: MediaQuery.of(context).size.width), + constraints: + BoxConstraints(minWidth: MediaQuery.of(context).size.width), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Padding(padding: const EdgeInsets.only(left: 8, right: 4),child: TDTheme( - data: TDThemeData.defaultData(), - child: TDButton( - text: AppLocalizations.of(context)?.defaultTheme, - theme: TDButtonTheme.primary, - onTap: () { - widget.onThemeChange?.call(TDTheme.defaultData()); - }, - )),), - Padding(padding: const EdgeInsets.only(left: 4, right: 4),child: TDTheme( - data: TDThemeData.fromJson('green', greenThemeConfig) ?? TDThemeData.defaultData(), - child: TDButton( - text: AppLocalizations.of(context)?.greenTheme, + Padding( + padding: const EdgeInsets.only(left: 8, right: 4), + child: TDTheme( + data: TDThemeData.defaultData(), + child: TDButton( + text: AppLocalizations.of(context)?.defaultTheme, theme: TDButtonTheme.primary, - onTap: () async { - var jsonString = await rootBundle.loadString('assets/theme.json'); - var newData = TDThemeData.fromJson('green', jsonString); - widget.onThemeChange?.call(newData ?? TDTheme.defaultData()); - }))), - Padding(padding: const EdgeInsets.only(left: 4, right: 8),child: TDTheme( - data: TDThemeData.fromJson('red', greenThemeConfig) ?? TDThemeData.defaultData(), + onTap: () { + widget.onThemeChange + ?.call(TDTheme.defaultData(), false); + }, + )), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: TDTheme( + data: TDThemeData.fromJson('green', greenThemeConfig) ?? + TDThemeData.defaultData(), + child: TDButton( + text: AppLocalizations.of(context)?.greenTheme, + theme: TDButtonTheme.primary, + onTap: () async { + var jsonString = await rootBundle + .loadString('assets/theme.json'); + var newData = + TDThemeData.fromJson('green', jsonString); + widget.onThemeChange + ?.call(newData ?? TDTheme.defaultData(), false); + }))), + Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: TDTheme( + data: TDThemeData.fromJson('red', greenThemeConfig) ?? + TDThemeData.defaultData(), + child: TDButton( + text: AppLocalizations.of(context)?.redTheme, + theme: TDButtonTheme.danger, + onTap: () async { + var jsonString = await rootBundle + .loadString('assets/theme.json'); + var newData = + TDThemeData.fromJson('red', jsonString); + widget.onThemeChange + ?.call(newData ?? TDTheme.defaultData(), false); + }))), + Padding( + padding: const EdgeInsets.only(left: 4, right: 8), child: TDButton( - text: AppLocalizations.of(context)?.redTheme, - theme: TDButtonTheme.danger, + text: AppLocalizations.of(context)?.darkTheme, + style: TDButtonStyle( + backgroundColor: Colors.black, + textColor: Colors.white), onTap: () async { - var jsonString = await rootBundle.loadString('assets/theme.json'); - var newData = TDThemeData.fromJson('red', jsonString); - widget.onThemeChange?.call(newData ?? TDTheme.defaultData()); - }))), + var jsonString = + await rootBundle.loadString('assets/theme.json'); + var newData = TDThemeData.fromJson('dark', jsonString); + widget.onThemeChange + ?.call(newData ?? TDTheme.defaultData(), true); + })), ], ), ), @@ -169,7 +207,7 @@ class _MyHomePageState extends State { children.add(TDSearchBar( placeHolder: '请输入组件名称', focusNode: focusNode, - onTextChanged: (value){ + onTextChanged: (value) { setState(() { searchText = value; }); @@ -179,7 +217,8 @@ class _MyHomePageState extends State { exampleMap.forEach((key, value) { var subList = []; value.forEach((model) { - if(searchText.isNotEmpty && !model.text.toLowerCase().contains(searchText.toLowerCase())){ + if (searchText.isNotEmpty && + !model.text.toLowerCase().contains(searchText.toLowerCase())) { // 如果有搜索文案,不再搜索中的组件不展示 return; } @@ -187,7 +226,8 @@ class _MyHomePageState extends State { if (model.isTodo) { if (_kShowTodoComponent) { children.add(Padding( - padding: const EdgeInsets.only(left: 40, right: 40, top: 8, bottom: 8), + padding: + const EdgeInsets.only(left: 40, right: 40, top: 8, bottom: 8), child: TDButton( size: TDButtonSize.medium, type: TDButtonType.outline, @@ -202,7 +242,8 @@ class _MyHomePageState extends State { } } else { subList.add(Padding( - padding: const EdgeInsets.only(left: 40, right: 40, top: 8, bottom: 8), + padding: + const EdgeInsets.only(left: 40, right: 40, top: 8, bottom: 8), child: TDButton( size: TDButtonSize.medium, type: TDButtonType.outline, @@ -222,7 +263,8 @@ class _MyHomePageState extends State { padding: const EdgeInsets.only(left: 12), decoration: BoxDecoration( color: TDTheme.of(context).brandHoverColor, - borderRadius: BorderRadius.only(topRight: Radius.circular(TDTheme.of(context).radiusLarge))), + borderRadius: BorderRadius.only( + topRight: Radius.circular(TDTheme.of(context).radiusLarge))), child: TDText( '$key(${subList.length})', textColor: TDTheme.of(context).whiteColor1, @@ -234,7 +276,6 @@ class _MyHomePageState extends State { } } - String greenThemeConfig = ''' { "green": { diff --git a/tdesign-component/example/lib/l10n/app_en.arb b/tdesign-component/example/lib/l10n/app_en.arb index c67879ea5..cae39ff55 100644 --- a/tdesign-component/example/lib/l10n/app_en.arb +++ b/tdesign-component/example/lib/l10n/app_en.arb @@ -4,6 +4,7 @@ "defaultTheme": "defaultTheme", "greenTheme": "greenTheme", "redTheme": "redTheme", + "darkTheme": "Dark Mode", "cancel": "Cancel", "confirm": "Confirm", "switchClose": "C", @@ -54,7 +55,8 @@ "yearLabel": "year", "monthLabel": "month", "dateLabel": "date", - "weeks":"weeks", - "back":"BACK", - "top":"TOP" + "weeks": "weeks", + "back": "BACK", + "top": "TOP", + "emptyData": "No Data" } \ No newline at end of file diff --git a/tdesign-component/example/lib/l10n/app_localizations.dart b/tdesign-component/example/lib/l10n/app_localizations.dart index fb3b78236..0c487ecb9 100644 --- a/tdesign-component/example/lib/l10n/app_localizations.dart +++ b/tdesign-component/example/lib/l10n/app_localizations.dart @@ -128,6 +128,12 @@ abstract class AppLocalizations { /// **'redTheme'** String get redTheme; + /// No description provided for @darkTheme. + /// + /// In en, this message translates to: + /// **'Dark Mode'** + String get darkTheme; + /// No description provided for @cancel. /// /// In en, this message translates to: @@ -421,6 +427,12 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'TOP'** String get top; + + /// No description provided for @emptyData. + /// + /// In en, this message translates to: + /// **'No Data'** + String get emptyData; } class _AppLocalizationsDelegate diff --git a/tdesign-component/example/lib/l10n/app_localizations_en.dart b/tdesign-component/example/lib/l10n/app_localizations_en.dart index 28c285fc6..e6a4729ca 100644 --- a/tdesign-component/example/lib/l10n/app_localizations_en.dart +++ b/tdesign-component/example/lib/l10n/app_localizations_en.dart @@ -23,6 +23,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get redTheme => 'redTheme'; + @override + String get darkTheme => 'Dark Mode'; + @override String get cancel => 'Cancel'; @@ -169,4 +172,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get top => 'TOP'; + + @override + String get emptyData => 'No Data'; } diff --git a/tdesign-component/example/lib/l10n/app_localizations_zh.dart b/tdesign-component/example/lib/l10n/app_localizations_zh.dart index ec680e409..4d2443382 100644 --- a/tdesign-component/example/lib/l10n/app_localizations_zh.dart +++ b/tdesign-component/example/lib/l10n/app_localizations_zh.dart @@ -23,6 +23,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get redTheme => '红色主题'; + @override + String get darkTheme => '暗黑模式'; + @override String get cancel => '取消'; @@ -169,4 +172,7 @@ class AppLocalizationsZh extends AppLocalizations { @override String get top => '顶部'; + + @override + String get emptyData => '暂无数据'; } diff --git a/tdesign-component/example/lib/l10n/app_zh.arb b/tdesign-component/example/lib/l10n/app_zh.arb index 70291ef8c..9a645bda6 100644 --- a/tdesign-component/example/lib/l10n/app_zh.arb +++ b/tdesign-component/example/lib/l10n/app_zh.arb @@ -4,6 +4,7 @@ "defaultTheme": "默认主题", "greenTheme": "绿色主题", "redTheme": "红色主题", + "darkTheme": "暗黑模式", "cancel": "取消", "confirm": "确认", "switchClose": "关", @@ -54,7 +55,8 @@ "yearLabel":"年", "monthLabel": "月", "dateLabel": "日", - "weeks":"周", - "back":"返回", - "top":"顶部" + "weeks": "周", + "back": "返回", + "top": "顶部", + "emptyData": "暂无数据" } \ No newline at end of file diff --git a/tdesign-component/example/lib/localizations/app_localizations.dart b/tdesign-component/example/lib/localizations/app_localizations.dart deleted file mode 100644 index 325ca5287..000000000 --- a/tdesign-component/example/lib/localizations/app_localizations.dart +++ /dev/null @@ -1,457 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:intl/intl.dart' as intl; - -import 'app_localizations_en.dart'; -import '../localizations/app_localizations_zh.dart'; - -// ignore_for_file: type=lint - -/// Callers can lookup localized strings with an instance of AppLocalizations -/// returned by `AppLocalizations.of(context)`. -/// -/// Applications need to include `AppLocalizations.delegate()` in their app's -/// `localizationDelegates` list, and the locales they support in the app's -/// `supportedLocales` list. For example: -/// -/// ```dart -/// import 'l10n/app_localizations.dart'; -/// -/// return MaterialApp( -/// localizationsDelegates: AppLocalizations.localizationsDelegates, -/// supportedLocales: AppLocalizations.supportedLocales, -/// home: MyApplicationHome(), -/// ); -/// ``` -/// -/// ## Update pubspec.yaml -/// -/// Please make sure to update your pubspec.yaml to include the following -/// packages: -/// -/// ```yaml -/// dependencies: -/// # Internationalization support. -/// flutter_localizations: -/// sdk: flutter -/// intl: any # Use the pinned version from flutter_localizations -/// -/// # Rest of dependencies -/// ``` -/// -/// ## iOS Applications -/// -/// iOS applications define key application metadata, including supported -/// locales, in an Info.plist file that is built into the application bundle. -/// To configure the locales supported by your app, you’ll need to edit this -/// file. -/// -/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file. -/// Then, in the Project Navigator, open the Info.plist file under the Runner -/// project’s Runner folder. -/// -/// Next, select the Information Property List item, select Add Item from the -/// Editor menu, then select Localizations from the pop-up menu. -/// -/// Select and expand the newly-created Localizations item then, for each -/// locale your application supports, add a new item and select the locale -/// you wish to add from the pop-up menu in the Value field. This list should -/// be consistent with the languages listed in the AppLocalizations.supportedLocales -/// property. -abstract class AppLocalizations { - AppLocalizations(String locale) - : localeName = intl.Intl.canonicalizedLocale(locale.toString()); - - final String localeName; - - static AppLocalizations? of(BuildContext context) { - return Localizations.of(context, AppLocalizations); - } - - static const LocalizationsDelegate delegate = - _AppLocalizationsDelegate(); - - /// A list of this localizations delegate along with the default localizations - /// delegates. - /// - /// Returns a list of localizations delegates containing this delegate along with - /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, - /// and GlobalWidgetsLocalizations.delegate. - /// - /// Additional delegates can be added by appending to this list in - /// MaterialApp. This list does not have to be used at all if a custom list - /// of delegates is preferred or required. - static const List> localizationsDelegates = - >[ - delegate, - GlobalMaterialLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ]; - - /// A list of this localizations delegate's supported locales. - static const List supportedLocales = [ - Locale('en'), - Locale('zh') - ]; - - /// No description provided for @components. - /// - /// In en, this message translates to: - /// **'TD Flutter Components'** - String get components; - - /// No description provided for @about. - /// - /// In en, this message translates to: - /// **'About'** - String get about; - - /// No description provided for @defaultTheme. - /// - /// In en, this message translates to: - /// **'defaultTheme'** - String get defaultTheme; - - /// No description provided for @greenTheme. - /// - /// In en, this message translates to: - /// **'greenTheme'** - String get greenTheme; - - /// No description provided for @redTheme. - /// - /// In en, this message translates to: - /// **'redTheme'** - String get redTheme; - - /// No description provided for @cancel. - /// - /// In en, this message translates to: - /// **'Cancel'** - String get cancel; - - /// No description provided for @confirm. - /// - /// In en, this message translates to: - /// **'Confirm'** - String get confirm; - - /// No description provided for @switchClose. - /// - /// In en, this message translates to: - /// **'C'** - String get switchClose; - - /// No description provided for @switchOpen. - /// - /// In en, this message translates to: - /// **'O'** - String get switchOpen; - - /// No description provided for @knew. - /// - /// In en, this message translates to: - /// **'Knew'** - String get knew; - - /// No description provided for @loading. - /// - /// In en, this message translates to: - /// **'Loading'** - String get loading; - - /// No description provided for @loadingWithPoint. - /// - /// In en, this message translates to: - /// **'Loading...'** - String get loadingWithPoint; - - /// No description provided for @other. - /// - /// In en, this message translates to: - /// **'Other'** - String get other; - - /// No description provided for @refreshing. - /// - /// In en, this message translates to: - /// **'Refreshing'** - String get refreshing; - - /// No description provided for @releaseRefresh. - /// - /// In en, this message translates to: - /// **'ReleaseRefresh'** - String get releaseRefresh; - - /// No description provided for @pullToRefresh. - /// - /// In en, this message translates to: - /// **'PullToRefresh'** - String get pullToRefresh; - - /// No description provided for @completeRefresh. - /// - /// In en, this message translates to: - /// **'CompleteRefresh'** - String get completeRefresh; - - /// No description provided for @reset. - /// - /// In en, this message translates to: - /// **'Reset'** - String get reset; - - /// No description provided for @days. - /// - /// In en, this message translates to: - /// **'days'** - String get days; - - /// No description provided for @hours. - /// - /// In en, this message translates to: - /// **'hours'** - String get hours; - - /// No description provided for @minutes. - /// - /// In en, this message translates to: - /// **'minutes'** - String get minutes; - - /// No description provided for @seconds. - /// - /// In en, this message translates to: - /// **'seconds'** - String get seconds; - - /// No description provided for @milliseconds. - /// - /// In en, this message translates to: - /// **'milliseconds'** - String get milliseconds; - - /// No description provided for @yearLabel. - /// - /// In en, this message translates to: - /// **'year'** - String get yearLabel; - - /// No description provided for @monthLabel. - /// - /// In en, this message translates to: - /// **'month'** - String get monthLabel; - - /// No description provided for @dateLabel. - /// - /// In en, this message translates to: - /// **'date'** - String get dateLabel; - - /// No description provided for @weeks. - /// - /// In en, this message translates to: - /// **'weeks'** - String get weeks; - - /// No description provided for @sunday. - /// - /// In en, this message translates to: - /// **'SUN'** - String get sunday; - - /// No description provided for @monday. - /// - /// In en, this message translates to: - /// **'MON'** - String get monday; - - /// No description provided for @tuesday. - /// - /// In en, this message translates to: - /// **'TUE'** - String get tuesday; - - /// No description provided for @wednesday. - /// - /// In en, this message translates to: - /// **'WED'** - String get wednesday; - - /// No description provided for @thursday. - /// - /// In en, this message translates to: - /// **'THU'** - String get thursday; - - /// No description provided for @friday. - /// - /// In en, this message translates to: - /// **'FRI'** - String get friday; - - /// No description provided for @saturday. - /// - /// In en, this message translates to: - /// **'SAT'** - String get saturday; - - /// No description provided for @year. - /// - /// In en, this message translates to: - /// **''** - String get year; - - /// No description provided for @january. - /// - /// In en, this message translates to: - /// **'January'** - String get january; - - /// No description provided for @february. - /// - /// In en, this message translates to: - /// **'February'** - String get february; - - /// No description provided for @march. - /// - /// In en, this message translates to: - /// **'March'** - String get march; - - /// No description provided for @april. - /// - /// In en, this message translates to: - /// **'April'** - String get april; - - /// No description provided for @may. - /// - /// In en, this message translates to: - /// **'May'** - String get may; - - /// No description provided for @june. - /// - /// In en, this message translates to: - /// **'June'** - String get june; - - /// No description provided for @july. - /// - /// In en, this message translates to: - /// **'July'** - String get july; - - /// No description provided for @august. - /// - /// In en, this message translates to: - /// **'August'** - String get august; - - /// No description provided for @september. - /// - /// In en, this message translates to: - /// **'September'** - String get september; - - /// No description provided for @october. - /// - /// In en, this message translates to: - /// **'October'** - String get october; - - /// No description provided for @november. - /// - /// In en, this message translates to: - /// **'November'** - String get november; - - /// No description provided for @december. - /// - /// In en, this message translates to: - /// **'December'** - String get december; - - /// No description provided for @time. - /// - /// In en, this message translates to: - /// **'Time'** - String get time; - - /// No description provided for @start. - /// - /// In en, this message translates to: - /// **'Start'** - String get start; - - /// No description provided for @end. - /// - /// In en, this message translates to: - /// **'End'** - String get end; - - /// No description provided for @notRated. - /// - /// In en, this message translates to: - /// **'Not rated'** - String get notRated; - - /// No description provided for @cascadeLabel. - /// - /// In en, this message translates to: - /// **'Select Item'** - String get cascadeLabel; - - /// No description provided for @back. - /// - /// In en, this message translates to: - /// **'BACK'** - String get back; - - /// No description provided for @top. - /// - /// In en, this message translates to: - /// **'TOP'** - String get top; -} - -class _AppLocalizationsDelegate - extends LocalizationsDelegate { - const _AppLocalizationsDelegate(); - - @override - Future load(Locale locale) { - return SynchronousFuture(lookupAppLocalizations(locale)); - } - - @override - bool isSupported(Locale locale) => - ['en', 'zh'].contains(locale.languageCode); - - @override - bool shouldReload(_AppLocalizationsDelegate old) => false; -} - -AppLocalizations lookupAppLocalizations(Locale locale) { - // Lookup logic when only language code is specified. - switch (locale.languageCode) { - case 'en': - return AppLocalizationsEn(); - case 'zh': - return AppLocalizationsZh(); - } - - throw FlutterError( - 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' - 'an issue with the localizations generation tool. Please file an issue ' - 'on GitHub with a reproducible sample app and the gen-l10n configuration ' - 'that was used.'); -} diff --git a/tdesign-component/example/lib/localizations/app_localizations_en.dart b/tdesign-component/example/lib/localizations/app_localizations_en.dart deleted file mode 100644 index 28c285fc6..000000000 --- a/tdesign-component/example/lib/localizations/app_localizations_en.dart +++ /dev/null @@ -1,172 +0,0 @@ -// ignore: unused_import -import 'package:intl/intl.dart' as intl; -import 'app_localizations.dart'; - -// ignore_for_file: type=lint - -/// The translations for English (`en`). -class AppLocalizationsEn extends AppLocalizations { - AppLocalizationsEn([String locale = 'en']) : super(locale); - - @override - String get components => 'TD Flutter Components'; - - @override - String get about => 'About'; - - @override - String get defaultTheme => 'defaultTheme'; - - @override - String get greenTheme => 'greenTheme'; - - @override - String get redTheme => 'redTheme'; - - @override - String get cancel => 'Cancel'; - - @override - String get confirm => 'Confirm'; - - @override - String get switchClose => 'C'; - - @override - String get switchOpen => 'O'; - - @override - String get knew => 'Knew'; - - @override - String get loading => 'Loading'; - - @override - String get loadingWithPoint => 'Loading...'; - - @override - String get other => 'Other'; - - @override - String get refreshing => 'Refreshing'; - - @override - String get releaseRefresh => 'ReleaseRefresh'; - - @override - String get pullToRefresh => 'PullToRefresh'; - - @override - String get completeRefresh => 'CompleteRefresh'; - - @override - String get reset => 'Reset'; - - @override - String get days => 'days'; - - @override - String get hours => 'hours'; - - @override - String get minutes => 'minutes'; - - @override - String get seconds => 'seconds'; - - @override - String get milliseconds => 'milliseconds'; - - @override - String get yearLabel => 'year'; - - @override - String get monthLabel => 'month'; - - @override - String get dateLabel => 'date'; - - @override - String get weeks => 'weeks'; - - @override - String get sunday => 'SUN'; - - @override - String get monday => 'MON'; - - @override - String get tuesday => 'TUE'; - - @override - String get wednesday => 'WED'; - - @override - String get thursday => 'THU'; - - @override - String get friday => 'FRI'; - - @override - String get saturday => 'SAT'; - - @override - String get year => ''; - - @override - String get january => 'January'; - - @override - String get february => 'February'; - - @override - String get march => 'March'; - - @override - String get april => 'April'; - - @override - String get may => 'May'; - - @override - String get june => 'June'; - - @override - String get july => 'July'; - - @override - String get august => 'August'; - - @override - String get september => 'September'; - - @override - String get october => 'October'; - - @override - String get november => 'November'; - - @override - String get december => 'December'; - - @override - String get time => 'Time'; - - @override - String get start => 'Start'; - - @override - String get end => 'End'; - - @override - String get notRated => 'Not rated'; - - @override - String get cascadeLabel => 'Select Item'; - - @override - String get back => 'BACK'; - - @override - String get top => 'TOP'; -} diff --git a/tdesign-component/example/lib/localizations/app_localizations_zh.dart b/tdesign-component/example/lib/localizations/app_localizations_zh.dart deleted file mode 100644 index ec680e409..000000000 --- a/tdesign-component/example/lib/localizations/app_localizations_zh.dart +++ /dev/null @@ -1,172 +0,0 @@ -// ignore: unused_import -import 'package:intl/intl.dart' as intl; -import 'app_localizations.dart'; - -// ignore_for_file: type=lint - -/// The translations for Chinese (`zh`). -class AppLocalizationsZh extends AppLocalizations { - AppLocalizationsZh([String locale = 'zh']) : super(locale); - - @override - String get components => 'TDesign Flutter 组件库'; - - @override - String get about => '关于'; - - @override - String get defaultTheme => '默认主题'; - - @override - String get greenTheme => '绿色主题'; - - @override - String get redTheme => '红色主题'; - - @override - String get cancel => '取消'; - - @override - String get confirm => '确认'; - - @override - String get switchClose => '关'; - - @override - String get switchOpen => '开'; - - @override - String get knew => '知道了'; - - @override - String get loading => '加载中'; - - @override - String get loadingWithPoint => '加载中...'; - - @override - String get other => '其它'; - - @override - String get refreshing => '正在刷新'; - - @override - String get releaseRefresh => '松开刷新'; - - @override - String get pullToRefresh => '下拉刷新'; - - @override - String get completeRefresh => '刷新完成'; - - @override - String get reset => '重置'; - - @override - String get days => '天'; - - @override - String get hours => '时'; - - @override - String get minutes => '分'; - - @override - String get seconds => '秒'; - - @override - String get milliseconds => '毫秒'; - - @override - String get yearLabel => '年'; - - @override - String get monthLabel => '月'; - - @override - String get dateLabel => '日'; - - @override - String get weeks => '周'; - - @override - String get sunday => '日'; - - @override - String get monday => '一'; - - @override - String get tuesday => '二'; - - @override - String get wednesday => '三'; - - @override - String get thursday => '四'; - - @override - String get friday => '五'; - - @override - String get saturday => '六'; - - @override - String get year => ' 年'; - - @override - String get january => '1 月'; - - @override - String get february => '2 月'; - - @override - String get march => '3 月'; - - @override - String get april => '4 月'; - - @override - String get may => '5 月'; - - @override - String get june => '6 月'; - - @override - String get july => '7 月'; - - @override - String get august => '8 月'; - - @override - String get september => '9 月'; - - @override - String get october => '10 月'; - - @override - String get november => '11 月'; - - @override - String get december => '12 月'; - - @override - String get time => '时间'; - - @override - String get start => '开始'; - - @override - String get end => '结束'; - - @override - String get notRated => '未评分'; - - @override - String get cascadeLabel => '选择选项'; - - @override - String get back => '返回'; - - @override - String get top => '顶部'; -} diff --git a/tdesign-component/example/lib/main.dart b/tdesign-component/example/lib/main.dart index 3b3fad44f..9d58acbef 100644 --- a/tdesign-component/example/lib/main.dart +++ b/tdesign-component/example/lib/main.dart @@ -7,17 +7,17 @@ import 'base/example_route.dart'; import 'base/intl_resource_delegate.dart'; import 'config.dart'; import 'home.dart'; -import 'localizations/app_localizations.dart'; +import 'l10n/app_localizations.dart'; void main() { Log.setCustomLogPrinter((level, tag, msg) => print('[$level] $tag ==> $msg')); runApp(const MyApp()); - SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + /*SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.transparent, systemNavigationBarDividerColor: Colors.transparent, - )); + ));*/ exampleMap.forEach((key, value) { value.forEach((model) { @@ -38,6 +38,8 @@ class _MyAppState extends State { late TDThemeData _themeData; Locale? locale = const Locale('zh'); + ThemeMode _themeMode = ThemeMode.dark; + @override void initState() { super.initState(); @@ -53,27 +55,59 @@ class _MyAppState extends State { var delegate = IntlResourceDelegate(context); return MaterialApp( title: 'TDesign Flutter Example', - theme: ThemeData(extensions: [_themeData], colorScheme: ColorScheme.light(primary: _themeData.brandNormalColor)), - home: PlatformUtil.isWeb ? null : Builder( - builder: (context) { - // 设置文案代理,国际化需要在MaterialApp初始化完成之后才生效,而且需要每次更新context - TDTheme.setResourceBuilder((context) => delegate..updateContext(context), needAlwaysBuild: true); - return MyHomePage( - title: AppLocalizations.of(context)?.components ?? '', - locale: locale, - onLocaleChange: (locale){ - setState(() { - this.locale = locale; - }); - }, - onThemeChange: (themeData) { - setState(() { - _themeData = themeData; - }); - }, - ); - }, + theme: ThemeData( + extensions: [_themeData], + colorScheme: ColorScheme.light( + primary: _themeData.brandNormalColor, + ), + scaffoldBackgroundColor: _themeData.bgColorPage, + iconTheme: const IconThemeData().copyWith( + color: _themeData.brandNormalColor, + ), + ), + darkTheme: ThemeData( + extensions: [_themeData], + colorScheme: ColorScheme.dark( + primary: _themeData.brandNormalColor, + secondary: _themeData.brandNormalColor, + ), + scaffoldBackgroundColor: _themeData.bgColorPage, + bottomNavigationBarTheme: const BottomNavigationBarThemeData() + .copyWith(backgroundColor: _themeData.grayColor14), + appBarTheme: const AppBarTheme().copyWith( + backgroundColor: _themeData.grayColor13, + ), + iconTheme: const IconThemeData().copyWith( + color: _themeData.brandNormalColor, + ), ), + // themeMode: PlatformUtil.isWeb ? ThemeMode.dark : _themeMode, + themeMode: _themeMode, + home: PlatformUtil.isWeb + ? null + : Builder( + builder: (context) { + // 设置文案代理,国际化需要在MaterialApp初始化完成之后才生效,而且需要每次更新context + TDTheme.setResourceBuilder( + (context) => delegate..updateContext(context), + needAlwaysBuild: true); + return MyHomePage( + title: AppLocalizations.of(context)?.components ?? '', + locale: locale, + onLocaleChange: (locale) { + setState(() { + this.locale = locale; + }); + }, + onThemeChange: (themeData, isDark) { + setState(() { + _themeData = themeData; + _themeMode = isDark ? ThemeMode.dark : ThemeMode.light; + }); + }, + ); + }, + ), // 设置国际化处理 locale: locale, supportedLocales: AppLocalizations.supportedLocales, @@ -85,8 +119,11 @@ class _MyAppState extends State { Map _getRoutes() { if (PlatformUtil.isWeb) { - return {for (var model in examplePageList) model.name: (context) => model.pageBuilder.call(context, model)} - ..putIfAbsent('/', () => (context) => const MyHomePage(title: 'TDesign Flutter 组件库')); + return { + for (var model in examplePageList) + model.name: (context) => model.pageBuilder.call(context, model) + }..putIfAbsent('/', + () => (context) => const MyHomePage(title: 'TDesign Flutter 组件库')); } else { return const {}; } diff --git a/tdesign-component/example/lib/page/sidebar/td_sidebar_page.dart b/tdesign-component/example/lib/page/sidebar/td_sidebar_page.dart index ab391f391..9b5456c86 100644 --- a/tdesign-component/example/lib/page/sidebar/td_sidebar_page.dart +++ b/tdesign-component/example/lib/page/sidebar/td_sidebar_page.dart @@ -26,126 +26,101 @@ class TDSideBarPageState extends State { Widget buildWidget(BuildContext context) { return ExamplePage( - title: tdTitle(), - exampleCodeGroup: 'sideBar', - desc: '用于内容分类后的展示切换。', - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem( - desc: '侧边导航用法', - ignoreCode: true, - builder: _buildNavigatorSideBar), - ExampleItem( - desc: '图标侧边导航', - builder: _buildIconSideBar, - methodName: '_buildIconSideBar') - ]), - ExampleModule(title: '组件样式', children: [ - ExampleItem( - desc: '侧边导航样式', ignoreCode: true, builder: _buildStyleSideBar), - ]) - ], - test: [ + title: tdTitle(), + exampleCodeGroup: 'sideBar', + desc: '用于内容分类后的展示切换。', + children: [ + ExampleModule(title: '组件类型', children: [ ExampleItem( - desc: '延迟加载', ignoreCode: true, builder: _loadingSideBar), + desc: '侧边导航用法', + ignoreCode: true, + builder: _buildNavigatorSideBar), ExampleItem( - desc: '自定义未选中颜色', ignoreCode: true, builder: _unSelectedColorSideBar), - ], + desc: '图标侧边导航', + builder: _buildIconSideBar, + methodName: '_buildIconSideBar') + ]), + ExampleModule(title: '组件样式', children: [ + ExampleItem( + desc: '侧边导航样式', ignoreCode: true, builder: _buildStyleSideBar), + ]) + ], + test: [ + ExampleItem(desc: '延迟加载', ignoreCode: true, builder: _loadingSideBar), + ExampleItem( + desc: '自定义未选中颜色', + ignoreCode: true, + builder: _unSelectedColorSideBar), + ], ); } Widget _buildNavigatorSideBar(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - children: [ - CodeWrapper( - builder: (_) => getCustomButton(context, '锚点用法', 'SideBarAnchor'), - methodName: '_buildAnchorSideBar', - ), - const SizedBox( - height: 16, - ), - CodeWrapper( - builder: (_) => - getCustomButton(context, '切页用法', 'SideBarPagination'), - methodName: '_buildPaginationSideBar', - ), - ], - )); + return Column( + // spacing: 16, + children: [ + CodeWrapper( + builder: (_) => getCustomButton(context, '锚点用法', 'SideBarAnchor'), + methodName: '_buildAnchorSideBar', + ), + const SizedBox(height: 16), + CodeWrapper( + builder: (_) => getCustomButton(context, '切页用法', 'SideBarPagination'), + methodName: '_buildPaginationSideBar', + ), + ], + ); } Widget _buildIconSideBar(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - children: [ - getCustomButton(context, '带图标侧边导航', 'SideBarIcon'), - ], - )); + return getCustomButton(context, '带图标侧边导航', 'SideBarIcon'); } Widget _buildStyleSideBar(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - children: [ - CodeWrapper( - builder: (_) => - getCustomButton(context, '非通栏选项样式', 'SideBarOutline'), - methodName: '_buildOutlineSideBar', - ), - const SizedBox( - height: 16, - ), - CodeWrapper( - builder: (_) => - getCustomButton(context, '自定义样式', 'SideBarCustom'), - methodName: '_buildCustomSideBar', - ), - ], - )); + return Column( + children: [ + CodeWrapper( + builder: (_) => getCustomButton(context, '非通栏选项样式', 'SideBarOutline'), + methodName: '_buildOutlineSideBar', + ), + const SizedBox(height: 16), + CodeWrapper( + builder: (_) => getCustomButton(context, '自定义样式', 'SideBarCustom'), + methodName: '_buildCustomSideBar', + ), + ], + ); } Widget _loadingSideBar(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - children: [ - CodeWrapper( - builder: (_) => - getCustomButton(context, '延迟加载', 'SideBarLoading'), - methodName: '_buildLoadingSideBar', - ), - ], - )); + return CodeWrapper( + builder: (_) => getCustomButton(context, '延迟加载', 'SideBarLoading'), + methodName: '_buildLoadingSideBar', + ); } Widget _unSelectedColorSideBar(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - children: [ - CodeWrapper( - builder: (_) => - getCustomButton(context, '未选中颜色自定义', 'SideBarUnselectedColor'), - methodName: '_buildUnselectedColorSideBar', - ), - ], - )); + return CodeWrapper( + builder: (_) => + getCustomButton(context, '未选中颜色自定义', 'SideBarUnselectedColor'), + methodName: '_buildUnselectedColorSideBar', + ); } TDButton getCustomButton( BuildContext context, String text, String routeName) { return TDButton( text: text, - width: MediaQuery.of(context).size.width - 16 * 2, + isBlock: true, size: TDButtonSize.large, type: TDButtonType.outline, shape: TDButtonShape.rectangle, theme: TDButtonTheme.primary, onTap: () { - Navigator.pushNamed(context, PlatformUtil.isWeb ? routeName : '$routeName'); + Navigator.pushNamed( + context, + PlatformUtil.isWeb ? routeName : '$routeName', + ); }, ); } diff --git a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_anchor.dart b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_anchor.dart index b9676c00e..70e97de2b 100644 --- a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_anchor.dart +++ b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_anchor.dart @@ -47,12 +47,10 @@ class TDSideBarAnchorPageState extends State { } }); - // 锚点用法 - for (var i = 0; i < 20; i++) { list.add(SideItemProps( index: i, - label: '选项', + label: '选项$i', value: i, )); pages.add(getAnchorDemo(i)); @@ -68,20 +66,24 @@ class TDSideBarAnchorPageState extends State { } Future onSelected(int value) async { - if (currentValue != value) { - setState(() { - currentValue = value; - }); - - lock = true; - await _demoScroller.animateTo(value.toDouble() * itemHeight, - duration: const Duration(milliseconds: 500), curve: Curves.easeIn); - lock = false; + if (currentValue == value) { + return; } + setState(() { + currentValue = value; + }); + + lock = true; + await _demoScroller.animateTo( + value.toDouble() * itemHeight, + duration: const Duration(milliseconds: 500), + curve: Curves.easeIn, + ); + lock = false; } void onChanged(int value) { - if(mounted){ + if (mounted) { setState(() { currentValue = value; }); @@ -89,102 +91,104 @@ class TDSideBarAnchorPageState extends State { } @override - Widget build(BuildContext context) { - var current = buildWidget(context); - return current; + void dispose() { + _demoScroller.dispose(); + _sideBarController.dispose(); + super.dispose(); } - Widget buildWidget(BuildContext context) { + @override + Widget build(BuildContext context) { return ExamplePage( - title: 'SideBar 锚点用法', - exampleCodeGroup: 'sideBar', - showSingleChild: true, - singleChild: CodeWrapper( - isCenter: false, - builder: _buildAnchorSideBar, - )); + title: 'SideBar 锚点用法', + exampleCodeGroup: 'sideBar', + showSingleChild: true, + singleChild: CodeWrapper( + isCenter: false, + builder: _buildAnchorSideBar, + ), + ); } @Demo(group: 'sideBar') Widget _buildAnchorSideBar(BuildContext context) { var demoHeight = MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top - - titleBarHeight - testButtonHeight; - pages.add(Container( - height: demoHeight - itemHeight, - decoration: const BoxDecoration(color: Colors.white), - )); + titleBarHeight - + testButtonHeight; + return Column( children: [ Container( height: testButtonHeight, padding: const EdgeInsets.all(16), - child: TDButton(text: '更新children', + child: TDButton( + text: '更新children', onTap: () { setState(() { var children = list .map((e) => SideItemProps( - index: e.index, - label: '变更', - badge: e.badge, - value: e.value, - icon: e.icon)) + index: e.index, + label: '变更${e.index}', + badge: e.badge, + value: e.value, + icon: e.icon)) .toList(); _sideBarController.children = children; - setState(() { - - }); + setState(() {}); }); - },), + }, + ), ), - Row( - children: [ - SizedBox( - width: 110, - child: TDSideBar( - height: demoHeight, - style: TDSideBarStyle.normal, - value: currentValue, - controller: _sideBarController, - onChanged: onChanged, - onSelected: onSelected, + Expanded( + child: Row( + children: [ + SizedBox( + width: 110, + child: TDSideBar( + style: TDSideBarStyle.normal, + value: currentValue, + controller: _sideBarController, + onChanged: onChanged, + onSelected: onSelected, + ), ), - ), - Expanded( - child: SizedBox( - height: demoHeight, - child: SingleChildScrollView( + Expanded( + child: SingleChildScrollView( controller: _demoScroller, - child: Column( - children: pages, - ), - ), - )) - ], + child: Container( + color: TDTheme.of(context).bgColorContainer, + child: Column( + children: [ + ...pages, + Container(height: demoHeight - itemHeight) + ], + ), + )), + ) + ], + ), ) ], ); } Widget getAnchorDemo(int index) { - return Container( - decoration: const BoxDecoration(color: Colors.white), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 20, top: 15, right: 9), - child: TDText('标题$index', - style: const TextStyle( - fontSize: 14, - )), - ), - Padding( - padding: const EdgeInsets.only(left: 20), - child: displayImageList(), - ), - ], - ), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 20, top: 15, right: 9), + child: TDText('标题$index', + style: const TextStyle( + fontSize: 14, + )), + ), + Padding( + padding: const EdgeInsets.only(left: 20), + child: displayImageList(), + ), + ], ); } @@ -202,26 +206,20 @@ class TDSideBarAnchorPageState extends State { } Widget displayImageItem() { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 16), + return const Padding( + padding: EdgeInsets.symmetric(vertical: 16), child: Row( crossAxisAlignment: CrossAxisAlignment.center, - children: const [ + // spacing: 16, + children: [ TDImage( assetUrl: 'assets/img/empty.png', type: TDImageType.roundedSquare, width: 48, height: 48, ), - SizedBox( - width: 16, - ), - TDText( - '标题', - style: TextStyle( - fontSize: 16, - ), - ) + SizedBox(width: 16), + TDText('标题', style: TextStyle(fontSize: 16)) ], ), ); diff --git a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_custom.dart b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_custom.dart index df01f0b8e..98f9d1d75 100644 --- a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_custom.dart +++ b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_custom.dart @@ -47,8 +47,9 @@ class TDSideBarCustomPageState extends State { for (var i = 0; i < 100; i++) { list.add(SideItemProps( index: i, - label: '选项', + label: '选项 $i', value: i, + textStyle: TextStyle(color: TDTheme.of(context).brandLightColor), )); pages.add(getPageDemo(i)); } @@ -67,14 +68,11 @@ class TDSideBarCustomPageState extends State { } } - var demoHeight = MediaQuery.of(context).size.height; - return Row( children: [ SizedBox( width: 110, child: TDSideBar( - height: demoHeight, style: TDSideBarStyle.normal, value: currentValue, controller: _sideBarController, @@ -86,39 +84,35 @@ class TDSideBarCustomPageState extends State { textStyle: ele.textStyle, icon: ele.icon)) .toList(), - selectedTextStyle:TextStyle(color: Colors.red), + selectedTextStyle: const TextStyle(color: Colors.red), onSelected: setCurrentValue, - contentPadding:EdgeInsets.only(left: 16, top: 16,bottom: 16), + contentPadding: + const EdgeInsets.only(left: 16, top: 16, bottom: 16), selectedBgColor: Colors.blue, unSelectedBgColor: Colors.yellow, ), ), Expanded( - child: SizedBox( - height: demoHeight, child: PageView( controller: _pageController, scrollDirection: Axis.vertical, children: pages, physics: const NeverScrollableScrollPhysics(), ), - )) + ) ], ); } Widget getPageDemo(int index) { return Container( - decoration: const BoxDecoration(color: Colors.white), + decoration: const BoxDecoration(color: Colors.blue), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(left: 20, top: 2, right: 9), - child: TDText('标题$index', - style: const TextStyle( - fontSize: 14, - )), + child: TDText('标题 $index', style: const TextStyle(fontSize: 14)), ), const SizedBox(height: 16), displayImageList() @@ -128,72 +122,52 @@ class TDSideBarCustomPageState extends State { } Widget getAnchorDemo(int index) { - return Container( - decoration: const BoxDecoration(color: Colors.white), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 20, top: 2, right: 9), - child: TDText('标题$index', - style: const TextStyle( - fontSize: 14, - )), - ), - const SizedBox(height: 16), - displayImageList() - ], - ), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + // spacing: 16, + children: [ + Padding( + padding: const EdgeInsets.only(left: 20, top: 2, right: 9), + child: TDText('标题$index', style: const TextStyle(fontSize: 14)), + ), + const SizedBox(height: 16), + displayImageList() + ], ); } Widget displayImageList() { - return Column( - children: [ - Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - displayImageItem('标题文字'), - displayImageItem('标题文字'), - displayImageItem('最多六个文字'), - ]), - const SizedBox(height: 18), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - displayImageItem('标题文字'), - displayImageItem('标题文字'), - displayImageItem('最多六个文字'), - ], + return Container( + padding: const EdgeInsets.symmetric(horizontal: 18), + width: double.infinity, + child: Wrap( + spacing: 18, + runSpacing: 18, + alignment: WrapAlignment.spaceEvenly, + children: List.generate( + 12, + (index) => displayImageItem('${index}最多六个字'), ), - const SizedBox(height: 18), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - displayImageItem('标题文字'), - displayImageItem('标题文字'), - displayImageItem('最多六个文字'), - ], - ) - ], + ), ); } Widget displayImageItem(String title) { return Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const TDImage( - assetUrl: 'assets/img/empty.png', - type: TDImageType.roundedSquare, - width: 48, - height: 48, - ), - const SizedBox(height: 8), - TDText( - '$title', - style: const TextStyle(fontSize: 12), - ) - ], - )); + child: Column( + // spacing: 8, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const TDImage( + assetUrl: 'assets/img/empty.png', + type: TDImageType.roundedSquare, + width: 48, + height: 48, + ), + const SizedBox(height: 4), + TDText('$title', style: const TextStyle(fontSize: 12)) + ], + ), + ); } } diff --git a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_icon.dart b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_icon.dart index 2e75979c0..b4d13c0d5 100644 --- a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_icon.dart +++ b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_icon.dart @@ -86,14 +86,18 @@ class TDSideBarIconPageState extends State { final pages = []; for (var i = 0; i < 20; i++) { - list.add( - SideItemProps(index: i, label: '选项', value: i, icon: TDIcons.app)); + list.add(SideItemProps( + index: i, + label: '选项${i}', + value: i, + icon: TDIcons.app, + )); pages.add(getAnchorDemo(i)); } pages.add(Container( height: MediaQuery.of(context).size.height - itemHeight, - decoration: const BoxDecoration(color: Colors.white), + decoration: BoxDecoration(color: TDTheme.of(context).bgColorContainer), )); list[1].badge = const TDBadge(TDBadgeType.redPoint); @@ -102,14 +106,11 @@ class TDSideBarIconPageState extends State { count: '8', ); - var demoHeight = MediaQuery.of(context).size.height; - return Row( children: [ SizedBox( width: 110, child: TDSideBar( - height: demoHeight, style: TDSideBarStyle.normal, value: currentValue, controller: _sideBarController, @@ -125,22 +126,20 @@ class TDSideBarIconPageState extends State { ), ), Expanded( - child: SizedBox( - height: demoHeight, child: SingleChildScrollView( controller: _demoScroller, child: Column( children: pages, ), ), - )) + ) ], ); } Widget getAnchorDemo(int index) { return Container( - decoration: const BoxDecoration(color: Colors.white), + decoration: BoxDecoration(color: TDTheme.of(context).bgColorContainer), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -174,26 +173,20 @@ class TDSideBarIconPageState extends State { } Widget displayImageItem() { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 16), + return const Padding( + padding: EdgeInsets.symmetric(vertical: 16), child: Row( crossAxisAlignment: CrossAxisAlignment.center, - children: const [ + // spacing: 16, + children: [ TDImage( assetUrl: 'assets/img/empty.png', type: TDImageType.roundedSquare, width: 48, height: 48, ), - SizedBox( - width: 16, - ), - TDText( - '标题', - style: TextStyle( - fontSize: 16, - ), - ) + SizedBox(width: 16), + TDText('标题', style: TextStyle(fontSize: 16)) ], ), ); diff --git a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_loading.dart b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_loading.dart index 01dca141c..56a7290b5 100644 --- a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_loading.dart +++ b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_loading.dart @@ -91,7 +91,7 @@ class TDSideBarLoadingPageState extends State { for (var i = 0; i < 20; i++) { list.add(SideItemProps( index: i, - label: '选项', + label: '选项 $i', value: i, )); pages.add(getLoadingDemo(i)); @@ -99,7 +99,7 @@ class TDSideBarLoadingPageState extends State { pages.add(Container( height: MediaQuery.of(context).size.height - itemHeight, - decoration: const BoxDecoration(color: Colors.white), + decoration: BoxDecoration(color: TDTheme.of(context).bgColorContainer), )); list[1].badge = const TDBadge(TDBadgeType.redPoint); @@ -107,7 +107,7 @@ class TDSideBarLoadingPageState extends State { TDBadgeType.message, count: '8', ); - if(_sideBarController.loading) { + if (_sideBarController.loading) { _sideBarController.init(list); _sideBarController.selectTo(currentValue); // 初始化时避免右侧内容与左侧item不匹配 @@ -121,14 +121,12 @@ class TDSideBarLoadingPageState extends State { // 延迟加载 Future.delayed(const Duration(seconds: 3), _initData); var size = MediaQuery.of(context).size; - var demoHeight = size.height; return Row( children: [ SizedBox( width: list.isEmpty ? size.width : 110, child: TDSideBar( - height: demoHeight, style: TDSideBarStyle.normal, value: currentValue, controller: _sideBarController, @@ -145,22 +143,20 @@ class TDSideBarLoadingPageState extends State { ), ), Expanded( - child: SizedBox( - height: demoHeight, child: SingleChildScrollView( controller: _demoScroller, child: Column( children: pages, ), ), - )) + ) ], ); } Widget getLoadingDemo(int index) { return Container( - decoration: const BoxDecoration(color: Colors.white), + decoration: BoxDecoration(color: TDTheme.of(context).bgColorContainer), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -194,26 +190,20 @@ class TDSideBarLoadingPageState extends State { } Widget displayImageItem() { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 16), + return const Padding( + padding: EdgeInsets.symmetric(vertical: 16), child: Row( + // spacing: 16, crossAxisAlignment: CrossAxisAlignment.center, - children: const [ + children: [ TDImage( assetUrl: 'assets/img/empty.png', type: TDImageType.roundedSquare, width: 48, height: 48, ), - SizedBox( - width: 16, - ), - TDText( - '标题', - style: TextStyle( - fontSize: 16, - ), - ) + SizedBox(width: 16), + TDText('标题', style: TextStyle(fontSize: 16)) ], ), ); diff --git a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_outline.dart b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_outline.dart index e86d05a35..06a4df501 100644 --- a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_outline.dart +++ b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_outline.dart @@ -89,7 +89,7 @@ class TDSideBarOutlinePageState extends State { for (var i = 0; i < 20; i++) { list.add(SideItemProps( index: i, - label: '选项', + label: '选项${i}', value: i, )); pages.add(getAnchorDemo(i)); @@ -97,7 +97,7 @@ class TDSideBarOutlinePageState extends State { pages.add(Container( height: MediaQuery.of(context).size.height - itemHeight, - decoration: const BoxDecoration(color: Colors.white), + decoration: BoxDecoration(color: TDTheme.of(context).bgColorContainer), )); list[1].badge = const TDBadge(TDBadgeType.redPoint); @@ -106,14 +106,11 @@ class TDSideBarOutlinePageState extends State { count: '8', ); - var demoHeight = MediaQuery.of(context).size.height; - return Row( children: [ SizedBox( width: 110, child: TDSideBar( - height: demoHeight, style: TDSideBarStyle.outline, value: currentValue, controller: _sideBarController, @@ -129,28 +126,26 @@ class TDSideBarOutlinePageState extends State { ), ), Expanded( - child: SizedBox( - height: demoHeight, child: SingleChildScrollView( controller: _demoScroller, child: Column( children: pages, ), ), - )) + ) ], ); } Widget getAnchorDemo(int index) { return Container( - decoration: const BoxDecoration(color: Colors.white), + decoration: BoxDecoration(color: TDTheme.of(context).bgColorContainer), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(left: 20, top: 15, right: 9), - child: TDText('标题$index', + child: TDText('标题 $index', style: const TextStyle( fontSize: 14, )), @@ -178,26 +173,20 @@ class TDSideBarOutlinePageState extends State { } Widget displayImageItem() { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 16), + return const Padding( + padding: EdgeInsets.symmetric(vertical: 16), child: Row( + // spacing: 16, crossAxisAlignment: CrossAxisAlignment.center, - children: const [ + children: [ TDImage( assetUrl: 'assets/img/empty.png', type: TDImageType.roundedSquare, width: 48, height: 48, ), - SizedBox( - width: 16, - ), - TDText( - '标题', - style: TextStyle( - fontSize: 16, - ), - ) + SizedBox(width: 16), + TDText('标题', style: TextStyle(fontSize: 16)) ], ), ); diff --git a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_pagination.dart b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_pagination.dart index 970b4bb82..99cb2a2d7 100644 --- a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_pagination.dart +++ b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_pagination.dart @@ -47,7 +47,7 @@ class TDSideBarPaginationPageState extends State { for (var i = 0; i < 100; i++) { list.add(SideItemProps( index: i, - label: '选项', + label: '选项 ${i}', value: i, )); pages.add(getPageDemo(i)); @@ -66,14 +66,11 @@ class TDSideBarPaginationPageState extends State { } } - var demoHeight = MediaQuery.of(context).size.height; - return Row( children: [ SizedBox( width: 110, child: TDSideBar( - height: demoHeight, style: TDSideBarStyle.normal, value: currentValue, controller: _sideBarController, @@ -88,51 +85,27 @@ class TDSideBarPaginationPageState extends State { ), ), Expanded( - child: SizedBox( - height: demoHeight, child: PageView( controller: _pageController, scrollDirection: Axis.vertical, children: pages, physics: const NeverScrollableScrollPhysics(), ), - )) + ) ], ); } Widget getPageDemo(int index) { return Container( - decoration: const BoxDecoration(color: Colors.white), + decoration: BoxDecoration(color: TDTheme.of(context).bgColorContainer), child: Column( crossAxisAlignment: CrossAxisAlignment.start, + // spacing: 16, children: [ Padding( padding: const EdgeInsets.only(left: 20, top: 2, right: 9), - child: TDText('标题$index', - style: const TextStyle( - fontSize: 14, - )), - ), - const SizedBox(height: 16), - displayImageList() - ], - ), - ); - } - - Widget getAnchorDemo(int index) { - return Container( - decoration: const BoxDecoration(color: Colors.white), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 20, top: 2, right: 9), - child: TDText('标题$index', - style: const TextStyle( - fontSize: 14, - )), + child: TDText('标题 $index', style: const TextStyle(fontSize: 14)), ), const SizedBox(height: 16), displayImageList() @@ -142,38 +115,24 @@ class TDSideBarPaginationPageState extends State { } Widget displayImageList() { - return Column( - children: [ - Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - displayImageItem('标题文字'), - displayImageItem('标题文字'), - displayImageItem('最多六个文字'), - ]), - const SizedBox(height: 18), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - displayImageItem('标题文字'), - displayImageItem('标题文字'), - displayImageItem('最多六个文字'), - ], + return Container( + padding: const EdgeInsets.symmetric(horizontal: 18), + width: double.infinity, + child: Wrap( + spacing: 18, + runSpacing: 18, + alignment: WrapAlignment.spaceEvenly, + children: List.generate( + 12, + (index) => displayImageItem('${index}最多六个字'), ), - const SizedBox(height: 18), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - displayImageItem('标题文字'), - displayImageItem('标题文字'), - displayImageItem('最多六个文字'), - ], - ) - ], + ), ); } Widget displayImageItem(String title) { - return Expanded( - child: Column( + return Column( + // spacing: 8, crossAxisAlignment: CrossAxisAlignment.center, children: [ const TDImage( @@ -183,11 +142,8 @@ class TDSideBarPaginationPageState extends State { height: 48, ), const SizedBox(height: 8), - TDText( - '$title', - style: const TextStyle(fontSize: 12), - ) + TDText('$title', style: const TextStyle(fontSize: 12)) ], - )); + ); } } diff --git a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_unselected_color.dart b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_unselected_color.dart index 44539bc57..3b96bf610 100644 --- a/tdesign-component/example/lib/page/sidebar/td_sidebar_page_unselected_color.dart +++ b/tdesign-component/example/lib/page/sidebar/td_sidebar_page_unselected_color.dart @@ -16,7 +16,8 @@ class TDSideBarUnSelectedColorPage extends StatefulWidget { } } -class TDSideBarUnSelectedColorPageState extends State { +class TDSideBarUnSelectedColorPageState + extends State { var currentValue = 1; var itemHeight = 278.5; var titleBarHeight = 44; @@ -52,8 +53,9 @@ class TDSideBarUnSelectedColorPageState extends State SideItemProps( - index: e.index, - label: '变更', - badge: e.badge, - value: e.value, - icon: e.icon)) + index: e.index, + label: '变更${e.index}', + badge: e.badge, + value: e.value, + icon: e.icon)) .toList(); _sideBarController.children = children; - setState(() { - - }); + setState(() {}); }); - },), + }, + ), ), - Row( + Expanded( + child: Row( children: [ SizedBox( width: 110, child: TDSideBar( - height: demoHeight, unSelectedColor: Colors.red, style: TDSideBarStyle.normal, value: currentValue, @@ -152,40 +152,40 @@ class TDSideBarUnSelectedColorPageState extends State _gridItems = [ - TDActionSheetItem(label: '微信', icon: Image.asset('assets/img/td_action_sheet_1.png'), group: '分享至'), - TDActionSheetItem(label: '朋友圈', icon: Image.asset('assets/img/td_action_sheet_2.png'), group: '分享至'), - TDActionSheetItem(label: 'QQ', icon: Image.asset('assets/img/td_action_sheet_3.png'), group: '分享至'), - TDActionSheetItem(label: '企业微信', icon: Image.asset('assets/img/td_action_sheet_4.png'), group: '分享至'), - TDActionSheetItem(label: '收藏', icon: const IconWithBackground(icon: TDIcons.star), group: '分享至'), - TDActionSheetItem(label: '刷新', icon: const IconWithBackground(icon: TDIcons.refresh), group: '分享至'), - TDActionSheetItem(label: '下载', icon: const IconWithBackground(icon: TDIcons.download), group: '分享至'), - TDActionSheetItem(label: '复制', icon: const IconWithBackground(icon: TDIcons.queue), group: '分享至'), + TDActionSheetItem( + label: '微信', + icon: Image.asset('assets/img/td_action_sheet_1.png'), + group: '分享至'), + TDActionSheetItem( + label: '朋友圈', + icon: Image.asset('assets/img/td_action_sheet_2.png'), + group: '分享至'), + TDActionSheetItem( + label: 'QQ', + icon: Image.asset('assets/img/td_action_sheet_3.png'), + group: '分享至'), + TDActionSheetItem( + label: '企业微信', + icon: Image.asset('assets/img/td_action_sheet_4.png'), + group: '分享至'), + TDActionSheetItem( + label: '收藏', + icon: const IconWithBackground(icon: TDIcons.star), + group: '分享至'), + TDActionSheetItem( + label: '刷新', + icon: const IconWithBackground(icon: TDIcons.refresh), + group: '分享至'), + TDActionSheetItem( + label: '下载', + icon: const IconWithBackground(icon: TDIcons.download), + group: '分享至'), + TDActionSheetItem( + label: '复制', + icon: const IconWithBackground(icon: TDIcons.queue), + group: '分享至'), ]; class TDActionSheetPage extends StatelessWidget { @@ -47,89 +71,91 @@ class TDActionSheetPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - color: TDTheme.of(context).grayColor2, - child: ExamplePage( - title: tdTitle(context), - desc: '从底部弹出的模态框,提供和当前场景相关的操作动作,也支持提供信息输入和描述。', - exampleCodeGroup: 'action_sheet', - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem( - ignoreCode: true, - desc: '列表型动作面板', - builder: (BuildContext context) { - return const Column( - children: [ - CodeWrapper(builder: _buildBaseListActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildDescListActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildIconListActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildBadgeListActionSheet), - ], - ); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '宫格型动作面板', - builder: (BuildContext context) { - return const Column( - children: [ - CodeWrapper(builder: _buildBaseGridActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildDescGridActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildPaginationGridActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildScrollGridActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildMultiScrollGridActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildBadgeGridActionSheet), - ], - ); - }, - ), - ]), - ExampleModule(title: '组件状态', children: [ - ExampleItem( - ignoreCode: true, - desc: '列表型选项状态', - builder: (BuildContext context) { - return const Column( - children: [ - CodeWrapper(builder: _buildBaseListStateActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildIconListStateActionSheet), - ], - ); - }, - ) - ]), - ExampleModule(title: '组件样式', children: [ - ExampleItem( - ignoreCode: true, - desc: '列表型对齐方式', - builder: (BuildContext context) { - return const Column( - children: [ - CodeWrapper(builder: _buildBadgeListCenterActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildIconListCenterActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildBadgeListLeftActionSheet), - SizedBox(height: 16), - CodeWrapper(builder: _buildIconListLeftActionSheet), - ], - ); - }) - ]) - ], - test: const [], - )); + return ExamplePage( + title: tdTitle(context), + desc: '由用户操作后触发的一种特定的模态弹出框 ,呈现一组与当前情境相关的两个或多个选项。', + exampleCodeGroup: 'action_sheet', + children: [ + ExampleModule(title: '组件类型', children: [ + ExampleItem( + ignoreCode: true, + desc: '列表型动作面板', + builder: (BuildContext context) { + return const Column( + // spacing: 16, + children: [ + CodeWrapper(builder: _buildBaseListActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildDescListActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildIconListActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildBadgeListActionSheet), + ], + ); + }, + ), + ExampleItem( + ignoreCode: true, + desc: '宫格型动作面板', + builder: (BuildContext context) { + return const Column( + // spacing: 16, + children: [ + CodeWrapper(builder: _buildBaseGridActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildDescGridActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildPaginationGridActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildScrollGridActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildMultiScrollGridActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildBadgeGridActionSheet), + ], + ); + }, + ), + ]), + ExampleModule(title: '组件状态', children: [ + ExampleItem( + ignoreCode: true, + desc: '列表型选项状态', + builder: (BuildContext context) { + return const Column( + // spacing: 16, + children: [ + CodeWrapper(builder: _buildBaseListStateActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildIconListStateActionSheet), + ], + ); + }, + ) + ]), + ExampleModule(title: '组件样式', children: [ + ExampleItem( + ignoreCode: true, + desc: '列表型对齐方式', + builder: (BuildContext context) { + return const Column( + // spacing: 16, + children: [ + CodeWrapper(builder: _buildBadgeListCenterActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildIconListCenterActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildBadgeListLeftActionSheet), + SizedBox(height: 16), + CodeWrapper(builder: _buildIconListLeftActionSheet), + ], + ); + }) + ]) + ], + test: const [], + ); } } @@ -342,8 +368,8 @@ Widget _buildScrollGridActionSheet(BuildContext context) { icon: const IconWithBackground(icon: TDIcons.logo_github), ), TDActionSheetItem( - label: 'Github', - icon: const IconWithBackground(icon: TDIcons.logo_github), + label: 'Twitter', + icon: const IconWithBackground(icon: TDIcons.logo_twitter), ), ], ); @@ -407,14 +433,30 @@ Widget _buildBadgeGridActionSheet(BuildContext context) { size: TDButtonSize.large, onTap: () { TDActionSheet.showGridActionSheet(context, items: [ - TDActionSheetItem(label: '微信', icon: Image.asset('assets/img/td_action_sheet_1.png'), badge: const TDBadge(TDBadgeType.message, count: 'NEW')), - TDActionSheetItem(label: '朋友圈', icon: Image.asset('assets/img/td_action_sheet_2.png')), - TDActionSheetItem(label: 'QQ', icon: Image.asset('assets/img/td_action_sheet_3.png')), - TDActionSheetItem(label: '企业微信', icon: Image.asset('assets/img/td_action_sheet_4.png')), - TDActionSheetItem(label: '收藏', icon: const IconWithBackground(icon: TDIcons.star), badge: const TDBadge(TDBadgeType.redPoint)), - TDActionSheetItem(label: '刷新', icon: const IconWithBackground(icon: TDIcons.refresh)), - TDActionSheetItem(label: '下载', icon: const IconWithBackground(icon: TDIcons.download), badge: const TDBadge(TDBadgeType.message, count: '8')), - TDActionSheetItem(label: '复制', icon: const IconWithBackground(icon: TDIcons.queue)), + TDActionSheetItem( + label: '微信', + icon: Image.asset('assets/img/td_action_sheet_1.png'), + badge: const TDBadge(TDBadgeType.message, count: 'NEW')), + TDActionSheetItem( + label: '朋友圈', + icon: Image.asset('assets/img/td_action_sheet_2.png')), + TDActionSheetItem( + label: 'QQ', icon: Image.asset('assets/img/td_action_sheet_3.png')), + TDActionSheetItem( + label: '企业微信', + icon: Image.asset('assets/img/td_action_sheet_4.png')), + TDActionSheetItem( + label: '收藏', + icon: const IconWithBackground(icon: TDIcons.star), + badge: const TDBadge(TDBadgeType.redPoint)), + TDActionSheetItem( + label: '刷新', icon: const IconWithBackground(icon: TDIcons.refresh)), + TDActionSheetItem( + label: '下载', + icon: const IconWithBackground(icon: TDIcons.download), + badge: const TDBadge(TDBadgeType.message, count: '8')), + TDActionSheetItem( + label: '复制', icon: const IconWithBackground(icon: TDIcons.queue)), ]); }, ); @@ -526,11 +568,17 @@ Widget _buildBadgeListCenterActionSheet(BuildContext context) { ), TDActionSheetItem( label: '选项二', - badge: const TDBadge(TDBadgeType.message, count: '8',), + badge: const TDBadge( + TDBadgeType.message, + count: '8', + ), ), TDActionSheetItem( label: '选项三', - badge: const TDBadge(TDBadgeType.message, count: '99',), + badge: const TDBadge( + TDBadgeType.message, + count: '99', + ), ), ], ); diff --git a/tdesign-component/example/lib/page/td_avatar_page.dart b/tdesign-component/example/lib/page/td_avatar_page.dart index 003b41340..b576aa4b3 100644 --- a/tdesign-component/example/lib/page/td_avatar_page.dart +++ b/tdesign-component/example/lib/page/td_avatar_page.dart @@ -12,46 +12,40 @@ class TDAvatarPage extends StatefulWidget { } class _TDAvatarPageState extends State { + static const padding = EdgeInsets.symmetric(horizontal: 16); + @override Widget build(BuildContext context) { return ExamplePage( - backgroundColor: TDTheme.of(context).whiteColor1, title: tdTitle(), exampleCodeGroup: 'avatar', - desc: '用于告知用户,该区域的状态变化或者待处理任务的数量。', + desc: '用于展示用户头像信息,除了纯展示也可点击进入个人详情等操作。', children: [ ExampleModule(title: '组件类型', children: [ ExampleItem( - desc: '图片头像', - builder: _buildImageAvatar), + desc: '图片头像', padding: padding, builder: _buildImageAvatar), ExampleItem( - desc: '字符头像', - builder: _buildTextAvatar), + desc: '字符头像', padding: padding, builder: _buildTextAvatar), ExampleItem( - desc: '图标头像', - builder: _buildIconAvatar), + desc: '图标头像', padding: padding, builder: _buildIconAvatar), ExampleItem( - desc: '带徽标头像', - builder: _buildBadgeAvatar), + desc: '带徽标头像', padding: padding, builder: _buildBadgeAvatar), ]), ExampleModule(title: '特殊类型', children: [ ExampleItem( - desc: '纯展示的头像组', - builder: _buildDisplayAvatar), + desc: '纯展示的头像组', padding: padding, builder: _buildDisplayAvatar), ExampleItem( desc: '带操作的头像组', + padding: padding, builder: _buildOperationAvatar), ]), ExampleModule(title: '组件尺寸', children: [ ExampleItem( - desc: '大尺寸 :64px', - builder: _buildLargeAvatar), + desc: '大尺寸:64px', padding: padding, builder: _buildLargeAvatar), ExampleItem( - desc: '中尺寸 :48px', - builder: _buildMediumAvatar), + desc: '中尺寸:48px', padding: padding, builder: _buildMediumAvatar), ExampleItem( - desc: '小尺寸 :40px', - builder: _buildSmallAvatar), + desc: '小尺寸:40px', padding: padding, builder: _buildSmallAvatar), ]) ], ); @@ -59,232 +53,234 @@ class _TDAvatarPageState extends State { /// 图片头像 @Demo(group: 'avatar') - Widget _buildImageAvatar(BuildContext context){ - return Padding( - padding: const EdgeInsets.only(left: 16), - child: Row( - children: const [ - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.normal, - defaultUrl: 'assets/img/td_avatar_1.png',), - SizedBox(width: 32,), - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.normal, - shape: TDAvatarShape.square, - defaultUrl: 'assets/img/td_avatar_1.png',), - ], - ), + Widget _buildImageAvatar(BuildContext context) { + return const Row( + // spacing: 32, + children: [ + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.normal, + defaultUrl: 'assets/img/td_avatar_1.png', + ), + SizedBox(width: 32), + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.normal, + shape: TDAvatarShape.square, + defaultUrl: 'assets/img/td_avatar_1.png', + ), + ], ); } /// 字符头像 @Demo(group: 'avatar') - Widget _buildTextAvatar(BuildContext context){ - return Padding( - padding: const EdgeInsets.only(left: 16), - child: Row( - children: const [ - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.customText, - text: 'A'), - SizedBox(width: 32,), - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.customText, - shape: TDAvatarShape.square, - text: 'A'), - ], - ), + Widget _buildTextAvatar(BuildContext context) { + return const Row( + // spacing: 32, + children: [ + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.customText, + text: 'A', + ), + SizedBox(width: 32), + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.customText, + shape: TDAvatarShape.square, + text: 'A', + ), + ], ); } /// 图标头像 @Demo(group: 'avatar') - Widget _buildIconAvatar(BuildContext context){ - return Padding( - padding: const EdgeInsets.only(left: 16), - child: Row( - children: const [ - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.icon,), - SizedBox(width: 32,), - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.icon, - shape: TDAvatarShape.square, - ), - ], - ), + Widget _buildIconAvatar(BuildContext context) { + return const Row( + // spacing: 32, + children: [ + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.icon, + ), + SizedBox(width: 32), + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.icon, + shape: TDAvatarShape.square, + ), + ], ); } /// 带徽标头像 @Demo(group: 'avatar') - Widget _buildBadgeAvatar(BuildContext context){ - return Padding( - padding: const EdgeInsets.only(left: 16), - child: Row( - children: [ - SizedBox( - height: 51, - width: 51, - child: Stack( - alignment:Alignment.bottomLeft, - children: const [ - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.normal, - defaultUrl: 'assets/img/td_avatar_1.png',), - Positioned(child: TDBadge(TDBadgeType.redPoint), right: 0, top: 0) - ], - ), + Widget _buildBadgeAvatar(BuildContext context) { + return const Row( + // spacing: 32, + children: [ + SizedBox( + height: 51, + width: 51, + child: Stack( + alignment: Alignment.bottomLeft, + children: [ + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.normal, + defaultUrl: 'assets/img/td_avatar_1.png', + ), + Positioned(child: TDBadge(TDBadgeType.redPoint), right: 0, top: 0) + ], ), - const SizedBox(width: 32,), - SizedBox( - height: 51, - width: 51, - child: Stack( - alignment:Alignment.bottomLeft, - children: const [ - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.customText, - text: 'A'), - Positioned(child: TDBadge(TDBadgeType.message,count: '8',), right: 0, top: 0) - ], - ), + ), + SizedBox(width: 32), + SizedBox( + height: 51, + width: 51, + child: Stack( + alignment: Alignment.bottomLeft, + children: [ + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.customText, + text: 'A', + ), + Positioned( + child: TDBadge(TDBadgeType.message, count: '8'), + right: 0, + top: 0, + ) + ], ), - const SizedBox(width: 32,), - SizedBox( - width: 51, - height: 51, - child: Stack( - alignment:Alignment.bottomLeft, - children: const [ - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.icon,), - Positioned(child: TDBadge(TDBadgeType.message,count: '12',), right: 0, top: 0,) - ], - ), + ), + SizedBox(width: 32), + SizedBox( + width: 51, + height: 51, + child: Stack( + alignment: Alignment.bottomLeft, + children: [ + TDAvatar(size: TDAvatarSize.medium, type: TDAvatarType.icon), + Positioned( + child: TDBadge(TDBadgeType.message, count: '12'), + right: 0, + top: 0, + ) + ], ), - ], - ), + ), + ], ); } /// 纯展示的头像组 @Demo(group: 'avatar') - Widget _buildDisplayAvatar(BuildContext context){ + Widget _buildDisplayAvatar(BuildContext context) { var assetUrl = 'assets/img/td_avatar_1.png'; var assetUrl2 = 'assets/img/td_avatar_2.png'; var avatarList = [assetUrl, assetUrl2, assetUrl, assetUrl2, assetUrl]; - return Container( - alignment: Alignment.centerLeft, - padding: const EdgeInsets.only(left: 16), - child: TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.display, - displayText: '+5', - avatarDisplayListAsset: avatarList,), + return TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.display, + displayText: '+5', + avatarDisplayListAsset: avatarList, ); } /// 带操作的头像组 @Demo(group: 'avatar') - Widget _buildOperationAvatar(BuildContext context){ + Widget _buildOperationAvatar(BuildContext context) { var assetUrl = 'assets/img/td_avatar_1.png'; var assetUrl2 = 'assets/img/td_avatar_2.png'; var avatarList = [assetUrl, assetUrl2, assetUrl, assetUrl2, assetUrl]; - return Container( - alignment: Alignment.centerLeft, - padding: const EdgeInsets.only(left: 16), - child: TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.operation, - avatarDisplayListAsset: avatarList, - onTap: () { - TDToast.showText('点击了操作', context: context); - }), + return TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.operation, + avatarDisplayListAsset: avatarList, + onTap: () { + TDToast.showText('点击了操作', context: context); + }, ); } /// 组件尺寸 大尺寸 @Demo(group: 'avatar') - Widget _buildLargeAvatar(BuildContext context){ - return Padding( - padding: const EdgeInsets.only(left: 16), - child: Row( - children: const [ - TDAvatar( - size: TDAvatarSize.large, - type: TDAvatarType.normal, - defaultUrl: 'assets/img/td_avatar_1.png',), - SizedBox(width: 32,), - TDAvatar( - size: TDAvatarSize.large, - type: TDAvatarType.customText, - text: 'A'), - SizedBox(width: 32,), - TDAvatar( - size: TDAvatarSize.large, - type: TDAvatarType.icon,), - ], - ), + Widget _buildLargeAvatar(BuildContext context) { + return const Row( + // spacing: 32, + children: [ + TDAvatar( + size: TDAvatarSize.large, + type: TDAvatarType.normal, + defaultUrl: 'assets/img/td_avatar_1.png', + ), + SizedBox(width: 32), + TDAvatar( + size: TDAvatarSize.large, + type: TDAvatarType.customText, + text: 'A', + ), + SizedBox(width: 32), + TDAvatar( + size: TDAvatarSize.large, + type: TDAvatarType.icon, + ), + ], ); } /// 组件尺寸 中尺寸 @Demo(group: 'avatar') - Widget _buildMediumAvatar(BuildContext context){ - return Padding( - padding: const EdgeInsets.only(left: 16), - child: Row( - children: const [ - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.normal, - defaultUrl: 'assets/img/td_avatar_1.png',), - SizedBox(width: 48,), - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.customText, - text: 'A'), - SizedBox(width: 48,), - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.icon,), - ], - ), + Widget _buildMediumAvatar(BuildContext context) { + return const Row( + // spacing: 48, + children: [ + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.normal, + defaultUrl: 'assets/img/td_avatar_1.png', + ), + SizedBox(width: 48), + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.customText, + text: 'A', + ), + SizedBox(width: 48), + TDAvatar( + size: TDAvatarSize.medium, + type: TDAvatarType.icon, + ), + ], ); } /// 组件尺寸 小尺寸 @Demo(group: 'avatar') - Widget _buildSmallAvatar(BuildContext context){ - return Padding( - padding: const EdgeInsets.only(left: 16), - child: Row( - children: const [ - TDAvatar( - size: TDAvatarSize.small, - type: TDAvatarType.normal, - defaultUrl: 'assets/img/td_avatar_1.png',), - SizedBox(width: 56,), - TDAvatar( - size: TDAvatarSize.small, - type: TDAvatarType.customText, - text: 'A'), - SizedBox(width: 56,), - TDAvatar( - size: TDAvatarSize.small, - type: TDAvatarType.icon,), - ], - ), + Widget _buildSmallAvatar(BuildContext context) { + return const Row( + // spacing: 56, + children: [ + TDAvatar( + size: TDAvatarSize.small, + type: TDAvatarType.normal, + defaultUrl: 'assets/img/td_avatar_1.png', + ), + SizedBox(width: 56), + TDAvatar( + size: TDAvatarSize.small, + type: TDAvatarType.customText, + text: 'A', + ), + SizedBox(width: 56), + TDAvatar( + size: TDAvatarSize.small, + type: TDAvatarType.icon, + ), + ], ); } } diff --git a/tdesign-component/example/lib/page/td_backtop_page.dart b/tdesign-component/example/lib/page/td_backtop_page.dart index cbad63642..5ffbc477c 100644 --- a/tdesign-component/example/lib/page/td_backtop_page.dart +++ b/tdesign-component/example/lib/page/td_backtop_page.dart @@ -4,7 +4,6 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../annotation/demo.dart'; import '../base/example_widget.dart'; - class TDBackTopPage extends StatefulWidget { const TDBackTopPage({Key? key}) : super(key: key); @@ -16,11 +15,20 @@ class _TDBackTopPageState extends State { ScrollController controller = ScrollController(); bool showBackTop = false; TDBackTopStyle style = TDBackTopStyle.circle; + TDBackTopTheme theme = TDBackTopTheme.light; @override void initState() { super.initState(); controller.addListener(listenCallback); + + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + theme = Theme.of(context).brightness == Brightness.dark + ? TDBackTopTheme.light + : TDBackTopTheme.dark; + }); + }); } @override @@ -30,18 +38,11 @@ class _TDBackTopPageState extends State { } void listenCallback() { - if (controller.offset >= 100) { - if (!showBackTop) { - setState(() { - showBackTop = true; - }); - } - } else { - if (showBackTop) { - setState(() { - showBackTop = false; - }); - } + final shouldShow = controller.offset >= 100; + if (shouldShow != showBackTop) { + setState(() { + showBackTop = shouldShow; + }); } } @@ -63,16 +64,16 @@ class _TDBackTopPageState extends State { bottom: 10, child: TDBackTop( controller: controller, - theme: TDBackTopTheme.dark, + theme: theme, showText: true, style: style, )) : TDBackTop( controller: controller, - theme: TDBackTopTheme.dark, + theme: theme, showText: true, style: style, - )) + )), ], ), children: [ @@ -114,14 +115,7 @@ class _TDBackTopPageState extends State { child: Wrap( spacing: 16, runSpacing: 24, - children: [ - getDemoBox(context), - getDemoBox(context), - getDemoBox(context), - getDemoBox(context), - getDemoBox(context), - getDemoBox(context), - ], + children: List.generate(6, (_) => getDemoBox(context)), ), ) ], @@ -130,46 +124,49 @@ class _TDBackTopPageState extends State { Widget getCustomButton( BuildContext context, String text, void Function() onTap) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TDButton( - text: text, - width: MediaQuery.of(context).size.width - 16 * 2, - size: TDButtonSize.large, - type: TDButtonType.outline, - shape: TDButtonShape.rectangle, - theme: TDButtonTheme.primary, - onTap: onTap, - )); + return TDButton( + text: text, + isBlock: true, + size: TDButtonSize.large, + type: TDButtonType.outline, + shape: TDButtonShape.rectangle, + theme: TDButtonTheme.primary, + onTap: onTap, + ); } Widget getDemoBox(BuildContext context) { + final theme = TDTheme.of(context); return Column( crossAxisAlignment: CrossAxisAlignment.start, + // spacing: 10, children: [ Container( width: 163, height: 163, decoration: BoxDecoration( - color: Colors.white, borderRadius: BorderRadius.circular(12)), - ), - const SizedBox( - height: 10, + color: theme.bgColorContainer, + borderRadius: BorderRadius.circular(theme.radiusExtraLarge), + ), ), + const SizedBox(height: 10), Container( width: 163, height: 16, decoration: BoxDecoration( - color: Colors.white, borderRadius: BorderRadius.circular(3)), - ), - const SizedBox( - height: 10, + color: theme.bgColorContainer, + borderRadius: BorderRadius.circular(theme.radiusSmall), + ), ), + const SizedBox(height: 10), Container( - width: 100, - height: 16, - decoration: BoxDecoration( - color: Colors.white, borderRadius: BorderRadius.circular(3))), + width: 100, + height: 16, + decoration: BoxDecoration( + color: theme.bgColorContainer, + borderRadius: BorderRadius.circular(theme.radiusSmall), + ), + ), ], ); } diff --git a/tdesign-component/example/lib/page/td_badge_page.dart b/tdesign-component/example/lib/page/td_badge_page.dart index d81df2424..281aac1a9 100644 --- a/tdesign-component/example/lib/page/td_badge_page.dart +++ b/tdesign-component/example/lib/page/td_badge_page.dart @@ -11,8 +11,12 @@ class TDBadgePage extends StatefulWidget { } class _TDBadgePageState extends State { + int num = 8; + @override Widget build(BuildContext context) { + var padding = const EdgeInsets.symmetric(horizontal: 16); + return ExamplePage( title: tdTitle(), desc: '用于告知用户,该区域的状态变化或者待处理任务的数量。', @@ -24,58 +28,52 @@ class _TDBadgePageState extends State { ExampleItem( desc: '红点徽标', ignoreCode: true, + padding: padding, builder: (context) { return Row( + // spacing: 32, crossAxisAlignment: CrossAxisAlignment.center, children: [ - CodeWrapper( - builder: _buildRedPointMessageBadge, - ), - CodeWrapper( - builder: _buildRedPointIconBadge, - ), - CodeWrapper( - builder: _buildRedPointButtonBadge, - ), + CodeWrapper(builder: _buildRedPointMessageBadge), + const SizedBox(width: 32), + CodeWrapper(builder: _buildRedPointIconBadge), + const SizedBox(width: 32), + CodeWrapper(builder: _buildRedPointButtonBadge), ], ); }), - ExampleItem( desc: '数字徽标', ignoreCode: true, + padding: padding, builder: (context) { return Row( + // spacing: 32, crossAxisAlignment: CrossAxisAlignment.center, children: [ - CodeWrapper( - builder: _buildMessageNumberBadge, - ), - CodeWrapper( - builder: _buildIconNumberBadge, - ), - CodeWrapper( - builder: _buildButtonNumberBadge, - ), + CodeWrapper(builder: _buildMessageNumberBadge), + const SizedBox(width: 32), + CodeWrapper(builder: _buildIconNumberBadge), + const SizedBox(width: 32), + CodeWrapper(builder: _buildButtonNumberBadge), ], ); }), ExampleItem( desc: '自定义徽标', ignoreCode: true, + padding: padding, builder: (context) { return Row( crossAxisAlignment: CrossAxisAlignment.center, + // spacing: 32, children: [ + CodeWrapper(builder: _buildCustomBadgeShowingNumber), + const SizedBox(width: 32), + CodeWrapper(builder: _buildCustomBadgeShowingNumberZero), + const SizedBox(width: 32), CodeWrapper( - builder: _buildCustomBadgeShowingNumberEight, - ), - CodeWrapper( - builder: _buildCustomBadgeShowingNumberZero, - ), - CodeWrapper( - builder: _buildCustomBadgeWithoutShowingNumberZero, - ), + builder: _buildCustomBadgeWithoutShowingNumberZero), ], ); }), @@ -100,317 +98,250 @@ class _TDBadgePageState extends State { ], test: [ ExampleItem( - ignoreCode: true, - desc: '未超过上限', - builder: (context) { - return Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CodeWrapper( - builder: _buildLessThanMaxCountBadge, - ), - ], - ); - }), + ignoreCode: true, + desc: '未超过上限', + builder: _buildLessThanMaxCountBadge, + ), ExampleItem( - ignoreCode: true, - desc: '超过上限', - builder: (context) { - return Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CodeWrapper( - builder: _buildMoreThanMaxCountBadge, - ), - ], - ); - }) + ignoreCode: true, + desc: '超过上限', + builder: _buildMoreThanMaxCountBadge, + ) ], + floatingActionButton: TDFab( + theme: TDFabTheme.primary, + onClick: () { + setState(() { + num = num + 1; + }); + }), ); } @Demo(group: 'badge') Widget _buildRedPointMessageBadge(BuildContext context) { - return Container( + return SizedBox( + width: 40, + height: 24, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(left: 16, right: 16), - child: SizedBox( - width: 40, - height: 24, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - TDText( - '消息', - font: TDTheme.of(context).fontBodyLarge, - ), - const Positioned( - child: TDBadge(TDBadgeType.redPoint), - right: 0, - top: 0, - ) - ], + children: [ + TDText( + '消息', + font: TDTheme.of(context).fontBodyLarge, ), - )); + const Positioned( + child: TDBadge(TDBadgeType.redPoint), + right: 0, + top: 0, + ) + ], + ), + ); } @Demo(group: 'badge') Widget _buildRedPointIconBadge(BuildContext context) { - return Container( + return const SizedBox( + width: 27, + height: 27, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(left: 16, right: 16), - child: SizedBox( - width: 27, - height: 27, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - Icon(TDIcons.notification), - Positioned( - child: TDBadge(TDBadgeType.redPoint), - right: 0, - top: 0, - ) - ], - ), - )); + children: [ + Icon(TDIcons.notification), + Positioned( + child: TDBadge(TDBadgeType.redPoint), + right: 0, + top: 0, + ) + ], + ), + ); } @Demo(group: 'badge') Widget _buildRedPointButtonBadge(BuildContext context) { - return Container( + return const SizedBox( + width: 83, + height: 48, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(left: 16, right: 16), - child: SizedBox( - width: 83, - height: 48, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - TDButton( - width: 80, - height: 48, - text: '按钮', - size: TDButtonSize.large, - type: TDButtonType.fill, - ), - Positioned( - child: TDBadge(TDBadgeType.redPoint), - right: 0, - top: 0, - ) - ], + children: [ + TDButton( + width: 80, + height: 48, + text: '按钮', + size: TDButtonSize.large, + type: TDButtonType.fill, ), - )); + Positioned( + child: TDBadge(TDBadgeType.redPoint), + right: 0, + top: 0, + ) + ], + ), + ); } @Demo(group: 'badge') Widget _buildMessageNumberBadge(BuildContext context) { - return Container( + return SizedBox( + width: 56, + height: 36, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(left: 16), - child: SizedBox( - width: 54, - height: 36, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - TDText( - '消息', - font: TDTheme.of(context).fontBodyLarge, - ), - const Positioned( - child: TDBadge( - TDBadgeType.message, - count: '8', - ), - left: 28, - bottom: 18, - ) - ], - ), - )); + children: [ + TDText('消息', font: TDTheme.of(context).fontBodyLarge), + Positioned( + child: TDBadge(TDBadgeType.message, count: num.toString()), + left: 28, + bottom: 18, + ) + ], + ), + ); } @Demo(group: 'badge') Widget _buildIconNumberBadge(BuildContext context) { - return Container( + return SizedBox( + width: 46, + height: 36, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(left: 16), - child: SizedBox( - width: 42, - height: 36, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - Icon(TDIcons.notification), - Positioned( - child: TDBadge( - TDBadgeType.message, - count: '8', - ), - left: 18, - bottom: 18, - ) - ], - ), - )); + children: [ + const Icon(TDIcons.notification), + Positioned( + child: TDBadge(TDBadgeType.message, count: num.toString()), + left: 18, + bottom: 18, + ) + ], + ), + ); } @Demo(group: 'badge') Widget _buildButtonNumberBadge(BuildContext context) { - return Container( + return SizedBox( + width: 86, + height: 54, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(left: 16), - child: SizedBox( - width: 86, - height: 54, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - TDButton( - width: 80, - height: 48, - text: '按钮', - size: TDButtonSize.large, - ), - Positioned( - child: TDBadge( - TDBadgeType.message, - count: '8', - ), - right: 0, - top: 0, - ) - ], + children: [ + const TDButton( + width: 80, + height: 48, + text: '按钮', + size: TDButtonSize.large, ), - )); + Positioned( + child: TDBadge(TDBadgeType.message, count: num.toString()), + right: 0, + top: 0, + ) + ], + ), + ); } @Demo(group: 'badge') - Widget _buildCustomBadgeShowingNumberEight(BuildContext context) { - return Container( + Widget _buildCustomBadgeShowingNumber(BuildContext context) { + return SizedBox( + width: 64, + height: 56, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(top: 8, left: 16, right: 16, bottom: 8), - child: SizedBox( - width: 64, - height: 56, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - Container( - child: const Icon(TDIcons.notification), - decoration: BoxDecoration( - color: TDTheme.of(context).grayColor2, - borderRadius: BorderRadius.circular( - TDTheme.of(context).radiusDefault)), - height: 48, - width: 48, - ), - const Positioned( - child: TDBadge( - TDBadgeType.message, - count: '8', - ), - right: 0, - top: 0, - ) - ], + children: [ + Container( + child: const Icon(TDIcons.notification), + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorComponent, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)), + height: 48, + width: 48, ), - )); + Positioned( + child: TDBadge(TDBadgeType.message, count: num.toString()), + right: 0, + top: 0, + ) + ], + ), + ); } @Demo(group: 'badge') Widget _buildCustomBadgeShowingNumberZero(BuildContext context) { - return Container( + return SizedBox( + width: 64, + height: 56, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(top: 8, left: 16, right: 16, bottom: 8), - child: SizedBox( - width: 64, - height: 56, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - Container( - child: const Icon(TDIcons.notification), - decoration: BoxDecoration( - color: TDTheme.of(context).grayColor2, - borderRadius: BorderRadius.circular( - TDTheme.of(context).radiusDefault)), - height: 48, - width: 48, - ), - const Positioned( - child: TDBadge( - TDBadgeType.message, - count: '0', - ), - right: 0, - top: 0, - ) - ], + children: [ + Container( + child: const Icon(TDIcons.notification), + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorComponent, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)), + height: 48, + width: 48, ), - )); + const Positioned( + child: TDBadge(TDBadgeType.message, count: '0'), + right: 0, + top: 0, + ) + ], + ), + ); } @Demo(group: 'badge') Widget _buildCustomBadgeWithoutShowingNumberZero(BuildContext context) { - return Container( + return SizedBox( + width: 64, + height: 56, + child: Stack( alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(top: 8, left: 16, right: 16, bottom: 8), - child: SizedBox( - width: 64, - height: 56, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - Container( - child: const Icon(TDIcons.notification), - decoration: BoxDecoration( - color: TDTheme.of(context).grayColor2, - borderRadius: BorderRadius.circular( - TDTheme.of(context).radiusDefault)), - height: 48, - width: 48, - ), - const Positioned( - child: TDBadge( - TDBadgeType.message, - count: '0', - showZero: false, - ), - right: 0, - top: 0, - ) - ], + children: [ + Container( + child: const Icon(TDIcons.notification), + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorComponent, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)), + height: 48, + width: 48, ), - )); + const Positioned( + // 不显示 0 + child: TDBadge(TDBadgeType.message, count: '0', showZero: false), + right: 0, + top: 0, + ) + ], + ), + ); } @Demo(group: 'badge') Widget _buildCircleBadge(BuildContext context) { - return Padding( - padding: EdgeInsets.only(left: 16), - child: Row( + return SizedBox( + width: 48, + height: 34, + child: Stack( + alignment: Alignment.bottomLeft, children: [ - SizedBox( - width: 48, - height: 34, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - Icon(TDIcons.notification), - Positioned( - child: TDBadge( - TDBadgeType.message, - count: '16', - ), - left: 18, - bottom: 18, - ) - ], - ), - ), + const Icon(TDIcons.notification), + Positioned( + child: TDBadge(TDBadgeType.message, count: num.toString()), + left: 18, + bottom: 18, + ) ], ), ); @@ -418,29 +349,22 @@ class _TDBadgePageState extends State { @Demo(group: 'badge') Widget _buildSquareBadge(BuildContext context) { - return Padding( - padding: EdgeInsets.only(left: 16), - child: Row( + return SizedBox( + width: 48, + height: 34, + child: Stack( + alignment: Alignment.bottomLeft, children: [ - SizedBox( - width: 48, - height: 34, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - Icon(TDIcons.notification), - Positioned( - child: TDBadge( - TDBadgeType.square, - border: TDBadgeBorder.small, - count: '16', - ), - left: 20, - bottom: 18, - ) - ], + const Icon(TDIcons.notification), + Positioned( + child: TDBadge( + TDBadgeType.square, + border: TDBadgeBorder.small, + count: num.toString(), ), - ), + left: 20, + bottom: 18, + ) ], ), ); @@ -448,36 +372,26 @@ class _TDBadgePageState extends State { @Demo(group: 'badge') Widget _buildBubbleBadge(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16), - child: Row( + return SizedBox( + width: 67, + height: 56, + child: Stack( + alignment: Alignment.bottomLeft, children: [ - SizedBox( - width: 67, - height: 56, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - Container( - child: const Icon(TDIcons.shop), - decoration: BoxDecoration( - color: TDTheme.of(context).grayColor2, - borderRadius: BorderRadius.circular( - TDTheme.of(context).radiusDefault)), - height: 48, - width: 48, - ), - const Positioned( - child: TDBadge( - TDBadgeType.bubble, - count: '领积分', - ), - right: 0, - top: 0, - ) - ], - ), + Container( + child: const Icon(TDIcons.shop), + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorComponent, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)), + height: 48, + width: 48, ), + const Positioned( + child: TDBadge(TDBadgeType.bubble, count: '领积分'), + right: 0, + top: 0, + ) ], ), ); @@ -485,57 +399,30 @@ class _TDBadgePageState extends State { @Demo(group: 'badge') Widget _buildSubscriptBadge(BuildContext context) { - return Stack( + return const Stack( alignment: Alignment.topRight, children: [ - Container( - padding: const EdgeInsets.only(left: 16), - alignment: Alignment.centerLeft, - child: TDText( - '单行标题', - textColor: TDTheme.of(context).fontGyColor1, - font: TDTheme.of(context).fontBodyLarge, - ), - color: Colors.white, - height: 48, - width: MediaQuery.of(context).size.width, - ), - const TDBadge( - TDBadgeType.subscript, - message: 'NEW', - ), + TDCell(title: '单行标题'), + TDBadge(TDBadgeType.subscript, message: 'NEW'), ], ); } @Demo(group: 'badge') Widget _buildLargeBadge(BuildContext context) { - return Padding( - padding: EdgeInsets.only(left: 16), - child: Row( + return SizedBox( + width: 80, + height: 68, + child: Stack( + alignment: Alignment.bottomLeft, children: [ - SizedBox( - width: 68, - height: 70, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - TDAvatar( - size: TDAvatarSize.large, - type: TDAvatarType.icon, - ), - Positioned( - child: TDBadge( - TDBadgeType.message, - size: TDBadgeSize.large, - count: '8', - ), - left: 48, - bottom: 48, - ) - ], - ), - ), + const TDAvatar(size: TDAvatarSize.large, type: TDAvatarType.icon), + Positioned( + child: TDBadge(TDBadgeType.message, + size: TDBadgeSize.large, count: num.toString()), + left: 48, + bottom: 48, + ) ], ), ); @@ -543,31 +430,18 @@ class _TDBadgePageState extends State { @Demo(group: 'badge') Widget _buildMediumBadge(BuildContext context) { - return Container( - padding: const EdgeInsets.only(left: 16), - child: Row( + return SizedBox( + width: 72, + height: 54, + child: Stack( + alignment: Alignment.bottomLeft, children: [ - SizedBox( - width: 120, - height: 54, - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - TDAvatar( - size: TDAvatarSize.medium, - type: TDAvatarType.icon, - ), - Positioned( - child: TDBadge( - TDBadgeType.message, - count: '8', - ), - left: 36, - bottom: 36, - ) - ], - ), - ), + const TDAvatar(size: TDAvatarSize.medium, type: TDAvatarType.icon), + Positioned( + child: TDBadge(TDBadgeType.message, count: num.toString()), + left: 36, + bottom: 36, + ) ], ), ); @@ -575,63 +449,53 @@ class _TDBadgePageState extends State { @Demo(group: 'badge') Widget _buildLessThanMaxCountBadge(BuildContext context) { - return Container( - alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(left: 16, right: 16, bottom: 8), - child: SizedBox( - width: 60, - height: 50, - child: Stack( - children: [ - Positioned( - left: 0, - bottom: 0, - child: Icon(TDIcons.notification), - ), - Positioned( - child: TDBadge( - TDBadgeType.square, - count: '8888', - maxCount: '9000', - size: TDBadgeSize.large, - border: TDBadgeBorder.large, - ), - left: 18, - bottom: 18, - ), - ], + return const SizedBox( + width: 60, + height: 50, + child: Stack( + children: [ + Positioned( + left: 0, + bottom: 0, + child: Icon(TDIcons.notification), ), - )); + Positioned( + child: TDBadge( + TDBadgeType.square, + count: '8888', + maxCount: '9000', + size: TDBadgeSize.large, + border: TDBadgeBorder.large, + ), + left: 18, + bottom: 18, + ), + ], + ), + ); } @Demo(group: 'badge') Widget _buildMoreThanMaxCountBadge(BuildContext context) { - return Container( - alignment: Alignment.bottomLeft, - margin: const EdgeInsets.only(left: 16, right: 16, bottom: 8), - child: SizedBox( - width: 60, - height: 50, - child: Stack( - children: [ - Positioned( - left: 0, - bottom: 0, - child: Icon(TDIcons.notification), - ), - Positioned( - child: TDBadge( - TDBadgeType.square, - count: '888', - maxCount: '99', - size: TDBadgeSize.large, - border: TDBadgeBorder.large, - ), - left: 18, - bottom: 18, - ), - ], + return const SizedBox( + width: 60, + height: 50, + child: Stack( + children: [ + Positioned(left: 0, bottom: 0, child: Icon(TDIcons.notification)), + Positioned( + child: TDBadge( + TDBadgeType.square, + count: '888', + maxCount: '99', + size: TDBadgeSize.large, + border: TDBadgeBorder.large, + ), + left: 18, + bottom: 18, ), - )); + ], + ), + ); } } diff --git a/tdesign-component/example/lib/page/td_bottom_tab_bar_page.dart b/tdesign-component/example/lib/page/td_bottom_tab_bar_page.dart index 6b0191964..e436c4faf 100644 --- a/tdesign-component/example/lib/page/td_bottom_tab_bar_page.dart +++ b/tdesign-component/example/lib/page/td_bottom_tab_bar_page.dart @@ -33,180 +33,47 @@ class _TDBottomTabBarPageState extends State { _unSelectedIcon = Icon( TDIcons.app, size: 20, - color: TDTheme.of(context).brandNormalColor, + color: TDTheme.of(context).textColorPrimary, ); return ExamplePage( title: tdTitle(), desc: '用于在不同功能模块之间进行快速切换,位于页面底部。', exampleCodeGroup: 'bottomTabBar', + padding: const EdgeInsets.only(bottom: 16), children: [ ExampleModule( title: '组件类型', children: [ - ExampleItem( - ignoreCode: true, - desc: '纯文本标签栏', - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _textTypeTabBar), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _textTypeTabBar3tabs), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _textTypeTabBar4tabs), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _textTypeTabBar5tabs), - ); - }), - ExampleItem( - ignoreCode: true, - desc: '图标加文本标签栏', - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _iconTextTypeTabBar), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _iconTextTypeTabBar3tabs), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _iconTextTypeTabBar4tabs), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _iconTextTypeTabBar5tabs), - ); - }), - ExampleItem( - ignoreCode: true, - desc: '纯图标标签栏', - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _iconTypeTabBar), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _iconTypeTabBar3tabs), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _iconTypeTabBar4tabs), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _iconTypeTabBar5tabs), - ); - }), - ExampleItem( - desc: '双层级文本标签栏', - builder: _expansionPanelTypeTabBar, - ), + ExampleItem(desc: '纯文本标签栏', builder: _textTypeTabBar), + ExampleItem(builder: _textTypeTabBar3tabs), + ExampleItem(builder: _textTypeTabBar4tabs), + ExampleItem(builder: _textTypeTabBar5tabs), + ExampleItem(desc: '图标加文本标签栏', builder: _iconTextTypeTabBar), + ExampleItem(builder: _iconTextTypeTabBar3tabs), + ExampleItem(builder: _iconTextTypeTabBar4tabs), + ExampleItem(builder: _iconTextTypeTabBar5tabs), + ExampleItem(desc: '纯图标标签栏', builder: _iconTypeTabBar), + ExampleItem(builder: _iconTypeTabBar3tabs), + ExampleItem(builder: _iconTypeTabBar4tabs), + ExampleItem(builder: _iconTypeTabBar5tabs), + ExampleItem(desc: '双层级文本标签栏', builder: _expansionPanelTypeTabBar), ], ), ExampleModule(title: '组件样式', children: [ - ExampleItem( - ignoreCode: true, - desc: '弱选中标签栏', - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _weakSelectTextTabBar), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _weakSelectIconTabBar), - ); - }), - ExampleItem( - ignoreCode: true, - builder: (context) { - return Container( - padding: const EdgeInsets.only(bottom: 16), - child: CodeWrapper(builder: _weakSelectIconTextTabBar), - ); - }), - ExampleItem( - desc: '悬浮胶囊标签栏', - builder: _capsuleTabBar, - ), + ExampleItem(desc: '弱选中标签栏', builder: _weakSelectTextTabBar), + ExampleItem(builder: _weakSelectIconTabBar), + ExampleItem(builder: _weakSelectIconTextTabBar), + ExampleItem(desc: '悬浮胶囊标签栏', builder: _capsuleTabBar), ]), ExampleModule(title: '组件事件', children: [ - ExampleItem( - desc: '长按触发', - builder: _capsuleTabBarOnLongPress, - ), + ExampleItem(desc: '长按触发', builder: _capsuleTabBarOnLongPress), ]), ], test: [ ExampleItem(desc: '自定义上边线样式', builder: _buildCustomTopStyle), ExampleItem(desc: '自定义选择的背景颜色', builder: _customBgColor), - ExampleItem( - ignoreCode: true, - desc: '设置文本标签栏背景', - builder: (context) { - return CodeWrapper(builder: _customBgTypeTabBar); - }), - ExampleItem( - ignoreCode: true, - desc: '外部设置tabbar的选中项', - builder: (context) { - return CodeWrapper(builder: _setCurrentIndexToTabBar); - }), - ExampleItem( - ignoreCode: true, - desc: 'icon默认大小底部文字不溢出', - builder: (context) { - return CodeWrapper(builder: _iconTextTypeTabBarOverflow); - }), + ExampleItem(desc: '设置文本标签栏背景', builder: _customBgTypeTabBar), + ExampleItem(desc: '外部设置tabbar的选中项', builder: _setCurrentIndexToTabBar), ExampleItem(desc: 'onTap支持重复触发', builder: _allowMultipleTaps), ExampleItem(desc: '支持水波纹效果', builder: _needInkWellTabBar), ], @@ -215,432 +82,214 @@ class _TDBottomTabBarPageState extends State { @Demo(group: 'bottomTabBar') Widget _textTypeTabBar(BuildContext context) { - var _currentIndex = 0; - void _onTapTab(BuildContext context, String tabName, int currentIndex, - int currentSelectIndex) { - print('点击了 $tabName, 当前index: $currentIndex, 当前选择index: $currentSelectIndex'); - if (currentIndex == currentSelectIndex) { - TDToast.showText('$tabName 已经被选中了', context: context); - return; - } - TDToast.showText('点击了 $tabName', context: context); - } - - return TDBottomTabBar(TDBottomTabBarBasicType.text, - currentIndex: _currentIndex, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - _onTapTab(context, '标签1', 0, _currentIndex); - _currentIndex = 0; - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - _onTapTab(context, '标签2', 1, _currentIndex); - _currentIndex = 1; - }, - ), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.text, + useVerticalDivider: false, + navigationTabs: List.generate(2, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, + onTap: () { + onTapTab(context, label); + }, + ); + }), + ); } @Demo(group: 'bottomTabBar') Widget _textTypeTabBar3tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.text, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.text, + useVerticalDivider: false, + navigationTabs: List.generate(3, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, + onTap: () { + onTapTab(context, label); + }, + ); + }), + ); } @Demo(group: 'bottomTabBar') Widget _textTypeTabBar4tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.text, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.text, + useVerticalDivider: false, + navigationTabs: List.generate(4, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, + onTap: () { + onTapTab(context, label); + }, + ); + }), + ); } @Demo(group: 'bottomTabBar') Widget _textTypeTabBar5tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.text, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.text, + useVerticalDivider: false, + navigationTabs: List.generate(5, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, + onTap: () { + onTapTab(context, label); + }, + ); + }), + ); } @Demo(group: 'bottomTabBar') Widget _iconTextTypeTabBar(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.iconText, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.iconText, + useVerticalDivider: false, + navigationTabs: List.generate(2, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + onTap: () { + onTapTab(context, label); + }, + ); + }), + ); } @Demo(group: 'bottomTabBar') Widget _iconTextTypeTabBar3tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.iconText, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.iconText, + useVerticalDivider: false, + navigationTabs: List.generate(3, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + onTap: () { + onTapTab(context, label); + }, + ); + }), + ); } @Demo(group: 'bottomTabBar') Widget _iconTextTypeTabBar4tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.iconText, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.iconText, + useVerticalDivider: false, + navigationTabs: List.generate(4, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + onTap: () { + onTapTab(context, label); + }, + ); + }), + ); } @Demo(group: 'bottomTabBar') Widget _iconTextTypeTabBar5tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.iconText, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - ]); - } - - @Demo(group: 'bottomTabBar') - Widget _iconTextTypeTabBarOverflow(BuildContext context) { - final selectedIcon = Icon( - TDIcons.app, - color: TDTheme.of(context).brandNormalColor, - ); - final unSelectedIcon = Icon( - TDIcons.app, - color: TDTheme.of(context).brandNormalColor, + return TDBottomTabBar( + TDBottomTabBarBasicType.iconText, + useVerticalDivider: false, + navigationTabs: List.generate(5, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + onTap: () { + onTapTab(context, label); + }, + ); + }), ); - return TDBottomTabBar(TDBottomTabBarBasicType.iconText, - useVerticalDivider: false, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: selectedIcon, - unselectedIcon: unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: selectedIcon, - unselectedIcon: unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: selectedIcon, - unselectedIcon: unSelectedIcon, - onTap: () { - onTapTab(context, '标签3'); - }, - ), - ]); } @Demo(group: 'bottomTabBar') Widget _iconTypeTabBar(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.icon, - useVerticalDivider: true, - navigationTabs: [ - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }) - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.icon, + useVerticalDivider: true, + navigationTabs: List.generate(2, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + onTap: () { + onTapTab(context, label); + }); + }), + ); } @Demo(group: 'bottomTabBar') Widget _iconTypeTabBar3tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.icon, - useVerticalDivider: true, - navigationTabs: [ - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.icon, + useVerticalDivider: true, + navigationTabs: List.generate(3, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + onTap: () { + onTapTab(context, label); + }); + }), + ); } @Demo(group: 'bottomTabBar') Widget _iconTypeTabBar4tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.icon, - useVerticalDivider: true, - navigationTabs: [ - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.icon, + useVerticalDivider: true, + navigationTabs: List.generate(4, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + onTap: () { + onTapTab(context, label); + }); + }), + ); } @Demo(group: 'bottomTabBar') Widget _iconTypeTabBar5tabs(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.icon, - useVerticalDivider: true, - navigationTabs: [ - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }), - ]); + return TDBottomTabBar( + TDBottomTabBarBasicType.icon, + useVerticalDivider: true, + navigationTabs: List.generate(5, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + onTap: () { + onTapTab(context, label); + }); + }), + ); } @Demo(group: 'bottomTabBar') @@ -664,6 +313,7 @@ class _TDBottomTabBarPageState extends State { TDBottomTabBarTabConfig( tabText: '展开项', onTap: () { + // 不触发点击事件 onTapTab(context, '展开项'); }, popUpButtonConfig: TDBottomTabBarPopUpBtnConfig( @@ -672,22 +322,15 @@ class _TDBottomTabBarPageState extends State { arrowWidth: 16, arrowHeight: 8, ), - items: [ - '展开项一', - '展开项二', - '展开项三', - ] + items: ['展开项一', '展开项二', '展开项三'] .reversed .map((e) => PopUpMenuItem( value: e, - itemWidget: SizedBox( - //height: 30, - child: Text( - e, - style: TextStyle( - color: TDTheme.of(context).fontGyColor1, - fontSize: 16), - ), + itemWidget: Text( + e, + style: TextStyle( + color: TDTheme.of(context).textColorPrimary, + fontSize: 16), ), )) .toList(), @@ -817,84 +460,44 @@ class _TDBottomTabBarPageState extends State { @Demo(group: 'bottomTabBar') Widget _capsuleTabBar(BuildContext context) { - return TDBottomTabBar( - TDBottomTabBarBasicType.iconText, - componentType: TDBottomTabBarComponentType.label, - outlineType: TDBottomTabBarOutlineType.capsule, - useVerticalDivider: true, - navigationTabs: [ - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - tabText: '标签', - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - tabText: '标签', - onTap: () { - onTapTab(context, '标签3'); - }, - ), - ], - ); + return TDBottomTabBar(TDBottomTabBarBasicType.iconText, + componentType: TDBottomTabBarComponentType.label, + outlineType: TDBottomTabBarOutlineType.capsule, + useVerticalDivider: true, + navigationTabs: List.generate(3, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + tabText: label, + onTap: () { + onTapTab(context, label); + }, + ); + })); } @Demo(group: 'bottomTabBar') Widget _capsuleTabBarOnLongPress(BuildContext context) { - return TDBottomTabBar( - TDBottomTabBarBasicType.iconText, - componentType: TDBottomTabBarComponentType.label, - outlineType: TDBottomTabBarOutlineType.capsule, - useVerticalDivider: true, - navigationTabs: [ - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - tabText: '标签', - onTap: () { - onTapTab(context, '标签1'); - }, - onLongPress: () { - print('长按了标签1'); - TDToast.showText('长按了标签1', context: context); - }, - ), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - tabText: '标签', - onTap: () { - onTapTab(context, '标签2'); - }, - onLongPress: () { - TDToast.showText('长按了标签2', context: context); - }, - ), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - tabText: '标签', - onTap: () { - onTapTab(context, '标签3'); - }, - onLongPress: () { - TDToast.showText('长按了标签3', context: context); - }, - ), - ], - ); + return TDBottomTabBar(TDBottomTabBarBasicType.iconText, + componentType: TDBottomTabBarComponentType.label, + outlineType: TDBottomTabBarOutlineType.capsule, + useVerticalDivider: true, + navigationTabs: List.generate(3, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + selectedIcon: _selectedIcon, + unselectedIcon: _unSelectedIcon, + tabText: label, + onTap: () { + onTapTab(context, label); + }, + onLongPress: () { + print('长按了${label}'); + TDToast.showText('长按了 $label', context: context); + }, + ); + })); } @Demo(group: 'bottomTabBar') @@ -945,77 +548,47 @@ class _TDBottomTabBarPageState extends State { return TDBottomTabBar(TDBottomTabBarBasicType.iconText, useVerticalDivider: false, selectedBgColor: TDTheme.of(context).errorColor3, - unselectedBgColor: TDTheme.of(context).grayColor3, - navigationTabs: [ - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', + unselectedBgColor: TDTheme.of(context).bgColorSecondaryContainer, + navigationTabs: List.generate(5, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( + tabText: label, selectedIcon: _selectedIcon, unselectedIcon: _unSelectedIcon, onTap: () { - onTapTab(context, '标签2'); + onTapTab(context, label); }, - ), - TDBottomTabBarTabConfig( - tabText: '标签', - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }, - ), - ]); + ); + })); } @Demo(group: 'bottomTabBar') Widget _customBgTypeTabBar(BuildContext context) { return TDBottomTabBar(TDBottomTabBarBasicType.text, - backgroundColor: TDTheme.of(context).successColor6, - selectedBgColor: TDTheme.of(context).errorColor1, - unselectedBgColor: TDTheme.of(context).brandColor1, + backgroundColor: TDTheme.of(context).successNormalColor, + selectedBgColor: TDTheme.of(context).errorLightColor, + unselectedBgColor: TDTheme.of(context).brandLightColor, useVerticalDivider: false, navigationTabs: [ TDBottomTabBarTabConfig( - tabText: '标签', + tabText: '标签1', onTap: () { onTapTab(context, '标签1'); }, ), TDBottomTabBarTabConfig( - tabText: '标签', + tabText: '标签2', unselectTabTextStyle: - TextStyle(color: TDTheme.of(context).fontGyColor1), + TextStyle(color: TDTheme.of(context).textColorBrand), onTap: () { - onTapTab(context, '标签1'); + onTapTab(context, '标签2'); }, ), ]); } var currentIndex = 0; + @Demo(group: 'bottomTabBar') Widget _setCurrentIndexToTabBar(BuildContext context) { return SizedBox( @@ -1026,16 +599,11 @@ class _TDBottomTabBarPageState extends State { Expanded( child: PageView( children: const [ - Center( - child: TDText('页面1,手指左滑查看页面2'), - ), - Center( - child: TDText('页面2,手指右滑查看页面1'), - ), + Center(child: TDText('页面1,手指左滑查看页面2')), + Center(child: TDText('页面2,手指右滑查看页面1')), ], onPageChanged: (index) { setState(() { - // 修改选择index currentIndex = index; }); }, @@ -1045,20 +613,15 @@ class _TDBottomTabBarPageState extends State { currentIndex: currentIndex, TDBottomTabBarBasicType.icon, useVerticalDivider: true, - navigationTabs: [ - TDBottomTabBarTabConfig( + navigationTabs: List.generate(2, (index) { + final label = '标签${index + 1}'; + return TDBottomTabBarTabConfig( selectedIcon: _selectedIcon, unselectedIcon: _unSelectedIcon, onTap: () { - onTapTab(context, '标签1'); - }), - TDBottomTabBarTabConfig( - selectedIcon: _selectedIcon, - unselectedIcon: _unSelectedIcon, - onTap: () { - onTapTab(context, '标签2'); - }) - ]) + onTapTab(context, label); + }); + })) ], ), ); @@ -1066,21 +629,23 @@ class _TDBottomTabBarPageState extends State { @Demo(group: 'bottomTabBar') Widget _allowMultipleTaps(BuildContext context) { - return TDBottomTabBar(TDBottomTabBarBasicType.text, useVerticalDivider: false, navigationTabs: [ - TDBottomTabBarTabConfig( - allowMultipleTaps: true, - tabText: '支持重复点击', - onTap: () { - onTapTab(context, '标签1'); - }, - ), - TDBottomTabBarTabConfig( - tabText: '不支持重复点击', - onTap: () { - onTapTab(context, '标签2'); - }, - ), - ]); + return TDBottomTabBar(TDBottomTabBarBasicType.text, + useVerticalDivider: false, + navigationTabs: [ + TDBottomTabBarTabConfig( + allowMultipleTaps: true, + tabText: '支持重复点击', + onTap: () { + onTapTab(context, '标签1'); + }, + ), + TDBottomTabBarTabConfig( + tabText: '不支持重复点击', + onTap: () { + onTapTab(context, '标签2'); + }, + ), + ]); } @Demo(group: 'bottomTabBar') diff --git a/tdesign-component/example/lib/page/td_button_page.dart b/tdesign-component/example/lib/page/td_button_page.dart index e38f41e5d..4d5f25ac8 100644 --- a/tdesign-component/example/lib/page/td_button_page.dart +++ b/tdesign-component/example/lib/page/td_button_page.dart @@ -21,390 +21,248 @@ class _TDButtonPageState extends State { @override Widget build(BuildContext context) { - return Container( - color: TDTheme.of(context).grayColor2, - child: ExamplePage( - title: tdTitle(), - desc: '用于开启一个闭环的操作任务,如“删除”对象、“购买”商品等。', - exampleCodeGroup: 'button', - // padding: const EdgeInsets.only(top: 8, bottom: 8, ), - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem( - ignoreCode: true, - desc: '基础按钮', - builder: (context) { - return Container( - alignment: Alignment.topLeft, - padding: const EdgeInsets.only(left: 8), - child: Wrap( - children: [ - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildPrimaryFillButton, - methodName: '_buildPrimaryFillButton', - ), - ), - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildLightFillButton, - methodName: '_buildLightFillButton', - ), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildDefaultFillButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildPrimaryStrokeButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildPrimaryTextButton), - ), - ], - ), - ); - }), - ExampleItem( - ignoreCode: true, - desc: '图标按钮', - center: false, - builder: (context) { - return Container( - padding: const EdgeInsets.only(left: 8, right: 8), - child: Wrap( - children: [ - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildRectangleIconButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper(builder: _buildSquareIconButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildLoadingIconButton), - ) - ], - ), - ); - }), - ExampleItem( - ignoreCode: true, - desc: '幽灵按钮', - builder: (context) { - return Container( - alignment: Alignment.topLeft, - color: TDTheme.of(context).grayColor14, - padding: const EdgeInsets.only(left: 8, right: 8), - child: Wrap( - children: [ - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildPrimaryGhostButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildDangerGhostButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildDefaultGhostButton), - ), - ], - ), - ); - }), - ExampleItem( - ignoreCode: true, - desc: '组合按钮', - builder: (_) => - CodeWrapper(builder: _buildCombinationButtons)), - ExampleItem(desc: '通栏按钮', builder: _buildFilledFillButton), - ]), - ExampleModule(title: '组件状态', children: [ - ExampleItem( - ignoreCode: true, - desc: '按钮禁用状态', - builder: (context) { - return Container( - alignment: Alignment.topLeft, - padding: const EdgeInsets.only(left: 8), - child: Wrap( - children: [ - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildDisablePrimaryFillButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildDisableLightFillButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildDisableDefaultFillButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildDisablePrimaryStrokeButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildDisablePrimaryTextButton), - ), - ], - ), - ); - }), - ]), - ExampleModule(title: '组件主题', children: [ - ExampleItem( - ignoreCode: true, - desc: '按钮尺寸', - builder: (context) { - return Container( - alignment: Alignment.topLeft, - padding: const EdgeInsets.only(left: 10), - child: Wrap( - children: [ - Container( - margin: const EdgeInsets.all(6), - child: CodeWrapper(builder: _buildLargeButton), - ), - Container( - margin: const EdgeInsets.all(6), - child: CodeWrapper(builder: _buildMediumButton), - ), - Container( - margin: const EdgeInsets.all(6), - child: CodeWrapper(builder: _buildSmallButton), - ), - Container( - margin: const EdgeInsets.all(6), - child: CodeWrapper(builder: _buildExtraSmallButton), - ), - ], + return ExamplePage( + title: tdTitle(), + desc: '用于开启一个闭环的操作任务,如“删除”对象、“购买”商品等。', + exampleCodeGroup: 'button', + children: [ + ExampleModule(title: '组件类型', children: [ + ExampleItem( + ignoreCode: true, + desc: '基础按钮', + builder: (context) { + return Container( + alignment: Alignment.topLeft, + padding: const EdgeInsets.only(left: 16), + child: Wrap( + spacing: 16, // 主轴方向间距 + runSpacing: 16, // 交叉轴方向间距 + children: [ + CodeWrapper( + builder: _buildPrimaryFillButton, + methodName: '_buildPrimaryFillButton', ), - ); - }), - ExampleItem( - ignoreCode: true, - desc: '按钮形状', - builder: (context) { - return Container( - alignment: Alignment.topLeft, - child: Wrap( - children: [ - Container( - margin: const EdgeInsets.only( - left: 16, right: 6, top: 6), - child: CodeWrapper( - builder: _buildPrimaryFillButton, - ), - ), - Container( - margin: const EdgeInsets.all(6), - child: CodeWrapper(builder: _buildSquareIconButton), - ), - Container( - margin: const EdgeInsets.all(6), - child: CodeWrapper(builder: _buildRoundButton), - ), - Container( - margin: const EdgeInsets.only( - right: 16, left: 6, top: 6), - child: CodeWrapper(builder: _buildCircleButton), - ), - Container( - margin: const EdgeInsets.only(top: 10), - child: CodeWrapper(builder: _buildFilledButton), - ) - ], + CodeWrapper( + builder: _buildLightFillButton, + methodName: '_buildLightFillButton', ), - ); - }), - ExampleItem( - ignoreCode: true, - desc: '按钮主题', - builder: (context) { - return Container( - alignment: Alignment.topLeft, - padding: const EdgeInsets.only(left: 8), - child: Wrap( - children: [ - /// 默认主题 - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildDefaultFillButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildDefaultStrokeButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildDefaultTextButton), - ), + CodeWrapper(builder: _buildDefaultFillButton), + CodeWrapper(builder: _buildPrimaryStrokeButton), + CodeWrapper(builder: _buildPrimaryTextButton), + ], + ), + ); + }), + ExampleItem( + ignoreCode: true, + desc: '图标按钮', + center: false, + builder: (context) { + return Container( + padding: const EdgeInsets.only(left: 16), + child: Wrap( + spacing: 16, // 主轴方向间距 + runSpacing: 16, // 交叉轴方向间距 + children: [ + CodeWrapper(builder: _buildRectangleIconButton), + CodeWrapper(builder: _buildSquareIconButton), + CodeWrapper(builder: _buildLoadingIconButton) + ], + ), + ); + }), + ExampleItem( + ignoreCode: true, + desc: '幽灵按钮', + builder: (context) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 16), + alignment: Alignment.center, + color: TDTheme.of(context).grayColor14, + child: Wrap( + spacing: 16, // 主轴方向间距 + runSpacing: 16, // 交叉轴方向间距 + children: [ + CodeWrapper(builder: _buildPrimaryGhostButton), + CodeWrapper(builder: _buildDangerGhostButton), + CodeWrapper(builder: _buildDefaultGhostButton), + ], + ), + ); + }), + ExampleItem( + ignoreCode: true, + desc: '组合按钮', + builder: (_) => CodeWrapper(builder: _buildCombinationButtons)), + ExampleItem(desc: '通栏按钮', builder: _buildFilledFillButton), + ]), + ExampleModule(title: '组件状态', children: [ + ExampleItem( + ignoreCode: true, + desc: '按钮禁用状态', + builder: (context) { + return Wrap( + alignment: WrapAlignment.center, + spacing: 16, // 主轴方向间距 + runSpacing: 16, // 交叉轴方向间距 + children: [ + CodeWrapper(builder: _buildDisablePrimaryFillButton), + CodeWrapper(builder: _buildDisableLightFillButton), + CodeWrapper(builder: _buildDisableDefaultFillButton), + CodeWrapper(builder: _buildDisablePrimaryStrokeButton), + CodeWrapper(builder: _buildDisablePrimaryTextButton), + ], + ); + }), + ]), + ExampleModule(title: '组件主题', children: [ + ExampleItem( + ignoreCode: true, + desc: '按钮尺寸', + builder: (context) { + return Wrap( + alignment: WrapAlignment.center, + spacing: 16, // 主轴方向间距 + runSpacing: 16, // 交叉轴方向间距 + children: [ + CodeWrapper(builder: _buildLargeButton), + CodeWrapper(builder: _buildMediumButton), + CodeWrapper(builder: _buildSmallButton), + CodeWrapper(builder: _buildExtraSmallButton), + ], + ); + }), + ExampleItem( + ignoreCode: true, + desc: '按钮形状', + builder: (context) { + return Wrap( + alignment: WrapAlignment.center, + spacing: 16, // 主轴方向间距 + runSpacing: 16, // 交叉轴方向间距 + children: [ + CodeWrapper( + builder: _buildPrimaryFillButton, + ), + CodeWrapper(builder: _buildSquareIconButton), + CodeWrapper(builder: _buildRoundButton), + CodeWrapper(builder: _buildCircleButton), + CodeWrapper(builder: _buildFilledButton) + ], + ); + }), + ExampleItem( + ignoreCode: true, + desc: '按钮主题', + builder: (context) { + return Wrap( + alignment: WrapAlignment.center, + spacing: 16, // 主轴方向间距 + runSpacing: 16, // 交叉轴方向间距 + children: [ + /// 默认主题 + CodeWrapper(builder: _buildDefaultFillButton), + CodeWrapper(builder: _buildDefaultStrokeButton), + CodeWrapper(builder: _buildDefaultTextButton), - /// primary主题 - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildPrimaryFillButton, - ), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildPrimaryStrokeButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildPrimaryTextButton), - ), + /// primary主题 + CodeWrapper( + builder: _buildPrimaryFillButton, + ), + CodeWrapper(builder: _buildPrimaryStrokeButton), + CodeWrapper(builder: _buildPrimaryTextButton), - /// danger主题 - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper(builder: _buildDangerFillButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildDangerStrokeButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper(builder: _buildDangerTextButton), - ), + /// danger主题 + CodeWrapper(builder: _buildDangerFillButton), + CodeWrapper(builder: _buildDangerStrokeButton), + CodeWrapper(builder: _buildDangerTextButton), - /// light主题 - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper(builder: _buildLightFillButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: - CodeWrapper(builder: _buildLightStrokeButton), - ), - Container( - margin: const EdgeInsets.all(8), - child: CodeWrapper( - builder: _buildLightTextButton, - ), - ), - ], - ), - ); - }), - ]), - ], - test: [ - ExampleItem( - ignoreCode: true, - desc: '测试child', - builder: (context) { - return CodeWrapper(builder: _buildChildTestButton); - }), - ExampleItem( - ignoreCode: true, - desc: '通栏按钮测试', - builder: (context) { - return Container( - color: Colors.grey, - padding: const EdgeInsets.only(top: 16, bottom: 16), - child: Column( - mainAxisSize: MainAxisSize.min, - children: const [ - TDButton( - isBlock: true, - text: '填充block按钮', - theme: TDButtonTheme.primary, - ), - SizedBox( - height: 16, - ), - TDButton( - isBlock: true, - text: '描边block按钮', - type: TDButtonType.outline, - theme: TDButtonTheme.primary, - ), - SizedBox( - height: 16, - ), - TDButton( - isBlock: true, - text: '文字block按钮', - type: TDButtonType.text, - theme: TDButtonTheme.primary, - ), - SizedBox( - height: 16, - ), - TDButton( - isBlock: true, - text: '幽灵block按钮', - type: TDButtonType.ghost, - theme: TDButtonTheme.primary, - ), - ], + /// light主题 + CodeWrapper(builder: _buildLightFillButton), + CodeWrapper(builder: _buildLightStrokeButton), + CodeWrapper( + builder: _buildLightTextButton, ), - ); - }), - ExampleItem( - ignoreCode: true, - desc: '各种按钮状态测试', - builder: _buildStatusDisplay), - ExampleItem( - ignoreCode: true, - desc: '按钮中路由跳转', - builder: (context) { - return TDButton( - text: '点击跳转', - size: TDButtonSize.large, - // type: TDButtonType.text, - shape: TDButtonShape.rectangle, - onTap: () async { - var result = await Navigator.of(context) - .pushNamedAndRemoveUntil('divider', (router) { - return true; - }); - print('pushNamedAndRemoveUntil result: $result'); - }, - ); - }), - ExampleItem( - ignoreCode: true, - desc: '图标在文字右侧', - builder: (context) { - return CodeWrapper(builder: _buildRightIconButton); - }), - ], - )); + ], + ); + }), + ]), + ], + test: [ + ExampleItem( + ignoreCode: true, + desc: '测试child', + builder: (context) { + return CodeWrapper(builder: _buildChildTestButton); + }), + ExampleItem( + ignoreCode: true, + desc: '通栏按钮测试', + builder: (context) { + return Container( + color: TDTheme.of(context).bgColorContainer, + padding: const EdgeInsets.only(top: 16, bottom: 16), + child: const Column( + mainAxisSize: MainAxisSize.min, + // spacing: 16, + children: [ + TDButton( + isBlock: true, + text: '填充block按钮', + theme: TDButtonTheme.primary, + ), + SizedBox(height: 16), + TDButton( + isBlock: true, + text: '描边block按钮', + type: TDButtonType.outline, + theme: TDButtonTheme.primary, + ), + SizedBox(height: 16), + TDButton( + isBlock: true, + text: '文字block按钮', + type: TDButtonType.text, + theme: TDButtonTheme.primary, + ), + SizedBox(height: 16), + TDButton( + isBlock: true, + text: '幽灵block按钮', + type: TDButtonType.ghost, + theme: TDButtonTheme.primary, + ), + ], + ), + ); + }), + ExampleItem( + ignoreCode: true, desc: '各种按钮状态测试', builder: _buildStatusDisplay), + ExampleItem( + ignoreCode: true, + desc: '按钮中路由跳转', + builder: (context) { + return TDButton( + text: '点击跳转', + size: TDButtonSize.large, + shape: TDButtonShape.rectangle, + onTap: () async { + var result = await Navigator.of(context) + .pushNamedAndRemoveUntil('divider', (router) { + return true; + }); + print('pushNamedAndRemoveUntil result: $result'); + }, + ); + }), + ExampleItem( + ignoreCode: true, + desc: '图标在文字右侧', + builder: (context) { + return CodeWrapper(builder: _buildRightIconButton); + }), + ], + ); } @Demo(group: 'button') @@ -763,43 +621,41 @@ class _TDButtonPageState extends State { @Demo(group: 'button') Widget _buildCombinationButtons(BuildContext context) { - return Row( - children: const [ - SizedBox( - width: 16, - ), - Expanded( - child: TDButton( - text: '填充按钮', - size: TDButtonSize.large, - type: TDButtonType.fill, - shape: TDButtonShape.rectangle, - theme: TDButtonTheme.light, - )), - SizedBox( - width: 16, - ), - Expanded( - child: TDButton( - text: '填充按钮', - size: TDButtonSize.large, - type: TDButtonType.fill, - shape: TDButtonShape.rectangle, - theme: TDButtonTheme.primary, - )), - SizedBox( - width: 16, - ), - ], - ); + return const Padding( + padding: EdgeInsets.symmetric(horizontal: 16), + child: Row( + // spacing: 16, + children: [ + Expanded( + child: TDButton( + text: '填充按钮', + size: TDButtonSize.large, + type: TDButtonType.fill, + shape: TDButtonShape.rectangle, + theme: TDButtonTheme.light, + ), + ), + SizedBox(width: 16), + Expanded( + child: TDButton( + text: '填充按钮', + size: TDButtonSize.large, + type: TDButtonType.fill, + shape: TDButtonShape.rectangle, + theme: TDButtonTheme.primary, + ), + ), + ], + )); } @Demo(group: 'button') Widget _buildChildTestButton(BuildContext context) { return TDButton( child: Container( - height: 24, - width: 24, + // 高度被按钮约束了 + height: 48, + width: 48, color: Colors.red, ), ); @@ -807,41 +663,39 @@ class _TDButtonPageState extends State { @Demo(group: 'button') Widget _buildRightIconButton(BuildContext context) { - return Container( - margin: const EdgeInsets.all(16), - child: Wrap( - spacing: 8, - runSpacing: 8, - children: [ - TDButton( - text: '填充按钮', - icon: TDIcons.app, - size: TDButtonSize.large, - type: TDButtonType.fill, - shape: TDButtonShape.rectangle, - theme: TDButtonTheme.primary, - iconPosition: TDButtonIconPosition.right, - ), - TDButton( - icon: TDIcons.app, - size: TDButtonSize.large, - type: TDButtonType.fill, - shape: TDButtonShape.rectangle, - theme: TDButtonTheme.primary, - iconPosition: TDButtonIconPosition.right, - ), - TDButton( - text: '间距20', - icon: TDIcons.app, - size: TDButtonSize.large, - type: TDButtonType.fill, - shape: TDButtonShape.rectangle, - theme: TDButtonTheme.primary, - iconPosition: TDButtonIconPosition.right, - iconTextSpacing: 20, - ) - ], - ), + return const Wrap( + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, + children: [ + TDButton( + text: '填充按钮', + icon: TDIcons.app, + size: TDButtonSize.large, + type: TDButtonType.fill, + shape: TDButtonShape.rectangle, + theme: TDButtonTheme.primary, + iconPosition: TDButtonIconPosition.right, + ), + TDButton( + icon: TDIcons.app, + size: TDButtonSize.large, + type: TDButtonType.fill, + shape: TDButtonShape.rectangle, + theme: TDButtonTheme.primary, + iconPosition: TDButtonIconPosition.right, + ), + TDButton( + text: '间距20', + icon: TDIcons.app, + size: TDButtonSize.large, + type: TDButtonType.fill, + shape: TDButtonShape.rectangle, + theme: TDButtonTheme.primary, + iconPosition: TDButtonIconPosition.right, + iconTextSpacing: 20, + ) + ], ); } @@ -853,10 +707,11 @@ class _TDButtonPageState extends State { children: [ /// fill Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -880,10 +735,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -907,10 +763,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -934,10 +791,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -963,10 +821,11 @@ class _TDButtonPageState extends State { /// outline Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -993,10 +852,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1023,10 +883,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1053,10 +914,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1085,10 +947,11 @@ class _TDButtonPageState extends State { /// text Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1115,10 +978,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1145,10 +1009,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1175,10 +1040,11 @@ class _TDButtonPageState extends State { ), ), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 8), child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1207,11 +1073,12 @@ class _TDButtonPageState extends State { /// ghost Container( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.symmetric(vertical: 8), color: Colors.black, child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1238,11 +1105,12 @@ class _TDButtonPageState extends State { ), ), Container( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.symmetric(vertical: 8), color: Colors.black, child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1269,11 +1137,12 @@ class _TDButtonPageState extends State { ), ), Container( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.symmetric(vertical: 8), color: Colors.black, child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, @@ -1300,11 +1169,12 @@ class _TDButtonPageState extends State { ), ), Container( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.symmetric(vertical: 8), color: Colors.black, child: Wrap( - spacing: 8, - runSpacing: 8, + spacing: 16, + runSpacing: 16, + alignment: WrapAlignment.center, children: [ const TDButton( icon: TDIcons.app, diff --git a/tdesign-component/example/lib/page/td_calendar_page.dart b/tdesign-component/example/lib/page/td_calendar_page.dart index 3cd81ff6b..54fb5b66e 100644 --- a/tdesign-component/example/lib/page/td_calendar_page.dart +++ b/tdesign-component/example/lib/page/td_calendar_page.dart @@ -8,51 +8,48 @@ class TDCalendarPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - color: TDTheme.of(context).grayColor2, - child: ExamplePage( - title: tdTitle(context), - desc: '按照日历形式展示数据或日期的容器。', - exampleCodeGroup: 'calendar', - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem( - ignoreCode: true, - center: false, - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildSimple); - }, - ), - ]), - ExampleModule(title: '组件样式', children: [ - ExampleItem( - desc: '可以自由定义想要的风格', - ignoreCode: true, - center: false, - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildStyle); - }, - ), - ExampleItem( - desc: '自定义日期单元格', - ignoreCode: true, - center: false, - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildCustomCell); - }, - ), - ExampleItem( - desc: '不使用Popup', - ignoreCode: true, - center: false, - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildBlock); - }, - ), - ]), - ], - test: const [], - ), + return ExamplePage( + title: tdTitle(context), + desc: '按照日历形式展示数据或日期的容器。', + exampleCodeGroup: 'calendar', + children: [ + ExampleModule(title: '组件类型', children: [ + ExampleItem( + ignoreCode: true, + center: false, + builder: (BuildContext context) { + return const CodeWrapper(builder: _buildSimple); + }, + ), + ]), + ExampleModule(title: '组件样式', children: [ + ExampleItem( + desc: '可以自由定义想要的风格', + ignoreCode: true, + center: false, + builder: (BuildContext context) { + return const CodeWrapper(builder: _buildStyle); + }, + ), + ExampleItem( + desc: '自定义日期单元格', + ignoreCode: true, + center: false, + builder: (BuildContext context) { + return const CodeWrapper(builder: _buildCustomCell); + }, + ), + ExampleItem( + desc: '不使用Popup', + ignoreCode: true, + center: false, + builder: (BuildContext context) { + return const CodeWrapper(builder: _buildBlock); + }, + ), + ]), + ], + test: const [], ); } } @@ -60,7 +57,8 @@ class TDCalendarPage extends StatelessWidget { @Demo(group: 'calendar') Widget _buildSimple(BuildContext context) { final size = MediaQuery.of(context).size; - final selected = ValueNotifier>([DateTime.now().millisecondsSinceEpoch + 30 * 24 * 60 * 60 * 1000]); + final selected = ValueNotifier>( + [DateTime.now().millisecondsSinceEpoch + 30 * 24 * 60 * 60 * 1000]); return ValueListenableBuilder( valueListenable: selected, builder: (context, value, child) { @@ -76,7 +74,7 @@ Widget _buildSimple(BuildContext context) { context, visible: true, onConfirm: (value) { - print('onConfirm:$value'); + print('onConfirm:$value'); selected.value = value; }, onClose: () { @@ -87,16 +85,16 @@ Widget _buildSimple(BuildContext context) { value: value, height: size.height * 0.6 + 176, onCellClick: (value, type, tdate) { - print('onCellClick:$value'); + print('onCellClick: $value'); }, onCellLongPress: (value, type, tdate) { - print('onCellLongPress:$value'); + print('onCellLongPress: $value'); }, onHeaderClick: (index, week) { - print('onHeaderClick:$week'); + print('onHeaderClick: $week'); }, onChange: (value) { - print('onChange:$value'); + print('onChange: $value'); }, ), ); @@ -130,7 +128,9 @@ Widget _buildSimple(BuildContext context) { type: CalendarType.range, value: [ DateTime.now().millisecondsSinceEpoch, - DateTime.now().add(const Duration(days: 6)).millisecondsSinceEpoch, + DateTime.now() + .add(const Duration(days: 6)) + .millisecondsSinceEpoch, ], height: size.height * 0.6 + 176, ), @@ -140,7 +140,8 @@ Widget _buildSimple(BuildContext context) { TDCell( title: '单个选择日历和时间', arrow: true, - note: '${date.year}-${date.month}-${date.day} ${date.hour}:${date.minute}', + note: + '${date.year}-${date.month}-${date.day} ${date.hour}:${date.minute}', onClick: (cell) { TDCalendarPopup( context, @@ -160,16 +161,16 @@ Widget _buildSimple(BuildContext context) { // pickerHeight: 100, // pickerItemCount: 2, onCellClick: (value, type, tdate) { - print('onCellClick:$value'); + print('onCellClick: $value'); }, onCellLongPress: (value, type, tdate) { - print('onCellLongPress:$value'); + print('onCellLongPress: $value'); }, onHeaderClick: (index, week) { - print('onHeaderClick:$week'); + print('onHeaderClick: $week'); }, onChange: (value) { - print('onChange:$value'); + print('onChange: $value'); }, ), ); @@ -183,7 +184,7 @@ Widget _buildSimple(BuildContext context) { context, visible: true, onConfirm: (value) { - print('onConfirm:$value'); + print('onConfirm: $value'); }, onClose: () { print('onClose'); @@ -194,20 +195,22 @@ Widget _buildSimple(BuildContext context) { type: CalendarType.range, value: [ DateTime.now().millisecondsSinceEpoch, - DateTime.now().add(const Duration(days: 3)).millisecondsSinceEpoch, + DateTime.now() + .add(const Duration(days: 3)) + .millisecondsSinceEpoch, ], useTimePicker: true, onCellClick: (value, type, tdate) { - print('onCellClick:$value'); + print('onCellClick: $value'); }, onCellLongPress: (value, type, tdate) { - print('onCellLongPress:$value'); + print('onCellLongPress: $value'); }, onHeaderClick: (index, week) { - print('onHeaderClick:$week'); + print('onHeaderClick: $week'); }, onChange: (value) { - print('onChange:$value'); + print('onChange: $value'); }, ), ); @@ -252,11 +255,13 @@ Widget _buildStyle(BuildContext context) { day?.style = TextStyle( fontSize: TDTheme.of(context).fontTitleMedium?.size, height: TDTheme.of(context).fontTitleMedium?.height, - fontWeight: TDTheme.of(context).fontTitleMedium?.fontWeight, + fontWeight: + TDTheme.of(context).fontTitleMedium?.fontWeight, color: TDTheme.of(context).errorColor6, ); if (day?.typeNotifier.value == DateSelectType.selected) { - day?.style = day.style?.copyWith(color: TDTheme.of(context).fontWhColor1); + day?.style = day.style + ?.copyWith(color: TDTheme.of(context).fontWhColor1); } } } @@ -275,7 +280,8 @@ Widget _buildStyle(BuildContext context) { context, visible: true, confirmBtn: Padding( - padding: EdgeInsets.symmetric(vertical: TDTheme.of(context).spacer16), + padding: + EdgeInsets.symmetric(vertical: TDTheme.of(context).spacer16), child: TDButton( theme: TDButtonTheme.danger, shape: TDButtonShape.round, @@ -320,31 +326,35 @@ Widget _buildStyle(BuildContext context) { @Demo(group: 'calendar') Widget _buildBlock(BuildContext context) { final size = MediaQuery.of(context).size; - final selected = ValueNotifier>([DateTime.now().millisecondsSinceEpoch + 30 * 24 * 60 * 60 * 1000]); + final selected = ValueNotifier>( + [DateTime.now().millisecondsSinceEpoch + 30 * 24 * 60 * 60 * 1000], + ); return Column( + // spacing: TDTheme.of(context).spacer16, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( + // spacing: TDTheme.of(context).spacer16, + mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox(width: TDTheme.of(context).spacer16), TDButton( - text: '加一个月', - size: TDButtonSize.small, - theme: TDButtonTheme.primary, - onTap: () { - selected.value = [selected.value[0] + 30 * 24 * 60 * 60 * 1000]; - }), - SizedBox(width: TDTheme.of(context).spacer16), + text: '加一个月', + theme: TDButtonTheme.primary, + onTap: () { + selected.value = [selected.value[0] + 30 * 24 * 60 * 60 * 1000]; + }, + ), + const SizedBox(width: 16), TDButton( - text: '减一个月', - size: TDButtonSize.small, - theme: TDButtonTheme.primary, - onTap: () { - selected.value = [selected.value[0] - 30 * 24 * 60 * 60 * 1000]; - }), + text: '减一个月', + theme: TDButtonTheme.primary, + onTap: () { + selected.value = [selected.value[0] - 30 * 24 * 60 * 60 * 1000]; + }, + ), ], ), - SizedBox(height: TDTheme.of(context).spacer16), + const SizedBox(height: 16), ValueListenableBuilder( valueListenable: selected, builder: (context, value, child) { @@ -353,6 +363,8 @@ Widget _buildBlock(BuildContext context) { value: value, height: size.height * 0.6 + 176, animateTo: true, + // 不使用popup时,useSafeArea无效 + useSafeArea: true, ); }, ), @@ -363,7 +375,8 @@ Widget _buildBlock(BuildContext context) { @Demo(group: 'calendar') Widget _buildCustomCell(BuildContext context) { final size = MediaQuery.of(context).size; - final selected = ValueNotifier>([DateTime.now().millisecondsSinceEpoch + 30 * 24 * 60 * 60 * 1000]); + final selected = ValueNotifier>( + [DateTime.now().millisecondsSinceEpoch + 30 * 24 * 60 * 60 * 1000]); return ValueListenableBuilder( valueListenable: selected, builder: (context, value, child) { @@ -386,42 +399,51 @@ Widget _buildCustomCell(BuildContext context) { print('onClose'); }, child: TDCalendar( - title: '请选择日期', - value: value, - height: size.height * 0.6 + 176, - onCellClick: (value, type, tdate) { - print('onCellClick:$value'); - }, - onCellLongPress: (value, type, tdate) { - print('onCellLongPress:$value'); - }, - onHeaderClick: (index, week) { - print('onHeaderClick:$week'); - }, - onChange: (value) { - print('onChange:$value'); - }, - cellWidget: (context, tdate, selectType) { - if (selectType == DateSelectType.selected) { + title: '请选择日期', + value: value, + height: size.height * 0.6 + 176, + onCellClick: (value, type, tdate) { + print('onCellClick: $value'); + }, + onCellLongPress: (value, type, tdate) { + print('onCellLongPress: $value'); + }, + onHeaderClick: (index, week) { + print('onHeaderClick: $week'); + }, + onChange: (value) { + print('onChange: $value'); + }, + cellWidget: (context, tdate, selectType) { + if (selectType == DateSelectType.selected) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('${tdate.date.day}', + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.white)), + const Text('文案文案', + style: TextStyle( + fontSize: 6, color: Colors.white)), + const Text('自定义', + style: TextStyle( + fontSize: 12, color: Colors.white)), + ], + ); + } return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text('${tdate.date.day}', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white)), - Text('文案文案', style: TextStyle(fontSize: 6, color: Colors.white)), - Text('自定义', style: TextStyle(fontSize: 12, color: Colors.white)), + Text('${tdate.date.day}', + style: const TextStyle( + fontSize: 18, fontWeight: FontWeight.bold)), + const Text('文案文案', style: TextStyle(fontSize: 8)), + const Text('自定义', style: TextStyle(fontSize: 8)), ], ); - } - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('${tdate.date.day}', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), - Text('文案文案', style: TextStyle(fontSize: 8)), - Text('自定义', style: TextStyle(fontSize: 8)), - ], - ); - } - ), + }), ); }, ), diff --git a/tdesign-component/example/lib/page/td_cascader_page.dart b/tdesign-component/example/lib/page/td_cascader_page.dart index 8c1d6a79f..49db400fd 100644 --- a/tdesign-component/example/lib/page/td_cascader_page.dart +++ b/tdesign-component/example/lib/page/td_cascader_page.dart @@ -220,48 +220,67 @@ class _TDCascaderPageState extends State { 'value': '110100', 'label': '部门一', 'children': [ - {'value': '110201', 'label': '后勤部门', 'children':[ - { - 'value': '110301', 'label': '后勤A组','children':[ - { - 'value': '110401', 'label': '一组','children':[ - {'value': '110501', 'label': '洪磊',}, - {'value': '110502', 'label': '洪磊2'}, - {'value': '110506', 'label': '郭天1'}, - {'value': '110507', 'label': '郭天2'}, - {'value': '110508', 'label': '郭天3'}, - {'value': '110509', 'label': '冯笑1'}, - {'value': '1105022', 'label': '洪磊3'}, - {'value': '110505', 'label': '洪磊4'}, - ] + { + 'value': '110201', + 'label': '后勤部门', + 'children': [ + { + 'value': '110301', + 'label': '后勤A组', + 'children': [ + { + 'value': '110401', + 'label': '一组', + 'children': [ + { + 'value': '110501', + 'label': '洪磊', + }, + {'value': '110502', 'label': '洪磊2'}, + {'value': '110506', 'label': '郭天1'}, + {'value': '110507', 'label': '郭天2'}, + {'value': '110508', 'label': '郭天3'}, + {'value': '110509', 'label': '冯笑1'}, + {'value': '1105022', 'label': '洪磊3'}, + {'value': '110505', 'label': '洪磊4'}, + ] + } + ] } - ] - } - ]}, + ] + }, ], }, { 'value': '120100', 'label': '部门二', 'children': [ - {'value': '120201', 'label': '后勤部门', 'children':[ - { - 'value': '120301', 'label': '后勤A组','children':[ + { + 'value': '120201', + 'label': '后勤部门', + 'children': [ { - 'value': '120401', 'label': '一组','children':[ - {'value': '120501', 'label': '张雷1'}, - {'value': '120502', 'label': '张雷2'}, - {'value': '1205022', 'label': '张雷3'}, - {'value': '120505', 'label': '张雷4'}, - {'value': '120506', 'label': '张雷5'}, - {'value': '120507', 'label': '张雷6'}, - {'value': '120508', 'label': '张雷7'}, - {'value': '120509', 'label': '张雷8'}, - ] + 'value': '120301', + 'label': '后勤A组', + 'children': [ + { + 'value': '120401', + 'label': '一组', + 'children': [ + {'value': '120501', 'label': '张雷1'}, + {'value': '120502', 'label': '张雷2'}, + {'value': '1205022', 'label': '张雷3'}, + {'value': '120505', 'label': '张雷4'}, + {'value': '120506', 'label': '张雷5'}, + {'value': '120507', 'label': '张雷6'}, + {'value': '120508', 'label': '张雷7'}, + {'value': '120509', 'label': '张雷8'}, + ] + } + ] } ] - } - ]}, + }, ], }, ], @@ -300,285 +319,264 @@ class _TDCascaderPageState extends State { @Demo(group: 'cascader') Widget _buildVerticalCascader(BuildContext context) { - return GestureDetector( - onTap: () { - TDCascader.showMultiCascader(context, title: '选择地址', data: _data, initialData: _initData, theme: 'step', - onChange: (List selectData) { - setState(() { - var result = []; - var len = selectData.length; - _initData = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); + const title = '选择地址'; + return TDCell( + title: title, + note: _selected_1, + arrow: true, + onClick: (click) { + TDCascader.showMultiCascader(context, + title: title, + data: _data, + initialData: _initData, + theme: 'step', onChange: (List selectData) { + setState(() { + var result = []; + var len = selectData.length; + _initData = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); + }); + _selected_1 = result.join('/'); }); - _selected_1 = result.join('/'); + }, onClose: () { + Navigator.of(context).pop(); }); - }, onClose: () { - Navigator.of(context).pop(); }); - }, - child: _buildSelectRow(context, _selected_1, '选择地区'), - ); } @Demo(group: 'cascader') Widget _buildVerticalLetterCascader(BuildContext context) { - return GestureDetector( - onTap: () { - TDCascader.showMultiCascader(context, title: '选择地址', data: _data_2, initialData: _initData_2, theme: 'step', - onChange: (List selectData) { - setState(() { - var result = []; - var len = selectData.length; - _initData_2 = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); + const title = '选择地址'; + return TDCell( + title: title, + note: _selected_2, + arrow: true, + onClick: (click) { + TDCascader.showMultiCascader(context, + title: title, + data: _data_2, + initialData: _initData_2, + theme: 'step', onChange: (List selectData) { + setState(() { + var result = []; + var len = selectData.length; + _initData_2 = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); + }); + _selected_2 = result.join('/'); }); - _selected_2 = result.join('/'); + }, onClose: () { + Navigator.of(context).pop(); }); - }, onClose: () { - Navigator.of(context).pop(); }); - }, - child: _buildSelectRow(context, _selected_2, '选择地区'), - ); } @Demo(group: 'cascader') Widget _buildHorizontalCascader(BuildContext context) { - return GestureDetector( - onTap: () { - TDCascader.showMultiCascader(context, - title: '选择地址', - subTitles: ['请选择省份', '请选择城市', '请选择区/县'], - data: _data, - initialData: _initData, - theme: 'tab', onChange: (List selectData) { - setState(() { - var result = []; - var len = selectData.length; - _initData = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); + const title = '选择地址'; + return TDCell( + title: title, + note: _selected_1, + arrow: true, + onClick: (click) { + TDCascader.showMultiCascader(context, + title: title, + subTitles: ['请选择省份', '请选择城市', '请选择区/县'], + data: _data, + initialData: _initData, + theme: 'tab', onChange: (List selectData) { + setState(() { + var result = []; + var len = selectData.length; + _initData = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); + }); + _selected_1 = result.join('/'); }); - _selected_1 = result.join('/'); + }, onClose: () { + Navigator.of(context).pop(); }); - }, onClose: () { - Navigator.of(context).pop(); }); - }, - child: _buildSelectRow(context, _selected_1, '选择地区'), - ); } @Demo(group: 'cascader') Widget _buildHorizontalLetterCascader(BuildContext context) { - return GestureDetector( - onTap: () { - TDCascader.showMultiCascader(context, - title: '选择地址', - data: _data_2, - initialData: _initData_2, - isLetterSort: true, - theme: 'tab', onChange: (List selectData) { - setState(() { - var result = []; - var len = selectData.length; - _initData_2 = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); + const title = '选择地址'; + return TDCell( + title: title, + note: _selected_2, + arrow: true, + onClick: (click) { + TDCascader.showMultiCascader(context, + title: title, + data: _data_2, + initialData: _initData_2, + isLetterSort: true, + theme: 'tab', onChange: (List selectData) { + setState(() { + var result = []; + var len = selectData.length; + _initData_2 = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); + }); + _selected_2 = result.join('/'); }); - _selected_2 = result.join('/'); + }, onClose: () { + Navigator.of(context).pop(); }); - }, onClose: () { - Navigator.of(context).pop(); }); - }, - child: _buildSelectRow(context, _selected_2, '选择地区'), - ); } @Demo(group: 'cascader') Widget _buildHorizontalCompanyCascader(BuildContext context) { - return GestureDetector( - onTap: () { - TDCascader.showMultiCascader(context, title: '选择部门人员', data: _data_3,isLetterSort: true, initialData: _initData_3, theme: 'tab', - onChange: (List selectData) { - setState(() { - var result = []; - var len = selectData.length; - _initData_3 = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); + const title = '选择部门人员'; + return TDCell( + title: title, + note: _selected_3, + arrow: true, + onClick: (click) { + TDCascader.showMultiCascader(context, + title: title, + data: _data_3, + isLetterSort: true, + initialData: _initData_3, + theme: 'tab', onChange: (List selectData) { + setState(() { + var result = []; + var len = selectData.length; + _initData_3 = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); + }); + _selected_3 = result.join('/'); }); - _selected_3 = result.join('/'); + }, onClose: () { + Navigator.of(context).pop(); }); - }, onClose: () { - Navigator.of(context).pop(); }); - }, - child: _buildSelectRow(context, _selected_3, '选择部门人员'), - ); } @Demo(group: 'cascader') Widget _buildVerticalCompanyCascader(BuildContext context) { - return GestureDetector( - onTap: () { - TDCascader.showMultiCascader(context, title: '选择部门人员', data: _data_3,isLetterSort: true, initialData: _initData_3, theme: 'step', - onChange: (List selectData) { - setState(() { - var result = []; - var len = selectData.length; - _initData_3 = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); + const title = '选择部门人员'; + return TDCell( + title: title, + note: _selected_3, + arrow: true, + onClick: (click) { + TDCascader.showMultiCascader(context, + title: title, + data: _data_3, + isLetterSort: true, + initialData: _initData_3, + theme: 'step', onChange: (List selectData) { + setState(() { + var result = []; + var len = selectData.length; + _initData_3 = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); + }); + _selected_3 = result.join('/'); }); - _selected_3 = result.join('/'); + }, onClose: () { + Navigator.of(context).pop(); }); - }, onClose: () { - Navigator.of(context).pop(); }); - }, - child: _buildSelectRow(context, _selected_3, '选择部门人员'), - ); } @Demo(group: 'cascader') Widget _buildVerticalSubTitleCascader(BuildContext context) { - return GestureDetector( - onTap: () { - TDCascader.showMultiCascader(context, - title: '选择地址', - subTitles: ['请选择省份', '请选择城市', '请选择区/县'], - data: _data, - initialData: _initData_4, - theme: 'tab', onChange: (List selectData) { - setState(() { - var result = []; - var len = selectData.length; - _initData_4 = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); + const title = '选择地址'; + return TDCell( + title: title, + note: _selected_1, + arrow: true, + onClick: (click) { + TDCascader.showMultiCascader(context, + title: title, + subTitles: ['请选择省份', '请选择城市', '请选择区/县'], + data: _data, + initialData: _initData_4, + theme: 'tab', onChange: (List selectData) { + setState(() { + var result = []; + var len = selectData.length; + _initData_4 = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); + }); + _selected_1 = result.join('/'); }); - _selected_1 = result.join('/'); + }, onClose: () { + Navigator.of(context).pop(); }); - }, onClose: () { - Navigator.of(context).pop(); }); - }, - child: _buildSelectRow(context, _selected_1, '选择地区'), - ); } @Demo(group: 'cascader') Widget _buildTestVerticalCompanyCascader(BuildContext context) { - return GestureDetector( - onTap: () { - TDCascader.showMultiCascader(context, - title: '选择部门人员', - data: _data_4, - initialData: _initData_5, - theme: 'step', onChange: (List selectData) { - setState(() { - var result = []; - var len = selectData.length; - _initData_5 = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); - }); - _selected_4 = result.join('/'); + const title = '选择部门人员'; + return TDCell( + title: title, + note: _selected_4, + arrow: true, + onClick: (click) { + TDCascader.showMultiCascader(context, + title: title, + data: _data_4, + initialData: _initData_5, + theme: 'step', onChange: (List selectData) { + setState(() { + var result = []; + var len = selectData.length; + _initData_5 = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); }); - }, onClose: () { - Navigator.of(context).pop(); + _selected_4 = result.join('/'); }); - }, - child: _buildSelectRow(context, _selected_4, '选择部门人员'), - ); + }, onClose: () { + Navigator.of(context).pop(); + }); + }); } @Demo(group: 'cascader') Widget _buildSelectAnyItemCascader(BuildContext context) { - return GestureDetector( - onTap: () { - var action = (List selectData) { - if(selectData.isEmpty){ - TDToast.showText('请选择数据', context: context); - return; - } - setState(() { - var result = []; - var len = selectData.length; - _initData_6 = selectData[len - 1].value!; - selectData.forEach((element) { - result.add(element.label); + const title = '请选择数据'; + return TDCell( + title: title, + note: _selected_1, + arrow: true, + onClick: (click) { + var action = (List selectData) { + if (selectData.isEmpty) { + TDToast.showText(title, context: context); + return; + } + setState(() { + var result = []; + var len = selectData.length; + _initData_6 = selectData[len - 1].value!; + selectData.forEach((element) { + result.add(element.label); + }); + _selected_1 = result.join('/'); }); - _selected_1 = result.join('/'); - }); - }; - TDCascader.showMultiCascader( - context, - title: '选择地址', - data: _data, - initialData: _initData_6, - action: TDCascaderAction(onConfirm: action), - onChange: action, - ); - }, - child: _buildSelectRow(context, _selected_1, '选择地区'), - ); - } - - - Widget _buildSelectRow(BuildContext context, String output, String title) { - return Container( - color: TDTheme.of(context).whiteColor1, - height: 56, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 16, top: 16, bottom: 16), - child: TDText( - title, - font: TDTheme.of(context).fontBodyLarge, - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 16, left: 16), - child: Row( - children: [ - Expanded( - child: TDText( - output, - font: TDTheme.of(context).fontBodyLarge, - textColor: TDTheme.of(context).fontGyColor3.withOpacity(0.4), - maxLines: 1, - overflow: TextOverflow.ellipsis, - )), - Padding( - padding: const EdgeInsets.only(left: 2), - child: Icon( - TDIcons.chevron_right, - color: TDTheme.of(context).fontGyColor3.withOpacity(0.4), - ), - ), - ], - ), - )), - ], - ), - const TDDivider( - margin: EdgeInsets.only( - left: 16, - ), - ) - ], - ), - ); + }; + TDCascader.showMultiCascader( + context, + title: '选择地址', + data: _data, + initialData: _initData_6, + action: TDCascaderAction(onConfirm: action), + onChange: action, + ); + }); } } diff --git a/tdesign-component/example/lib/page/td_cell_page.dart b/tdesign-component/example/lib/page/td_cell_page.dart index 5a2d817c4..7bc947d93 100644 --- a/tdesign-component/example/lib/page/td_cell_page.dart +++ b/tdesign-component/example/lib/page/td_cell_page.dart @@ -8,53 +8,24 @@ class TDCellPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - color: TDTheme.of(context).grayColor2, - child: ExamplePage( - title: tdTitle(context), - desc: '一行内容/功能的垂直排列方式。一行项目左侧为主要内容展示区域,右侧可增加更多操作内容。', - exampleCodeGroup: 'cell', - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem( - ignoreCode: true, - desc: '单行单元格', - center: false, - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildSimple); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '多行单元格', - center: false, - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildDesSimple); - }, - ), - ]), - ExampleModule(title: '组件样式', children: [ - ExampleItem( - ignoreCode: true, - desc: '卡片单元格', - center: false, - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildCard); - }, - ), - ]), - ], - test: [ - ExampleItem( - ignoreCode: true, - desc: '自定义内边距-padding', - center: false, - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildPadding); - }, - ), - ], - )); + return ExamplePage( + title: tdTitle(context), + desc: '一行内容/功能的垂直排列方式。一行项目左侧为主要内容展示区域,右侧可增加更多操作内容。', + exampleCodeGroup: 'cell', + children: const [ + ExampleModule(title: '组件类型', children: [ + ExampleItem(desc: '单行单元格', builder: _buildSimple), + ExampleItem(desc: '多行单元格', builder: _buildDesSimple), + ]), + ExampleModule(title: '组件样式', children: [ + ExampleItem(desc: '卡片单元格', builder: _buildCard), + ]), + ], + test: const [ + ExampleItem(desc: '自定义内边距-padding', builder: _buildPadding), + ExampleItem(desc: '长标题、内容', builder: _buildTestContent), + ], + ); } } @@ -66,14 +37,42 @@ Widget _buildSimple(BuildContext context) { style: style, cells: [ // 可单独修改样式 - TDCell(arrow: true, title: '单行标题', style: TDCellStyle.cellStyle(context)), - TDCell(arrow: true, title: '单行标题', required: true, onClick: (cell) { - print('单行标题'); - }), - const TDCell(arrow: true, title: '单行标题', noteWidget: TDBadge(TDBadgeType.message, count: '8')), - const TDCell(arrow: false, title: '单行标题', rightIconWidget: TDSwitch(isOn: true)), - const TDCell(arrow: true, title: '单行标题', note: '辅助信息'), - const TDCell(arrow: true, title: '单行标题', leftIcon: TDIcons.lock_on), + TDCell( + arrow: true, + title: '单行标题', + style: TDCellStyle.cellStyle(context), + ), + TDCell( + arrow: true, + title: '单行标题', + required: true, + onClick: (cell) { + print('单行标题'); + }, + onLongPress: (cell) { + print('onLongPress 单行标题'); + }, + ), + const TDCell( + arrow: true, + title: '单行标题', + noteWidget: TDBadge(TDBadgeType.message, count: '8'), + ), + const TDCell( + arrow: false, + title: '单行标题', + rightIconWidget: TDSwitch(isOn: true), + ), + const TDCell( + arrow: true, + title: '单行标题', + note: '辅助信息', + ), + const TDCell( + arrow: true, + title: '单行标题', + leftIcon: TDIcons.lock_on, + ), const TDCell(arrow: false, title: '单行标题'), ], ); @@ -117,7 +116,7 @@ Widget _buildDesSimple(BuildContext context) { TDCell( arrow: true, title: '多行带头像', - description: '一段很长很长的内容文字', + description: '一段很长很长的内容文字一段很长很长的内容文字一段很长很长的内容', image: AssetImage('assets/img/td_avatar_1.png'), ), // NetworkImage('https://tdesign.gtimg.com/mobile/demos/avatar1.png')), @@ -163,30 +162,11 @@ Widget _buildPadding(BuildContext context) { ); } -// @Demo(group: 'cell') -// Widget _buildBorder(BuildContext context) { -// return const TDCellGroup( -// theme: TDCellGroupTheme.cardTheme, -// bordered: true, -// cells: [ -// TDCell(arrow: true, title: '单行标题'), -// TDCell(arrow: true, title: '单行标题', required: true), -// TDCell(arrow: true, title: '单行标题'), -// ], -// ); -// } - -// @Demo(group: 'cell') -// Widget _buildTitle(BuildContext context) { -// var style = TDCellStyle.cellStyle(context); -// style.leftIconColor = TDTheme.of(context).fontGyColor1; -// return TDCellGroup( -// title: '标题', -// style: style, -// cells: const [ -// TDCell(title: 'item', leftIcon: TDIcons.app), -// TDCell(title: 'item', leftIcon: TDIcons.app), -// TDCell(title: 'item', leftIcon: TDIcons.app), -// ], -// ); -// } +@Demo(group: 'cell') +Widget _buildTestContent(BuildContext context) { + return const TDCell( + title: '这是标题,非常长的标题', + note: '这是一个很长很长的note字段,测试长内容,你说这内容长不长!', + arrow: true, + ); +} diff --git a/tdesign-component/example/lib/page/td_checkbox_page.dart b/tdesign-component/example/lib/page/td_checkbox_page.dart index c88864880..eab3c5245 100644 --- a/tdesign-component/example/lib/page/td_checkbox_page.dart +++ b/tdesign-component/example/lib/page/td_checkbox_page.dart @@ -4,9 +4,7 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; -/// /// TDCheckbox演示 -/// class TDCheckboxPage extends StatefulWidget { const TDCheckboxPage({Key? key}) : super(key: key); @@ -17,8 +15,11 @@ class TDCheckboxPage extends StatefulWidget { } class TDCheckboxPageState extends State { - - List? checkIds = ['index:1','index:2','index:3',]; + List? checkIds = [ + 'index:1', + 'index:2', + 'index:3', + ]; TDCheckboxGroupController? controller; @@ -30,35 +31,35 @@ class TDCheckboxPageState extends State { @override Widget build(BuildContext context) { - return ExamplePage( - title: tdTitle(), - desc: '用于预设的一组选项中执行多项选择,并呈现选择结果。', - exampleCodeGroup: 'checkbox', - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem(desc: '纵向多选框', builder: _verticalCheckbox), - ExampleItem(desc: '横向多选框', builder: _horizontalCheckbox), - ExampleItem(desc: '带全选多选框', builder: _checkAllSelected) - ]), - ExampleModule(title: '组件状态', children: [ - ExampleItem(desc: '多选框状态', builder: _checkboxStatus), - ]), - ExampleModule(title: '组件样式', children: [ - ExampleItem(desc: '勾选样式', builder: _checkStyle), - ExampleItem(desc: '勾选显示位置', builder: _checkPosition), - ExampleItem(desc: '非通栏多选样式', builder: _passThroughStyle), - ]), - ExampleModule(title: '特殊样式', children: [ - ExampleItem(desc: '纵向卡片单选框', builder: _verticalCardStyle), - ExampleItem(desc: '横向卡片单选框', builder: _horizontalCardStyle), - ]), - ], - test: [ - ExampleItem(desc: '自定义Icon', builder: _customIconBuildStyle), - ExampleItem(desc: '自定义颜色', builder: _customColor), - ExampleItem(desc: '自定义字体尺寸', builder: _customFont), - ],); + title: tdTitle(), + desc: '用于预设的一组选项中执行多项选择,并呈现选择结果。', + exampleCodeGroup: 'checkbox', + children: [ + ExampleModule(title: '组件类型', children: [ + ExampleItem(desc: '纵向多选框', builder: _verticalCheckbox), + ExampleItem(desc: '横向多选框', builder: _horizontalCheckbox), + ExampleItem(desc: '带全选多选框', builder: _checkAllSelected) + ]), + ExampleModule(title: '组件状态', children: [ + ExampleItem(desc: '多选框状态', builder: _checkboxStatus), + ]), + ExampleModule(title: '组件样式', children: [ + ExampleItem(desc: '勾选样式', builder: _checkStyle), + ExampleItem(desc: '勾选显示位置', builder: _checkPosition), + ExampleItem(desc: '非通栏多选样式', builder: _passThroughStyle), + ]), + ExampleModule(title: '特殊样式', children: [ + ExampleItem(desc: '纵向卡片单选框', builder: _verticalCardStyle), + ExampleItem(desc: '横向卡片单选框', builder: _horizontalCardStyle), + ]), + ], + test: [ + ExampleItem(desc: '自定义Icon', builder: _customIconBuildStyle), + ExampleItem(desc: '自定义颜色', builder: _customColor), + ExampleItem(desc: '自定义字体尺寸', builder: _customFont), + ], + ); } @Demo(group: 'checkbox') @@ -135,7 +136,7 @@ class TDCheckboxPageState extends State { physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { var title = '多选'; - if(index == 0){ + if (index == 0) { title = '全选'; return SizedBox( height: 56, @@ -143,15 +144,14 @@ class TDCheckboxPageState extends State { id: 'index:$index', title: title, customIconBuilder: (context, checked) { - var length = controller!.allChecked().length - (controller!.checked('index:0') ? 1 : 0); + var length = controller!.allChecked().length - + (controller!.checked('index:0') ? 1 : 0); var allCheck = itemCount - 1 == length; var halfSelected = - controller != null - && !allCheck - && length > 0; + controller != null && !allCheck && length > 0; return getAllIcon(allCheck, halfSelected); }, - onCheckBoxChanged: (checked){ + onCheckBoxChanged: (checked) { if (checked) { controller?.toggleAll(true); } else { @@ -160,21 +160,22 @@ class TDCheckboxPageState extends State { }, ), ); - }else{ + } else { return SizedBox( height: index == itemCount - 1 ? null : 56, child: TDCheckbox( id: 'index:$index', title: title, - subTitle: index == itemCount - 1 ? '描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息' : null, + subTitle: index == itemCount - 1 + ? '描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息' + : null, subTitleMaxLine: 2, - onCheckBoxChanged: (checked){ - var length = controller!.allChecked().length - (controller!.checked('index:0') ? 1 : 0); + onCheckBoxChanged: (checked) { + var length = controller!.allChecked().length - + (controller!.checked('index:0') ? 1 : 0); var allCheck = itemCount - 1 == length; var halfSelected = - controller != null - && !allCheck - && length > 0; + controller != null && !allCheck && length > 0; controller!.toggle('index:0', allCheck); getAllIcon(allCheck, halfSelected); }, @@ -192,8 +193,8 @@ class TDCheckboxPageState extends State { return TDCheckboxGroupContainer( contentDirection: TDContentDirection.right, selectIds: const ['0'], - child: Column( - children: const [ + child: const Column( + children: [ TDCheckbox( id: '0', title: '选项禁用-已选', @@ -359,7 +360,7 @@ class TDCheckboxPageState extends State { selectIds: const ['index:1'], cardMode: true, direction: Axis.vertical, - directionalTdCheckboxes: [ + directionalTdCheckboxes: [ TDCheckbox( id: 'index:0', title: '多选', @@ -367,20 +368,24 @@ class TDCheckboxPageState extends State { titleMaxLine: 2, subTitleMaxLine: 2, cardMode: true, - customIconBuilder: (context, checked){ - return const Icon(TDIcons.app, size: 12,); + customIconBuilder: (context, checked) { + return const Icon( + TDIcons.app, + size: 12, + ); }, ), ], ); } + @Demo(group: 'checkbox') Widget _customColor(BuildContext context) { return TDCheckboxGroupContainer( contentDirection: TDContentDirection.right, selectIds: const ['0'], child: Column( - children: [ + children: [ TDCheckbox( selectColor: TDTheme.of(context).errorColor3, disableColor: TDTheme.of(context).errorColor1, @@ -396,7 +401,6 @@ class TDCheckboxPageState extends State { title: '选项禁用-默认', style: TDCheckboxStyle.circle, ), - TDCheckbox( selectColor: TDTheme.of(context).errorColor3, disableColor: TDTheme.of(context).errorColor1, @@ -407,7 +411,6 @@ class TDCheckboxPageState extends State { subTitleMaxLine: 2, cardMode: true, ), - TDCheckbox( selectColor: TDTheme.of(context).errorColor3, id: 'index:1', @@ -430,7 +433,7 @@ class TDCheckboxPageState extends State { contentDirection: TDContentDirection.right, selectIds: const ['0'], child: Column( - children: [ + children: [ TDCheckbox( id: '0', title: '选项禁用-已选', @@ -448,7 +451,6 @@ class TDCheckboxPageState extends State { titleFont: TDTheme.of(context).fontBodySmall, subTitleFont: TDTheme.of(context).fontBodyExtraSmall, ), - TDCheckbox( id: 'index:0', title: '多选', @@ -466,9 +468,14 @@ class TDCheckboxPageState extends State { Widget getAllIcon(bool checked, bool halfSelected) { return Icon( - checked ? TDIcons.check_circle_filled : halfSelected ? TDIcons.minus_circle_filled : TDIcons.circle, + checked + ? TDIcons.check_circle_filled + : halfSelected + ? TDIcons.minus_circle_filled + : TDIcons.circle, size: 24, - color: (checked || halfSelected) ? TDTheme.of(context).brandNormalColor : TDTheme.of(context).grayColor4 - ); + color: (checked || halfSelected) + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).grayColor4); } } diff --git a/tdesign-component/example/lib/page/td_collapse_page.dart b/tdesign-component/example/lib/page/td_collapse_page.dart index 7e7b5ed69..094b7b6ba 100644 --- a/tdesign-component/example/lib/page/td_collapse_page.dart +++ b/tdesign-component/example/lib/page/td_collapse_page.dart @@ -3,6 +3,7 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../annotation/demo.dart'; import '../base/example_widget.dart'; + class TDCollapsePage extends StatefulWidget { const TDCollapsePage({Key? key}) : super(key: key); diff --git a/tdesign-component/example/lib/page/td_date_picker_page.dart b/tdesign-component/example/lib/page/td_date_picker_page.dart index e17d582f5..ecb23420f 100644 --- a/tdesign-component/example/lib/page/td_date_picker_page.dart +++ b/tdesign-component/example/lib/page/td_date_picker_page.dart @@ -22,7 +22,7 @@ class _TDDatePickerPageState extends State { String selected_8 = ''; String selected_9 = ''; - var weekDayList = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']; + final weekDayList = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']; @override void initState() { @@ -52,6 +52,7 @@ class _TDDatePickerPageState extends State { children: [ ExampleItem(desc: '是否带标题', builder: buildWithTitle), ExampleItem(desc: '不带标题', builder: buildWithoutTitle), + ExampleItem(desc: '不使用弹窗、不带顶部内容', builder: buildWithoutHeader), ], ) ], @@ -67,286 +68,323 @@ class _TDDatePickerPageState extends State { @Demo(group: 'datetimePicker') Widget buildYearMonthDay(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_1 = - '${selected['year'].toString().padLeft(4, '0')}-${selected['month'].toString().padLeft(2, '0')}-${selected['day'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31], - initialDate: [2012, 1, 1]); + return TDCell( + title: '选择时间', + note: selected_1.isEmpty ? '请选择' : selected_1, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_1 = '${selected['year'].toString().padLeft(4, '0')}' + '-${selected['month'].toString().padLeft(2, '0')}' + '-${selected['day'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + initialDate: [2012, 1, 1], + ); }, - child: buildSelectRow(context, selected_1, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget buildYearMonth(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_2 = '${selected['year'].toString().padLeft(4, '0')}-' - '${selected['month'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - useDay: false, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31], - initialDate: [2012, 1, 1]); + return TDCell( + title: '选择时间', + note: selected_2.isEmpty ? '请选择' : selected_2, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_2 = '${selected['year'].toString().padLeft(4, '0')}-' + '${selected['month'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + useDay: false, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + initialDate: [2012, 1, 1], + ); }, - child: buildSelectRow(context, selected_2, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget buildMonthDay(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_3 = '${selected['month'].toString().padLeft(2, '0')}-' - '${selected['day'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - useYear: false, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31], - initialDate: [2012, 1, 1]); + return TDCell( + title: '选择时间', + note: selected_3.isEmpty ? '请选择' : selected_3, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_3 = '${selected['month'].toString().padLeft(2, '0')}-' + '${selected['day'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + useYear: false, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + initialDate: [2012, 1, 1], + ); }, - child: buildSelectRow(context, selected_3, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget buildHourMinuteSecond(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_4 = '${selected['hour'].toString().padLeft(2, '0')}:' - '${selected['minute'].toString().padLeft(2, '0')}:' - '${selected['second'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - useYear: false, - useMonth: false, - useDay: false, - useHour: true, - useMinute: true, - useSecond: true, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31, 4, 12, 20], - initialDate: [2023, 12, 31]); + return TDCell( + title: '选择时间', + note: selected_4.isEmpty ? '请选择' : selected_4, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_4 = '${selected['hour'].toString().padLeft(2, '0')}:' + '${selected['minute'].toString().padLeft(2, '0')}:' + '${selected['second'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + useYear: false, + useMonth: false, + useDay: false, + useHour: true, + useMinute: true, + useSecond: true, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31, 4, 12, 20], + initialDate: [2023, 12, 31], + ); }, - child: buildSelectRow(context, selected_4, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget buildAll(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_5 = '${selected['year'].toString().padLeft(4, '0')}-' - '${selected['month'].toString().padLeft(2, '0')}-' - '${selected['day'].toString().padLeft(2, '0')} ' - '${selected['hour'].toString().padLeft(2, '0')}:' - '${selected['minute'].toString().padLeft(2, '0')}:' - '${selected['second'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - useHour: true, - useMinute: true, - useSecond: true, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31], - initialDate: [2012, 1, 1]); + return TDCell( + title: '选择时间', + note: selected_5.isEmpty ? '请选择' : selected_5, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_5 = '${selected['year'].toString().padLeft(4, '0')}-' + '${selected['month'].toString().padLeft(2, '0')}-' + '${selected['day'].toString().padLeft(2, '0')} ' + '${selected['hour'].toString().padLeft(2, '0')}:' + '${selected['minute'].toString().padLeft(2, '0')}:' + '${selected['second'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + useHour: true, + useMinute: true, + useSecond: true, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + initialDate: [2012, 1, 1], + ); }, - child: buildSelectRow(context, selected_5, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget buildWeekDay(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_6 = '${selected['year'].toString().padLeft(4, '0')}-' - '${selected['month'].toString().padLeft(2, '0')}-' - '${selected['day'].toString().padLeft(2, '0')} ' - '${weekDayList[selected['weekDay']! - 1]}'; - }); - Navigator.of(context).pop(); - }, - useWeekDay: true, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31], - initialDate: [2012, 1, 1]); + return TDCell( + title: '选择时间', + note: selected_6.isEmpty ? '请选择' : selected_6, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_6 = '${selected['year'].toString().padLeft(4, '0')}-' + '${selected['month'].toString().padLeft(2, '0')}-' + '${selected['day'].toString().padLeft(2, '0')} ' + '${weekDayList[selected['weekDay']! - 1]}'; + }); + Navigator.of(context).pop(); + }, + useWeekDay: true, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + initialDate: [2012, 1, 1], + ); }, - child: buildSelectRow(context, selected_6, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget buildWithTitle(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_7 = '${selected['year'].toString().padLeft(4, '0')}-' - '${selected['month'].toString().padLeft(2, '0')}-' - '${selected['day'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31], - initialDate: [2012, 1, 1]); + return TDCell( + title: '选择时间', + note: selected_7.isEmpty ? '请选择' : selected_7, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_7 = '${selected['year'].toString().padLeft(4, '0')}-' + '${selected['month'].toString().padLeft(2, '0')}-' + '${selected['day'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + initialDate: [2012, 1, 1], + ); }, - child: buildSelectRow(context, selected_7, '带标题时间选择器'), ); } @Demo(group: 'datetimePicker') Widget buildWithoutTitle(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '', onConfirm: (selected) { - setState(() { - selected_8 = '${selected['year'].toString().padLeft(4, '0')}-' - '${selected['month'].toString().padLeft(2, '0')}-' - '${selected['day'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31], - initialDate: [2012, 1, 1]); + return TDCell( + title: '选择时间', + note: selected_8.isEmpty ? '请选择' : selected_8, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + // 不传或传空字符串、null,则不显示标题 + // title: '', + onConfirm: (selected) { + setState(() { + selected_8 = '${selected['year'].toString().padLeft(4, '0')}-' + '${selected['month'].toString().padLeft(2, '0')}-' + '${selected['day'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + initialDate: [2012, 1, 1], + ); }, - child: buildSelectRow(context, selected_8, '无标题时间选择器'), ); } - Widget buildSelectRow(BuildContext context, String output, String title) { - return Container( - color: TDTheme.of(context).whiteColor1, - height: 56, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 16, top: 16, bottom: 16), - child: TDText( - title, - font: TDTheme.of(context).fontBodyLarge, - ), - ), - Padding( - padding: const EdgeInsets.only(right: 16), - child: Row( - children: [ - TDText( - output, - font: TDTheme.of(context).fontBodyLarge, - textColor: - TDTheme.of(context).fontGyColor3.withOpacity(0.4), - ), - Padding( - padding: const EdgeInsets.only(left: 2), - child: Icon( - TDIcons.chevron_right, - color: - TDTheme.of(context).fontGyColor3.withOpacity(0.4), - ), - ), - ], - ), - ), - ], - ), - const TDDivider( - margin: EdgeInsets.only( - left: 16, - ), - ) - ], + @Demo(group: 'datetimePicker') + Widget buildWithoutHeader(BuildContext context) { + return TDDatePicker( + header: false, + model: DatePickerModel( + useYear: true, + useMonth: true, + useDay: true, + useHour: true, + useMinute: true, + useSecond: true, + useWeekDay: false, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + dateInitial: [2012, 1, 1], ), + onChange: (selected) { + print('onChange ${selected}'); + }, ); } @Demo(group: 'datetimePicker') Widget _customStartTime(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_5 = '${selected['year'].toString().padLeft(4, '0')}-' - '${selected['month'].toString().padLeft(2, '0')}-' - '${selected['day'].toString().padLeft(2, '0')} ' - '${selected['hour'].toString().padLeft(2, '0')}:' - '${selected['minute'].toString().padLeft(2, '0')}:' - '${selected['second'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - useYear: true, - useMonth: true, - useDay: true, - useHour: true, - useMinute: true, - useSecond: true, - dateStart: [2012, 1, 15, 12, 28, 11], - dateEnd: [2012, 6, 15, 12, 48, 32], - initialDate: [2012, 1, 15, 13, 20]); + return TDCell( + title: '选择时间', + note: selected_5.isEmpty ? '请选择' : selected_5, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_5 = '${selected['year'].toString().padLeft(4, '0')}-' + '${selected['month'].toString().padLeft(2, '0')}-' + '${selected['day'].toString().padLeft(2, '0')} ' + '${selected['hour'].toString().padLeft(2, '0')}:' + '${selected['minute'].toString().padLeft(2, '0')}:' + '${selected['second'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + useYear: true, + useMonth: true, + useDay: true, + useHour: true, + useMinute: true, + useSecond: true, + dateStart: [2012, 1, 15, 12, 28, 11], + dateEnd: [2012, 6, 15, 12, 48, 32], + initialDate: [2012, 1, 15, 13, 20], + ); }, - child: buildSelectRow(context, selected_5, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget _customLimitTime(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_4 = '${selected['hour'].toString().padLeft(2, '0')}:' - '${selected['minute'].toString().padLeft(2, '0')}:' - '${selected['second'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - useYear: false, - useMonth: false, - useDay: false, - useHour: true, - useMinute: true, - useSecond: true, - dateStart: [2023, 12, 31], - dateEnd: [2023, 12, 31, 4, 12, 20], - initialDate: [2023, 12, 31, 3, 02, 03]); + return TDCell( + title: '选择时间', + note: selected_4.isEmpty ? '请选择' : selected_4, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_4 = '${selected['hour'].toString().padLeft(2, '0')}:' + '${selected['minute'].toString().padLeft(2, '0')}:' + '${selected['second'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + useYear: false, + useMonth: false, + useDay: false, + useHour: true, + useMinute: true, + useSecond: true, + dateStart: [2023, 12, 31], + dateEnd: [2023, 12, 31, 4, 12, 20], + initialDate: [2023, 12, 31, 3, 02, 03], + ); }, - child: buildSelectRow(context, selected_4, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget _customItems(BuildContext context) { - return GestureDetector( - onTap: () { + return TDCell( + title: '选择时间', + note: selected_9.isEmpty ? '请选择' : selected_9, + arrow: true, + onClick: (click) { TDPicker.showDatePicker( context, title: '选择时间', @@ -385,7 +423,7 @@ class _TDDatePickerPageState extends State { context, distance), fontSize: index % 2 == 0 ? 20 : 10, color: index % 2 == 1 - ? TDTheme.of(context).fontGyColor1 + ? TDTheme.of(context).textColorPrimary : TDTheme.of(context).successColor6, ), ) @@ -393,14 +431,16 @@ class _TDDatePickerPageState extends State { }, ); }, - child: buildSelectRow(context, selected_9, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget _customItemsOnlyHour(BuildContext context) { - return GestureDetector( - onTap: () { + return TDCell( + title: '选择时间', + note: selected_9.isEmpty ? '请选择' : selected_9, + arrow: true, + onClick: (click) { TDPicker.showDatePicker( context, title: '只有时分', @@ -418,39 +458,45 @@ class _TDDatePickerPageState extends State { initialDate: [2025, 1, 1, 22, 46, 0], ); }, - child: buildSelectRow(context, selected_9, '选择时间'), ); } @Demo(group: 'datetimePicker') Widget _customSelectWidget(BuildContext context) { - return GestureDetector( - onTap: () { - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { - setState(() { - selected_9 = '${selected['year'].toString().padLeft(4, '0')}-' - '${selected['month'].toString().padLeft(2, '0')}-' - '${selected['day'].toString().padLeft(2, '0')} ' - '${selected['hour'].toString().padLeft(2, '0')}:' - '${selected['minute'].toString().padLeft(2, '0')}:' - '${selected['second'].toString().padLeft(2, '0')}'; - }); - Navigator.of(context).pop(); - }, - useHour: true, - useMinute: true, - useSecond: true, - dateStart: [1999, 01, 01], - dateEnd: [2023, 12, 31], - initialDate: [2012, 1, 1], - customSelectWidget: Container( - height: 40, - decoration: const BoxDecoration( - color: Colors.red, - borderRadius: BorderRadius.all(Radius.circular(6))), - )); + return TDCell( + title: '选择时间', + note: selected_9, + arrow: true, + onClick: (click) { + TDPicker.showDatePicker( + context, + title: '选择时间', + onConfirm: (selected) { + setState(() { + selected_9 = '${selected['year'].toString().padLeft(4, '0')}-' + '${selected['month'].toString().padLeft(2, '0')}-' + '${selected['day'].toString().padLeft(2, '0')} ' + '${selected['hour'].toString().padLeft(2, '0')}:' + '${selected['minute'].toString().padLeft(2, '0')}:' + '${selected['second'].toString().padLeft(2, '0')}'; + }); + Navigator.of(context).pop(); + }, + useHour: true, + useMinute: true, + useSecond: true, + dateStart: [1999, 01, 01], + dateEnd: [2023, 12, 31], + initialDate: [2012, 1, 1], + customSelectWidget: Container( + height: 40, + decoration: const BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.all(Radius.circular(6)), + ), + ), + ); }, - child: buildSelectRow(context, selected_9, '选择时间'), ); } } diff --git a/tdesign-component/example/lib/page/td_dialog_page.dart b/tdesign-component/example/lib/page/td_dialog_page.dart index 1de5a620b..fb91cb732 100644 --- a/tdesign-component/example/lib/page/td_dialog_page.dart +++ b/tdesign-component/example/lib/page/td_dialog_page.dart @@ -85,7 +85,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, content: _commonContent, @@ -106,7 +107,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( content: _commonContent, ); @@ -126,7 +128,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, ); @@ -146,7 +149,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, content: _longContent, @@ -169,7 +173,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDAlertDialog( title: _dialogTitle, content: _commonContent, @@ -190,7 +195,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDAlertDialog( content: _commonContent, ); @@ -210,7 +216,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDAlertDialog( title: _dialogTitle, ); @@ -231,7 +238,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDInputDialog( textEditingController: TextEditingController(), title: _dialogTitle, @@ -254,7 +262,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDInputDialog( textEditingController: TextEditingController(), title: _dialogTitle, @@ -277,7 +286,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDImageDialog( image: _demoImage, title: _dialogTitle, @@ -299,7 +309,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDImageDialog( image: _demoImage, content: _commonContent, @@ -320,7 +331,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDImageDialog( image: _demoImage, title: _dialogTitle, @@ -341,7 +353,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDImageDialog( image: _demoImage, title: _dialogTitle, @@ -364,7 +377,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDImageDialog( image: _demoImage, title: _dialogTitle, @@ -386,7 +400,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDImageDialog( image: _demoImage, imagePosition: TDDialogImagePosition.middle, @@ -408,7 +423,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, content: _commonContent, @@ -430,7 +446,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDAlertDialog( title: _dialogTitle, content: _commonContent, @@ -453,7 +470,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, content: _commonContent, @@ -474,7 +492,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDAlertDialog( title: _dialogTitle, content: _commonContent, @@ -496,22 +515,26 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { - return TDAlertDialog.vertical(title: _dialogTitle, content: _commonContent, buttons: [ - TDDialogButtonOptions( - title: '主要按钮', - action: () { - Navigator.pop(context); - }, - theme: TDButtonTheme.primary), - TDDialogButtonOptions( - title: '次要按钮', - titleColor: TDTheme.of(context).brandColor7, - action: () { - Navigator.pop(context); - }, - theme: TDButtonTheme.light), - ]); + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { + return TDAlertDialog.vertical( + title: _dialogTitle, + content: _commonContent, + buttons: [ + TDDialogButtonOptions( + title: '主要按钮', + action: () { + Navigator.pop(context); + }, + theme: TDButtonTheme.primary), + TDDialogButtonOptions( + title: '次要按钮', + titleColor: TDTheme.of(context).brandColor7, + action: () { + Navigator.pop(context); + }, + theme: TDButtonTheme.light), + ]); }, ); }, @@ -528,29 +551,33 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { - return TDAlertDialog.vertical(title: _dialogTitle, content: _commonContent, buttons: [ - TDDialogButtonOptions( - title: '主要按钮', - action: () { - Navigator.pop(context); - }, - theme: TDButtonTheme.primary), - TDDialogButtonOptions( - title: '次要按钮', - titleColor: TDTheme.of(context).brandColor7, - action: () { - Navigator.pop(context); - }, - theme: TDButtonTheme.light), - TDDialogButtonOptions( - title: '次要按钮', - titleColor: TDTheme.of(context).brandColor7, - action: () { - Navigator.pop(context); - }, - theme: TDButtonTheme.light), - ]); + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { + return TDAlertDialog.vertical( + title: _dialogTitle, + content: _commonContent, + buttons: [ + TDDialogButtonOptions( + title: '主要按钮', + action: () { + Navigator.pop(context); + }, + theme: TDButtonTheme.primary), + TDDialogButtonOptions( + title: '次要按钮', + titleColor: TDTheme.of(context).brandColor7, + action: () { + Navigator.pop(context); + }, + theme: TDButtonTheme.light), + TDDialogButtonOptions( + title: '次要按钮', + titleColor: TDTheme.of(context).brandColor7, + action: () { + Navigator.pop(context); + }, + theme: TDButtonTheme.light), + ]); }, ); }, @@ -567,7 +594,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, content: _commonContent, @@ -590,7 +618,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, titleAlignment: Alignment.centerLeft, @@ -615,7 +644,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDAlertDialog( title: _dialogTitle, titleAlignment: Alignment.centerRight, @@ -640,7 +670,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDAlertDialog.vertical( title: _dialogTitle, contentWidget: TDText.rich(TDTextSpan(children: [ @@ -678,7 +709,8 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { return TDImageDialog( image: _demoImage, title: _dialogTitle, @@ -706,8 +738,9 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: - (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, + Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, content: _commonContent, @@ -737,8 +770,9 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: - (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, + Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( width: 500, title: _dialogTitle, @@ -769,8 +803,9 @@ class _TDDialogPageState extends State { onTap: () { showGeneralDialog( context: context, - pageBuilder: - (BuildContext buildContext, Animation animation, Animation secondaryAnimation) { + pageBuilder: (BuildContext buildContext, + Animation animation, + Animation secondaryAnimation) { return TDConfirmDialog( title: _dialogTitle, content: _commonContent, diff --git a/tdesign-component/example/lib/page/td_divider_page.dart b/tdesign-component/example/lib/page/td_divider_page.dart index 311dc47b1..01e4dfd76 100644 --- a/tdesign-component/example/lib/page/td_divider_page.dart +++ b/tdesign-component/example/lib/page/td_divider_page.dart @@ -13,7 +13,6 @@ class TDDividerPage extends StatelessWidget { title: tdTitle(context), desc: '用于分割、组织、细化有一定逻辑的组织元素内容和页面结构。', exampleCodeGroup: 'divider', - // padding: const EdgeInsets.only(top: 16, bottom: 16), children: [ ExampleModule(title: '组件类型', children: [ ExampleItem(desc: '水平分割线', builder: _verticalDivider), @@ -28,33 +27,26 @@ class TDDividerPage extends StatelessWidget { @Demo(group: 'divider') Widget _verticalDivider(BuildContext context) { - return SizedBox( + return Container( height: 20, - child: Container( - alignment: Alignment.center, - child: const TDDivider(), - ), + alignment: Alignment.center, + child: const TDDivider(), ); } @Demo(group: 'divider') Widget _verticalTextDivider(BuildContext context) { - return Column( - children: const [ + return const Wrap( + runSpacing: 20, + children: [ TDDivider( text: '文字信息', alignment: TextAlignment.left, ), - SizedBox( - height: 20, - ), TDDivider( text: '文字信息', alignment: TextAlignment.center, ), - SizedBox( - height: 20, - ), TDDivider( text: '文字信息', alignment: TextAlignment.right, @@ -66,34 +58,30 @@ class TDDividerPage extends StatelessWidget { @Demo(group: 'divider') Widget _horizontalTextDivider(BuildContext context) { return Container( - alignment: Alignment.centerLeft, + alignment: Alignment.center, + margin: const EdgeInsets.only(left: 16), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, children: [ - const SizedBox( - width: 16, - ), TDText( '文字信息', - textColor: TDTheme.of(context).fontGyColor1.withOpacity(0.9), + textColor: TDTheme.of(context).textColorPlaceholder, ), const TDDivider( width: 0.5, height: 12, - margin: EdgeInsets.only(left: 16, right: 16), + margin: EdgeInsets.symmetric(horizontal: 8), ), - TDText('文字信息', - textColor: TDTheme.of(context).fontGyColor1.withOpacity(0.9)), + TDText('文字信息', textColor: TDTheme.of(context).textColorPlaceholder), const TDDivider( width: 0.5, height: 12, - margin: EdgeInsets.only(left: 16, right: 16), + margin: EdgeInsets.symmetric(horizontal: 8), isDashed: true, direction: Axis.vertical, ), - TDText('文字信息', - textColor: TDTheme.of(context).fontGyColor1.withOpacity(0.9)), + TDText('文字信息', textColor: TDTheme.of(context).textColorPlaceholder), ], ), ); @@ -101,33 +89,22 @@ class TDDividerPage extends StatelessWidget { @Demo(group: 'divider') Widget _dashedDivider(BuildContext context) { - return Column( - children: const [ - SizedBox( - height: 20, - ), + return const Wrap( + runSpacing: 20, + children: [ TDDivider( isDashed: true, ), - SizedBox( - height: 20, - ), TDDivider( text: '文字信息', alignment: TextAlignment.left, isDashed: true, ), - SizedBox( - height: 20, - ), TDDivider( text: '文字信息', alignment: TextAlignment.center, isDashed: true, ), - SizedBox( - height: 20, - ), TDDivider( text: '文字信息', alignment: TextAlignment.right, diff --git a/tdesign-component/example/lib/page/td_drawer_page.dart b/tdesign-component/example/lib/page/td_drawer_page.dart index bea327ba7..0e74e17d1 100644 --- a/tdesign-component/example/lib/page/td_drawer_page.dart +++ b/tdesign-component/example/lib/page/td_drawer_page.dart @@ -3,38 +3,7 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../annotation/demo.dart'; import '../base/example_widget.dart'; -const _nums = [ - '一', - '二', - '三', - '四', - '五', - '六', - '七', - '八', - '九', - '十', - '十一', - '十二', - '十三', - '十四', - '十五', - '十六', - '十七', - '十八', - '十九', - '二十', - '二一', - '二二', - '二三', - '二四', - '二五', - '二六', - '二七', - '二八', - '二九', - '三十', -]; +const drawerItemLength = 30; class TDDrawerPage extends StatelessWidget { const TDDrawerPage({super.key}); @@ -110,7 +79,8 @@ Widget _buildBaseSimple(BuildContext context) { context, visible: true, drawerTop: renderBox?.size.height, - items: List.generate(30, (index) => TDDrawerItem(title: '菜单${_nums[index]}')).toList(), + items: List.generate( + drawerItemLength, (index) => TDDrawerItem(title: '菜单${index + 1}')), onItemClick: (index, item) { print('drawer item被点击,index:$index,title:${item.title}'); }, @@ -134,7 +104,10 @@ Widget _buildIconSimple(BuildContext context) { context, visible: true, drawerTop: renderBox?.size.height, - items: List.generate(30, (index) => TDDrawerItem(title: '菜单${_nums[index]}', icon: const Icon(TDIcons.app))).toList(), + items: List.generate( + drawerItemLength, + (index) => TDDrawerItem( + title: '菜单${index + 1}', icon: const Icon(TDIcons.app))), ); }, ); @@ -157,7 +130,8 @@ Widget _buildTitleSimple(BuildContext context) { drawerTop: renderBox?.size.height, title: '标题', placement: TDDrawerPlacement.left, - items: List.generate(10, (index) => TDDrawerItem(title: '菜单${_nums[index]}')).toList(), + items: List.generate( + drawerItemLength, (index) => TDDrawerItem(title: '菜单${index + 1}')), ); }, ); @@ -180,7 +154,8 @@ Widget _buildBottomSimple(BuildContext context) { drawerTop: renderBox?.size.height, title: '标题', placement: TDDrawerPlacement.left, - items: List.generate(10, (index) => TDDrawerItem(title: '菜单${_nums[index]}')).toList(), + items: List.generate( + drawerItemLength, (index) => TDDrawerItem(title: '菜单${index + 1}')), footer: const TDButton( text: '操作', type: TDButtonType.outline, @@ -195,6 +170,10 @@ Widget _buildBottomSimple(BuildContext context) { @Demo(group: 'drawer') Widget _buildColorSimple(BuildContext context) { var renderBox = navBarkey.currentContext?.findRenderObject() as RenderBox?; + + var tdCellStyle = TDCellStyle(context: context); + tdCellStyle.backgroundColor = TDTheme.of(context).brandNormalColor; + return TDButton( text: '自定义背景色', isBlock: true, @@ -207,9 +186,11 @@ Widget _buildColorSimple(BuildContext context) { visible: true, drawerTop: renderBox?.size.height, title: '标题', - backgroundColor: TDTheme.of(context).grayColor1, + backgroundColor: TDTheme.of(context).bgColorSecondaryContainer, + style: tdCellStyle, placement: TDDrawerPlacement.right, - items: List.generate(10, (index) => TDDrawerItem(title: '菜单${_nums[index]}')).toList(), + items: List.generate( + drawerItemLength, (index) => TDDrawerItem(title: '菜单${index + 1}')), ); }, ); diff --git a/tdesign-component/example/lib/page/td_dropdown_menu_page.dart b/tdesign-component/example/lib/page/td_dropdown_menu_page.dart index fcf4782c4..bdc9a7a0b 100644 --- a/tdesign-component/example/lib/page/td_dropdown_menu_page.dart +++ b/tdesign-component/example/lib/page/td_dropdown_menu_page.dart @@ -8,84 +8,28 @@ class TDDropdownMenuPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - color: TDTheme.of(context).grayColor2, - child: ExamplePage( - title: tdTitle(context), - desc: '菜单呈现数个并列的选项类目,用于整个页面的内容筛选,由菜单面板和菜单选项组成。', - exampleCodeGroup: 'dropdownMenu', - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem( - ignoreCode: true, - desc: '单选下拉菜单', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildDownSimple); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '分栏下拉菜单', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildDownChunk); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '向上展开', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildUp); - }, - ), - ]), - ExampleModule(title: '组件状态', children: [ - ExampleItem( - ignoreCode: true, - desc: '禁用状态', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildDisabled); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '分组菜单', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildGroup); - }, - ), - ]), - ], - test: [ - ExampleItem( - ignoreCode: true, - desc: '自动弹出方向', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildHidden); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '最大高度限制', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildHeight); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '可横向滚动菜单', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildOverflow); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '可横向滚动菜单(自定义禁用、选中颜色)', - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildCustomOverflow); - }, - ), - ], - )); + return ExamplePage( + title: tdTitle(context), + desc: '菜单呈现数个并列的选项类目,用于整个页面的内容筛选,由菜单面板和菜单选项组成。', + exampleCodeGroup: 'dropdownMenu', + children: const [ + ExampleModule(title: '组件类型', children: [ + ExampleItem(desc: '单选下拉菜单', builder: _buildDownSimple), + ExampleItem(desc: '分栏下拉菜单', builder: _buildDownChunk), + ExampleItem(desc: '向上展开', builder: _buildUp), + ]), + ExampleModule(title: '组件状态', children: [ + ExampleItem(desc: '禁用状态', builder: _buildDisabled), + ExampleItem(desc: '分组菜单', builder: _buildGroup), + ]), + ], + test: const [ + ExampleItem(desc: '自动弹出方向', builder: _buildHidden), + ExampleItem(desc: '最大高度限制', builder: _buildHeight), + ExampleItem(desc: '可横向滚动菜单', builder: _buildOverflow), + ExampleItem(desc: '可横向滚动菜单(自定义禁用、选中颜色)', builder: _buildCustomOverflow), + ], + ); } } @@ -231,7 +175,8 @@ TDDropdownMenu _buildUp(BuildContext context) { ), TDDropdownItem( options: [ - TDDropdownItemOption(label: '默认排序', value: 'default', selected: true), + TDDropdownItemOption( + label: '默认排序', value: 'default', selected: true), TDDropdownItemOption(label: '价格从高到低', value: 'price'), ], ), @@ -270,7 +215,8 @@ TDDropdownMenu _buildGroup(BuildContext context) { multiple: true, optionsColumns: 3, options: [ - TDDropdownItemOption(label: '选项1', value: '1', selected: true, group: '类型'), + TDDropdownItemOption( + label: '选项1', value: '1', selected: true, group: '类型'), TDDropdownItemOption(label: '选项2', value: '2', group: '类型'), TDDropdownItemOption(label: '选项3', value: '3', group: '类型'), TDDropdownItemOption(label: '选项4', value: '4', group: '类型'), @@ -278,7 +224,8 @@ TDDropdownMenu _buildGroup(BuildContext context) { TDDropdownItemOption(label: '选项6', value: '6', group: '角色'), TDDropdownItemOption(label: '选项7', value: '7', group: '角色'), TDDropdownItemOption(label: '选项8', value: '8', group: '角色'), - TDDropdownItemOption(label: '禁用选项', value: '9', disabled: true, group: '角色'), + TDDropdownItemOption( + label: '禁用选项', value: '9', disabled: true, group: '角色'), ], onChange: (value) { print('选择:$value'); @@ -304,7 +251,8 @@ TDDropdownMenu _buildHidden(BuildContext context) { multiple: true, optionsColumns: 3, options: [ - TDDropdownItemOption(label: '选项1', value: '1', selected: true, group: '类型'), + TDDropdownItemOption( + label: '选项1', value: '1', selected: true, group: '类型'), TDDropdownItemOption(label: '选项2', value: '2', group: '类型'), TDDropdownItemOption(label: '选项3', value: '3', group: '类型'), TDDropdownItemOption(label: '选项4', value: '4', group: '类型'), @@ -312,7 +260,8 @@ TDDropdownMenu _buildHidden(BuildContext context) { TDDropdownItemOption(label: '选项6', value: '6', group: '角色'), TDDropdownItemOption(label: '选项7', value: '7', group: '角色'), TDDropdownItemOption(label: '选项8', value: '8', group: '角色'), - TDDropdownItemOption(label: '禁用选项', value: '9', disabled: true, group: '角色'), + TDDropdownItemOption( + label: '禁用选项', value: '9', disabled: true, group: '角色'), ], onChange: (value) { print('选择:$value'); @@ -397,7 +346,7 @@ TDDropdownMenu _buildOverflow(BuildContext context) { label: '最大高度限制', multiple: true, maxHeight: 200, - tabBarWidth: 200, + tabBarWidth: 150, options: [ TDDropdownItemOption(label: '选项1', value: '1', selected: true), TDDropdownItemOption(label: '选项2', value: '2', selected: true), @@ -421,7 +370,8 @@ TDDropdownMenu _buildOverflow(BuildContext context) { tabBarWidth: 200, tabBarAlign: MainAxisAlignment.start, options: [ - TDDropdownItemOption(label: '选项1选项1选项1选项1选项1选项1选项1', value: '1', selected: true), + TDDropdownItemOption( + label: '选项1选项1选项1选项1选项1选项1选项1', value: '1', selected: true), TDDropdownItemOption(label: '选项2', value: '2'), ], ), @@ -464,9 +414,15 @@ TDDropdownMenu _buildCustomOverflow(BuildContext context) { items: [ TDDropdownItem( options: [ - TDDropdownItemOption(label: '全部产品', value: 'all', selected: true, selectedColor: Colors.red), - TDDropdownItemOption(label: '最新产品', value: 'new', selectedColor: Colors.blue), - TDDropdownItemOption(label: '最火产品', value: 'hot', selectedColor: Colors.green), + TDDropdownItemOption( + label: '全部产品', + value: 'all', + selected: true, + selectedColor: Colors.red), + TDDropdownItemOption( + label: '最新产品', value: 'new', selectedColor: Colors.blue), + TDDropdownItemOption( + label: '最火产品', value: 'hot', selectedColor: Colors.green), ], onChange: (value) { print('选择:$value'); @@ -475,11 +431,15 @@ TDDropdownMenu _buildCustomOverflow(BuildContext context) { TDDropdownItem( multiple: true, options: [ - TDDropdownItemOption(label: '默认排序', value: 'default', selected: true, selectedColor: Colors.red), - TDDropdownItemOption(label: '价格从高到低', value: 'price', selectedColor: Colors.green), - + TDDropdownItemOption( + label: '默认排序', + value: 'default', + selected: true, + selectedColor: Colors.red), + TDDropdownItemOption( + label: '价格从高到低', value: 'price', selectedColor: Colors.green), ], ), ], ); -} \ No newline at end of file +} diff --git a/tdesign-component/example/lib/page/td_empty_page.dart b/tdesign-component/example/lib/page/td_empty_page.dart index bc040b2d8..7043d46e6 100644 --- a/tdesign-component/example/lib/page/td_empty_page.dart +++ b/tdesign-component/example/lib/page/td_empty_page.dart @@ -14,14 +14,19 @@ class TDEmptyPage extends StatefulWidget { class _TDEmptyPageState extends State { @override Widget build(BuildContext context) { - return ExamplePage(title: tdTitle(), exampleCodeGroup: 'empty', desc: '用于空状态时的占位提示。', children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem(desc: '图标空状态', builder: _iconEmpty), - ExampleItem(desc: '自定义图片空状态', builder: _imageEmpty), - ExampleItem(desc: '带操作空状态', builder: _operationEmpty), - ExampleItem(desc: '自定义带操作空状态', builder: _operationCustomEmpty), - ]), - ]); + return ExamplePage( + title: tdTitle(), + exampleCodeGroup: 'empty', + desc: '用于空状态时的占位提示。', + children: [ + ExampleModule(title: '组件类型', children: [ + ExampleItem(desc: '图标空状态', builder: _iconEmpty), + ExampleItem(desc: '自定义图标空状态', builder: _iconEmptyCustom), + ExampleItem(desc: '自定义图片空状态', builder: _imageEmpty), + ExampleItem(desc: '带操作空状态', builder: _operationEmpty), + ExampleItem(desc: '自定义带操作空状态', builder: _operationCustomEmpty), + ]), + ]); } @Demo(group: 'empty') @@ -32,17 +37,30 @@ class _TDEmptyPageState extends State { ); } + @Demo(group: 'empty') + Widget _iconEmptyCustom(BuildContext context) { + return const TDEmpty( + type: TDEmptyType.plain, + icon: Icons.hourglass_empty_sharp, + emptyText: '描述文字', + ); + } + @Demo(group: 'empty') Widget _imageEmpty(BuildContext context) { return TDEmpty( type: TDEmptyType.plain, emptyText: '描述文字', image: Container( - width: 120, - height: 120, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), - image: const DecorationImage(image: AssetImage('assets/img/empty.png'))), + color: TDTheme.of(context).bgColorComponent, + borderRadius: BorderRadius.circular(8), + ), + child: const TDImage( + width: 120, + assetUrl: 'assets/img/empty.png', + type: TDImageType.fitWidth, + ), ), ); } @@ -62,14 +80,15 @@ class _TDEmptyPageState extends State { type: TDEmptyType.operation, emptyText: '描述文字', customOperationWidget: Padding( - padding: const EdgeInsets.only(top: 32), - child: TDButton( - text: '自定义操作按钮', - size: TDButtonSize.medium, - theme: TDButtonTheme.danger, - width: 160, - onTap: () {}, - )), + padding: const EdgeInsets.only(top: 32), + child: TDButton( + text: '自定义操作按钮', + size: TDButtonSize.medium, + theme: TDButtonTheme.danger, + width: 160, + onTap: () {}, + ), + ), ); } } diff --git a/tdesign-component/example/lib/page/td_fab_page.dart b/tdesign-component/example/lib/page/td_fab_page.dart index 9e001cb62..878752655 100644 --- a/tdesign-component/example/lib/page/td_fab_page.dart +++ b/tdesign-component/example/lib/page/td_fab_page.dart @@ -3,6 +3,7 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../annotation/demo.dart'; import '../base/example_widget.dart'; + class TDFabPage extends StatefulWidget { const TDFabPage({Key? key}) : super(key: key); @@ -159,20 +160,16 @@ class _TDFabPageState extends State { padding: const EdgeInsets.only(right: 30), child: Column( crossAxisAlignment: CrossAxisAlignment.center, + // spacing: 24, children: [ SizedBox( height: 48, - child: Column( - children: [fab['component']], - ), - ), - const SizedBox( - height: 24, + child: Column(children: [fab['component']]), ), + const SizedBox(height: 24), TDText( fab['desc'], - style: TextStyle( - fontSize: 14, color: Colors.black.withOpacity(0.4)), + style: const TextStyle(fontSize: 14), ) ], ), diff --git a/tdesign-component/example/lib/page/td_font_page.dart b/tdesign-component/example/lib/page/td_font_page.dart index 1c796888c..ec9a478fd 100644 --- a/tdesign-component/example/lib/page/td_font_page.dart +++ b/tdesign-component/example/lib/page/td_font_page.dart @@ -10,67 +10,126 @@ class TDFontPage extends StatelessWidget { @override Widget build(BuildContext context) { - // debugPaintBaselinesEnabled = true; - return ExamplePage(padding: const EdgeInsets.all(8), title: tdTitle(context), exampleCodeGroup: 'fonts', children: [ - ExampleModule(title: 'Token', children: [ - ExampleItem( + return ExamplePage( + padding: const EdgeInsets.all(8), + title: tdTitle(context), + exampleCodeGroup: 'fonts', + children: [ + ExampleModule(title: 'Token', children: [ + ExampleItem( + ignoreCode: true, + builder: (context) { + var children = []; + TDTheme.of(context).fontMap.forEach((key, value) { + children.add(Container( + padding: const EdgeInsets.symmetric(vertical: 8), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: TDTheme.of(context).componentBorderColor, + width: 0.5), + ), + ), + child: TDText( + '@$key:${value.size.toInt()}px', + font: value, + + /// link类型的示例添加下划线 + style: TextStyle( + decoration: key.contains('Link') + ? TextDecoration.underline + : null, + decorationColor: + TDTheme.of(context).textColorPrimary), + ), + )); + }); + return ListView( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + children: children, + ); + }) + ]), + ], + test: [ + ExampleItem( + desc: '字体测试', ignoreCode: true, builder: (context) { - var children = []; - TDTheme.of(context).fontMap.forEach((key, value) { - children.add(Container( - child: TDText( - '@$key:${value.size.toInt()}px', - font: value, - - /// link类型的示例添加下划线 - style: TextStyle( - decoration: key.contains('Link') ? TextDecoration.underline : null, - decorationColor: TDTheme.of(context).fontGyColor1), + return Column( + // spacing: 16, + children: [ + TDText( + '使用主题字体:fontBodySmall', + font: TDTheme.of(context).fontBodySmall, + ), + const SizedBox(height: 16), + TDText( + '使用主题字体:fontBodyLarge', + font: TDTheme.of(context).fontBodyLarge, + ), + const SizedBox(height: 16), + TDText( + '不使用数字字体:1234567890abcd', + font: TDTheme.defaultData().fontTitleSmall, + textColor: TDTheme.of(context).brandNormalColor, + ), + const SizedBox(height: 16), + TDText( + '使用数字字体:1234567890abcd', + font: TDTheme.defaultData().fontTitleSmall, + textColor: TDTheme.of(context).brandNormalColor, + fontFamily: TDTheme.defaultData().numberFontFamily, + ) + ], + ); + }, + ), + ExampleItem( + desc: '字符测试 - 待修复', + ignoreCode: true, + builder: (context) { + return Column( + // spacing: 16, + children: [ + TDText( + '延14字号', + style: const TextStyle(fontSize: 14), + font: TDTheme.of(context).fontMarkLarge, + ), + const SizedBox(height: 16), + TDText( + '延15字号', + style: const TextStyle(fontSize: 15), + font: TDTheme.of(context).fontMarkLarge, + ), + const SizedBox(height: 16), + TDText( + '延16字号', + style: const TextStyle(fontSize: 16), + font: TDTheme.of(context).fontMarkLarge, + ), + const SizedBox(height: 16), + TDText( + '延17字号', + style: const TextStyle(fontSize: 17), + font: TDTheme.of(context).fontMarkLarge, + ), + const SizedBox(height: 16), + TDText( + '延18字号', + style: const TextStyle(fontSize: 18), + font: TDTheme.of(context).fontMarkLarge, ), - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: TDTheme.of(context).grayColor4, width: 0.5))), - )); - }); - return ListView( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - children: children, + const SizedBox(height: 16), + const Text('延-系统字体16字号', style: TextStyle(fontSize: 18)), + const SizedBox(height: 16), + const Text('延-系统字体18字号', style: TextStyle(fontSize: 18)) + ], ); - }) - ]), - ], test: [ - ExampleItem( - ignoreCode: true, - builder: (context) { - return Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: TDText('使用主题字体:fontBodySmall', font: TDTheme.of(context).fontBodySmall), - ), - Padding( - padding: const EdgeInsets.all(16), - child: TDText('使用主题字体:fontBodyLarge', font: TDTheme.of(context).fontBodyLarge), - ), - Padding( - padding: const EdgeInsets.all(16), - child: TDText( - '不使用数字字体:1234567890abcd', - font: TDTheme.defaultData().fontTitleSmall, - textColor: TDTheme.of(context).brandColor6, - )), - Padding( - padding: const EdgeInsets.all(16), - child: TDText( - '使用数字字体:1234567890abcd', - font: TDTheme.defaultData().fontTitleSmall, - textColor: TDTheme.of(context).brandColor6, - fontFamily: TDTheme.defaultData().numberFontFamily, - )), - ], - ); - }) - ]); + }, + ), + ]); } } diff --git a/tdesign-component/example/lib/page/td_footer_page.dart b/tdesign-component/example/lib/page/td_footer_page.dart index cb782993d..10502991e 100644 --- a/tdesign-component/example/lib/page/td_footer_page.dart +++ b/tdesign-component/example/lib/page/td_footer_page.dart @@ -4,19 +4,13 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; -class TDFooterPage extends StatefulWidget { +class TDFooterPage extends StatelessWidget { const TDFooterPage({Key? key}) : super(key: key); - @override - State createState() => _TDFooterPageState(); -} - -class _TDFooterPageState extends State { @override Widget build(BuildContext context) { return ExamplePage( - title: tdTitle(), - backgroundColor: TDTheme.of(context).whiteColor1, + title: tdTitle(context), desc: '用于展示App的版权声明、联系信息、重要页面链接和其他相关内容等信息。', exampleCodeGroup: 'footer', children: [ @@ -43,65 +37,55 @@ class _TDFooterPageState extends State { @Demo(group: 'footer') Widget _buildSingleLinkFooter(BuildContext context) { - // 示例链接列表 - final singleLink = [ - TDLink( - label: '底部链接', - style: TDLinkStyle.primary, - // type: TDLinkType.withSuffixIcon, - uri: Uri.parse('https://example.com'), - linkClick: (link) { - print('点击了链接 $link'); - }, - ), - ]; - return TDFooter( TDFooterType.link, - links: singleLink, + links: [ + TDLink( + label: '底部链接', + style: TDLinkStyle.primary, + type: TDLinkType.withSuffixIcon, + uri: Uri.parse('https://example.com'), + linkClick: (link) { + print('点击了链接 $link'); + }, + ), + ], text: 'Copyright © 2019-2023 TDesign.All Rights Reserved.', ); } @Demo(group: 'footer') Widget _buildLinksFooter(BuildContext context) { - final links = [ - TDLink( - label: '底部链接1', - style: TDLinkStyle.primary, - uri: Uri.parse('https://example.com'), - linkClick: (link) { - print('点击了链接1 $link'); - }, - ), - TDLink( - label: '底部链接2', - style: TDLinkStyle.primary, - uri: Uri.parse('https://example.com'), - linkClick: (link) { - print('点击了链接2 $link'); - }, - ), - ]; - return Column( - children: [ - const SizedBox(height: 12), - TDFooter( - TDFooterType.link, - links: links, - text: 'Copyright © 2019-2023 TDesign.All Rights Reserved.', - ) + return TDFooter( + TDFooterType.link, + links: [ + TDLink( + label: '底部链接1', + style: TDLinkStyle.primary, + uri: Uri.parse('https://example.com'), + linkClick: (link) { + print('点击了链接1 $link'); + }, + ), + TDLink( + label: '底部链接2', + style: TDLinkStyle.primary, + uri: Uri.parse('https://example.com'), + linkClick: (link) { + print('点击了链接2 $link'); + }, + ), ], + text: 'Copyright © 2019-2023 TDesign.All Rights Reserved.', ); } @Demo(group: 'footer') Widget _buildBrandFooter(BuildContext context) { - return TDFooter( + return const TDFooter( TDFooterType.brand, logo: 'assets/img/td_brand.png', width: 204, - height: 48, ); } } diff --git a/tdesign-component/example/lib/page/td_form_page.dart b/tdesign-component/example/lib/page/td_form_page.dart index cd2a2f11e..553e9bb23 100644 --- a/tdesign-component/example/lib/page/td_form_page.dart +++ b/tdesign-component/example/lib/page/td_form_page.dart @@ -14,9 +14,10 @@ class TDFormPage extends StatefulWidget { } class _TDFormPageState extends State { - List _controller = []; - FormController _formController = FormController(); - StreamController _stepController = StreamController.broadcast(); + final List _controller = []; + final FormController _formController = FormController(); + final StreamController _stepController = + StreamController.broadcast(); String _selected_1 = ''; String _selected_2 = ''; String? _initLocalData; @@ -48,66 +49,66 @@ class _TDFormPageState extends State { { 'label': '北京市', 'value': '110000', - "children": [ + 'children': [ { - "value": '110100', - "label": '北京市', - "children": [ - {"value": '110101', "label": '东城区'}, - {"value": '1101022', "label": '东区'}, - {"value": '110102', "label": '西城区'}, - {"value": '110105', "label": '朝阳区'}, - {"value": '110106', "label": '丰台区'}, - {"value": '110107', "label": '石景山区'}, - {"value": '110108', "label": '海淀区'}, - {"value": '110109', "label": '门头沟区'}, + 'value': '110100', + 'label': '北京市', + 'children': [ + {'value': '110101', 'label': '东城区'}, + {'value': '1101022', 'label': '东区'}, + {'value': '110102', 'label': '西城区'}, + {'value': '110105', 'label': '朝阳区'}, + {'value': '110106', 'label': '丰台区'}, + {'value': '110107', 'label': '石景山区'}, + {'value': '110108', 'label': '海淀区'}, + {'value': '110109', 'label': '门头沟区'}, ], }, ], }, { - "label": '天津市', - "value": '120000', - "children": [ + 'label': '天津市', + 'value': '120000', + 'children': [ { - "value": '120100', - "label": '天津市', - "children": [ + 'value': '120100', + 'label': '天津市', + 'children': [ { - "value": '120101', - "label": '和平区', + 'value': '120101', + 'label': '和平区', }, { - "value": '120102', - "label": '河东区', + 'value': '120102', + 'label': '河东区', }, { - "value": '120103', - "label": '河西区', + 'value': '120103', + 'label': '河西区', }, { - "value": '120104', - "label": '南开区', + 'value': '120104', + 'label': '南开区', }, { - "value": '120105', - "label": '河北区', + 'value': '120105', + 'label': '河北区', }, { - "value": '120106', - "label": '红桥区', + 'value': '120106', + 'label': '红桥区', }, { - "value": '120110', - "label": '东丽区', + 'value': '120110', + 'label': '东丽区', }, { - "value": '120111', - "label": '西青区', + 'value': '120111', + 'label': '西青区', }, { - "value": '120112', - "label": '津南区', + 'value': '120112', + 'label': '津南区', }, ], }, @@ -118,30 +119,31 @@ class _TDFormPageState extends State { ///密码是否浏览 bool browseOn = false; - TDCheckboxGroupController _genderCheckboxGroupController = TDCheckboxGroupController(); + final TDCheckboxGroupController _genderCheckboxGroupController = + TDCheckboxGroupController(); /// 整个表单存放的数据 Map _formData = { - "name": '', - "password": '', - "gender": '', - "birth": '', - "place": '', - "age": "2", - "description": "2", - "resume": '', - "photo": '', + 'name': '', + 'password': '', + 'gender': '', + 'birth': '', + 'place': '', + 'age': '2', + 'description': '2', + 'resume': '', + 'photo': '', }; - Map _formItemNotifier = { - "name": '', - "password": '', - "gender": '', - "birth": '', - "place": '', - "age": '2', - "description": '', - "resume": '', - "photo": "", + final Map _formItemNotifier = { + 'name': '', + 'password': '', + 'gender': '', + 'birth': '', + 'place': '', + 'age': '2', + 'description': '', + 'resume': '', + 'photo': '', }; @override @@ -177,27 +179,28 @@ class _TDFormPageState extends State { errorMessage: '输入不能为空', type: TDFormItemType.input, ), - "password": TDFormValidation( - validate: (value) => RegExp(r'^[a-zA-Z]{8}$').hasMatch(value ?? '') ? null : 'invalid', + 'password': TDFormValidation( + validate: (value) => + RegExp(r'^[a-zA-Z]{8}$').hasMatch(value ?? '') ? null : 'invalid', errorMessage: '只能输入8个字符英文', type: TDFormItemType.input, ), - "gender": TDFormValidation( + 'gender': TDFormValidation( validate: (value) => value == null || value.isEmpty ? 'empty' : null, errorMessage: '不能为空', type: TDFormItemType.radios, ), - "birth": TDFormValidation( + 'birth': TDFormValidation( validate: (value) => value == null || value.isEmpty ? 'empty' : null, errorMessage: '不能为空', type: TDFormItemType.dateTimePicker, ), - "place": TDFormValidation( + 'place': TDFormValidation( validate: (value) => value == null || value.isEmpty ? 'empty' : null, errorMessage: '不能为空', type: TDFormItemType.cascader, ), - "age": TDFormValidation( + 'age': TDFormValidation( validate: (value) { if (value == null || value.isEmpty) { return 'empty'; @@ -209,7 +212,7 @@ class _TDFormPageState extends State { errorMessage: '输入的数字不能大于用户所填生日对应的年龄', type: TDFormItemType.stepper, ), - "description": TDFormValidation( + 'description': TDFormValidation( validate: (value) { if (value == null || value.isEmpty) { return 'empty'; @@ -221,12 +224,12 @@ class _TDFormPageState extends State { errorMessage: '分数过低会影响整体评价', type: TDFormItemType.rate, ), - "resume": TDFormValidation( + 'resume': TDFormValidation( validate: (value) => value == null || value.isEmpty ? 'empty' : null, errorMessage: '不能为空', type: TDFormItemType.textarea, ), - "photo": TDFormValidation( + 'photo': TDFormValidation( validate: (value) => value == null || value.isEmpty ? 'empty' : null, errorMessage: '不能为空', type: TDFormItemType.upLoadImg, @@ -235,29 +238,38 @@ class _TDFormPageState extends State { ///表单提交数据 onSubmit(Map formData, isValidateSuc) {} + @override Widget build(BuildContext context) { return ExamplePage( title: tdTitle(), exampleCodeGroup: 'form', desc: '用以收集、校验和提交数据,一般由输入框、单选框、复选框、选择器等控件组成。', - backgroundColor: const Color(0xfff6f6f6), children: [ ExampleModule(title: '基础类型', children: [ - ExampleItem(ignoreCode: true,desc: '基础表单', builder: _buildArrangementSwitch), - ExampleItem(ignoreCode: true,desc: '', builder: _buildSwitchWithBase), - ExampleItem(ignoreCode: true, builder: (BuildContext context) { - return CodeWrapper(builder: _buildForm); - }), + ExampleItem( + ignoreCode: true, desc: '基础表单', builder: _buildArrangementSwitch), + ExampleItem( + ignoreCode: true, desc: '', builder: _buildSwitchWithBase), + ExampleItem( + ignoreCode: true, + builder: (BuildContext context) { + return CodeWrapper(builder: _buildForm); + }), // ExampleItem(ignoreCode: true, desc: '', builder: (_) => CodeWrapper(builder: _buildCombinationButtons)), ]), ], test: [ - ExampleItem(ignoreCode: true,desc: '自定义背景表单', builder: _buildArrangementSwitch), - ExampleItem(ignoreCode: true,desc: '', builder: _buildSwitchWithBase), - ExampleItem(ignoreCode: true, builder: (BuildContext context) { - return CodeWrapper(builder: _buildCustomForm); - }), + ExampleItem( + ignoreCode: true, + desc: '自定义背景表单', + builder: _buildArrangementSwitch), + ExampleItem(ignoreCode: true, desc: '', builder: _buildSwitchWithBase), + ExampleItem( + ignoreCode: true, + builder: (BuildContext context) { + return CodeWrapper(builder: _buildCustomForm); + }), ], ); } @@ -292,12 +304,13 @@ class _TDFormPageState extends State { child: TDInput( leftContentSpace: 0, inputDecoration: InputDecoration( - hintText: "请输入用户名", - border: InputBorder.none, - contentPadding: EdgeInsets.all(0), - hintStyle: TextStyle(color: TDTheme.of(context).fontGyColor3.withOpacity(0.4))), + hintText: '请输入用户名', + border: InputBorder.none, + hintStyle: TextStyle( + color: TDTheme.of(context).textColorPlaceholder, + ), + ), controller: _controller[0], - backgroundColor: Colors.white, additionInfoColor: TDTheme.of(context).errorColor6, showBottomDivider: false, readOnly: _formDisableState, @@ -306,7 +319,7 @@ class _TDFormPageState extends State { }, onClearTap: () { _controller[0].clear(); - _formItemNotifier['name']?.upDataForm(""); + _formItemNotifier['name']?.upDataForm(''); }), ), TDFormItem( @@ -319,13 +332,15 @@ class _TDFormPageState extends State { child: TDInput( leftContentSpace: 0, inputDecoration: InputDecoration( - hintText: '请输入密码', - border: InputBorder.none, - hintStyle: TextStyle(color: TDTheme.of(context).fontGyColor3.withOpacity(0.4))), + hintText: '请输入密码', + border: InputBorder.none, + hintStyle: TextStyle( + color: TDTheme.of(context).textColorPlaceholder, + ), + ), type: TDInputType.normal, controller: _controller[1], obscureText: !browseOn, - backgroundColor: Colors.white, needClear: false, readOnly: _formDisableState, showBottomDivider: false, @@ -334,7 +349,7 @@ class _TDFormPageState extends State { }, onClearTap: () { _controller[1].clear(); - _formItemNotifier['password']?.upDataForm(""); + _formItemNotifier['password']?.upDataForm(''); }), ), TDFormItem( @@ -376,20 +391,24 @@ class _TDFormPageState extends State { contentAlign: TextAlign.left, tipAlign: TextAlign.left, formItemNotifier: _formItemNotifier['birth'], - hintText:'请输入内容', + hintText: '请输入内容', select: _selected_1, selectFn: (BuildContext context) { if (_formDisableState) { return; } - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { + TDPicker.showDatePicker(context, title: '选择时间', + onConfirm: (selected) { setState(() { _selected_1 = '${selected['year'].toString().padLeft(4, '0')}-${selected['month'].toString().padLeft(2, '0')}-${selected['day'].toString().padLeft(2, '0')}'; _formItemNotifier['birth']?.upDataForm(_selected_1); }); Navigator.of(context).pop(); - }, dateStart: [1999, 01, 01], dateEnd: [2050, 12, 31], initialDate: [2012, 1, 1]); + }, + dateStart: [1999, 01, 01], + dateEnd: [2050, 12, 31], + initialDate: [2012, 1, 1]); }, ), TDFormItem( @@ -399,7 +418,7 @@ class _TDFormPageState extends State { contentAlign: TextAlign.left, tipAlign: TextAlign.left, labelWidth: 82.0, - hintText:'请输入内容', + hintText: '请输入内容', select: _selected_2, formItemNotifier: _formItemNotifier['place'], selectFn: (BuildContext context) { @@ -410,7 +429,8 @@ class _TDFormPageState extends State { title: '选择地址', data: _data, initialData: _initLocalData, - theme: 'step', onChange: (List selectData) { + theme: 'step', + onChange: (List selectData) { setState(() { var result = []; var len = selectData.length; @@ -433,12 +453,12 @@ class _TDFormPageState extends State { type: TDFormItemType.stepper, formItemNotifier: _formItemNotifier['age'], child: Padding( - padding: EdgeInsets.only( right: 18), + padding: const EdgeInsets.only(right: 18), child: TDStepper( theme: TDStepperTheme.filled, disabled: _formDisableState, eventController: _stepController!, - value:int.parse(_formData['age']), + value: int.parse(_formData['age']), onChange: (value) { _formItemNotifier['age']?.upDataForm('${value}'); }, @@ -454,7 +474,7 @@ class _TDFormPageState extends State { child: Align( alignment: Alignment.centerLeft, child: Padding( - padding: EdgeInsets.only(right: 18), + padding: const EdgeInsets.only(right: 18), child: TDRate( count: 5, value: double.parse(_formData['description']), @@ -476,10 +496,10 @@ class _TDFormPageState extends State { type: TDFormItemType.textarea, formItemNotifier: _formItemNotifier['resume'], child: Padding( - padding: EdgeInsets.only(top: _isFormHorizontal?0:8,bottom: 4), + padding: + EdgeInsets.only(top: _isFormHorizontal ? 0 : 8, bottom: 4), child: TDTextarea( backgroundColor: Colors.red, - padding: EdgeInsets.all(0), hintText: '请输入个人简介', maxLength: 500, indicator: true, @@ -499,7 +519,7 @@ class _TDFormPageState extends State { type: TDFormItemType.upLoadImg, formItemNotifier: _formItemNotifier['photo'], child: Padding( - padding: EdgeInsets.only(top:4,bottom: 4), + padding: EdgeInsets.only(top: 4, bottom: 4), child: TDUpload( files: files, multiple: true, @@ -512,7 +532,8 @@ class _TDFormPageState extends State { return; } files = _onValueChanged(files ?? [], imgList, type); - List imgs = files.map((e) => e.remotePath ?? e.assetPath).toList(); + List imgs = + files.map((e) => e.remotePath ?? e.assetPath).toList(); setState(() { _formItemNotifier['photo'].upDataForm(imgs.join(',')); }); @@ -521,72 +542,67 @@ class _TDFormPageState extends State { )) ], btnGroup: [ - Container( - decoration: BoxDecoration( - color: theme.whiteColor1, - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Expanded( - child: TDButton( - text: '重置', - size: TDButtonSize.large, - type: TDButtonType.fill, - theme: TDButtonTheme.light, - shape: TDButtonShape.rectangle, - disabled: _formDisableState, - onTap: () { - //用户名称 - _controller[0].clear(); - //密码 - _controller[1].clear(); - // 性别 - _genderCheckboxGroupController.toggle('', false); - //个人简介 - _controller[2].clear(); - //生日 - _selected_1 = ''; - //籍贯 - _selected_2 = ''; - //年限 - _stepController.add(TDStepperEventType.cleanValue); - //上传图片 - files.clear(); - _formData = { - "name": '', - "password": '', - "gender": '', - "birth": '', - "place": '', - "age": "0", - "description": "2", - "resume": '', - "photo": '' - }; - _formData.forEach((key, value) { - _formItemNotifier[key].upDataForm(value); - }); - _formController.reset(_formData); - setState(() {}); - }, - )), - SizedBox( - width: 20, - ), - Expanded( - child: TDButton( - text: '提交', - size: TDButtonSize.large, - type: TDButtonType.fill, - theme: TDButtonTheme.primary, - shape: TDButtonShape.rectangle, - onTap: _onSubmit, - disabled: _formDisableState)), - ], - )), - ) + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Expanded( + child: TDButton( + text: '重置', + size: TDButtonSize.large, + type: TDButtonType.fill, + theme: TDButtonTheme.light, + shape: TDButtonShape.rectangle, + disabled: _formDisableState, + onTap: () { + //用户名称 + _controller[0].clear(); + //密码 + _controller[1].clear(); + // 性别 + _genderCheckboxGroupController.toggle('', false); + //个人简介 + _controller[2].clear(); + //生日 + _selected_1 = ''; + //籍贯 + _selected_2 = ''; + //年限 + _stepController.add(TDStepperEventType.cleanValue); + //上传图片 + files.clear(); + _formData = { + 'name': '', + 'password': '', + 'gender': '', + 'birth': '', + 'place': '', + 'age': '0', + 'description': '2', + 'resume': '', + 'photo': '' + }; + _formData.forEach((key, value) { + _formItemNotifier[key].upDataForm(value); + }); + _formController.reset(_formData); + setState(() {}); + }, + )), + const SizedBox( + width: 20, + ), + Expanded( + child: TDButton( + text: '提交', + size: TDButtonSize.large, + type: TDButtonType.fill, + theme: TDButtonTheme.primary, + shape: TDButtonShape.rectangle, + onTap: _onSubmit, + disabled: _formDisableState)), + ], + )) ]); } @@ -621,10 +637,12 @@ class _TDFormPageState extends State { child: TDInput( leftContentSpace: 0, inputDecoration: InputDecoration( - hintText: "请输入用户名", + hintText: '请输入用户名', border: InputBorder.none, - contentPadding: EdgeInsets.all(0), - hintStyle: TextStyle(color: TDTheme.of(context).fontGyColor3.withOpacity(0.4))), + contentPadding: const EdgeInsets.all(0), + hintStyle: TextStyle( + color: + TDTheme.of(context).fontGyColor3.withOpacity(0.4))), controller: _controller[0], backgroundColor: TDTheme.of(context).brandNormalColor, additionInfoColor: TDTheme.of(context).errorColor6, @@ -635,7 +653,7 @@ class _TDFormPageState extends State { }, onClearTap: () { _controller[0].clear(); - _formItemNotifier['name']?.upDataForm(""); + _formItemNotifier['name']?.upDataForm(''); }), ), TDFormItem( @@ -651,7 +669,9 @@ class _TDFormPageState extends State { inputDecoration: InputDecoration( hintText: '请输入密码', border: InputBorder.none, - hintStyle: TextStyle(color: TDTheme.of(context).fontGyColor3.withOpacity(0.4))), + hintStyle: TextStyle( + color: + TDTheme.of(context).fontGyColor3.withOpacity(0.4))), type: TDInputType.normal, controller: _controller[1], obscureText: !browseOn, @@ -664,7 +684,7 @@ class _TDFormPageState extends State { }, onClearTap: () { _controller[1].clear(); - _formItemNotifier['password']?.upDataForm(""); + _formItemNotifier['password']?.upDataForm(''); }), ), TDFormItem( @@ -689,7 +709,7 @@ class _TDFormPageState extends State { showDivider: false, spacing: 4, checkBoxLeftSpace: 0, - customSpace: EdgeInsets.all(0), + customSpace: const EdgeInsets.all(0), enable: !_formDisableState, ); }).toList(), @@ -710,20 +730,24 @@ class _TDFormPageState extends State { contentAlign: TextAlign.left, tipAlign: TextAlign.left, formItemNotifier: _formItemNotifier['birth'], - hintText:'请输入内容', + hintText: '请输入内容', select: _selected_1, selectFn: (BuildContext context) { if (_formDisableState) { return; } - TDPicker.showDatePicker(context, title: '选择时间', onConfirm: (selected) { + TDPicker.showDatePicker(context, title: '选择时间', + onConfirm: (selected) { setState(() { _selected_1 = - '${selected['year'].toString().padLeft(4, '0')}-${selected['month'].toString().padLeft(2, '0')}-${selected['day'].toString().padLeft(2, '0')}'; + '${selected['year'].toString().padLeft(4, '0')}-${selected['month'].toString().padLeft(2, '0')}-${selected['day'].toString().padLeft(2, '0')}'; _formItemNotifier['birth']?.upDataForm(_selected_1); }); Navigator.of(context).pop(); - }, dateStart: [1999, 01, 01], dateEnd: [2050, 12, 31], initialDate: [2012, 1, 1]); + }, + dateStart: [1999, 01, 01], + dateEnd: [2050, 12, 31], + initialDate: [2012, 1, 1]); }, ), TDFormItem( @@ -734,12 +758,12 @@ class _TDFormPageState extends State { type: TDFormItemType.stepper, formItemNotifier: _formItemNotifier['age'], child: Padding( - padding: EdgeInsets.only( right: 18), + padding: const EdgeInsets.only(right: 18), child: TDStepper( theme: TDStepperTheme.filled, disabled: _formDisableState, eventController: _stepController!, - value:int.parse(_formData['age']), + value: int.parse(_formData['age']), onChange: (value) { _formItemNotifier['age']?.upDataForm('${value}'); }, @@ -756,7 +780,7 @@ class _TDFormPageState extends State { child: Align( alignment: Alignment.centerLeft, child: Padding( - padding: EdgeInsets.only(right: 18), + padding: const EdgeInsets.only(right: 18), child: TDRate( count: 5, value: double.parse(_formData['description']), @@ -779,10 +803,11 @@ class _TDFormPageState extends State { backgroundColor: TDTheme.of(context).brandNormalColor, formItemNotifier: _formItemNotifier['resume'], child: Padding( - padding: EdgeInsets.only(top: _isFormHorizontal?0:8,bottom: 4), + padding: + EdgeInsets.only(top: _isFormHorizontal ? 0 : 8, bottom: 4), child: TDTextarea( backgroundColor: Colors.red, - padding: EdgeInsets.all(0), + padding: const EdgeInsets.all(0), hintText: '请输入个人简介', maxLength: 500, indicator: true, @@ -803,7 +828,7 @@ class _TDFormPageState extends State { type: TDFormItemType.upLoadImg, formItemNotifier: _formItemNotifier['photo'], child: Padding( - padding: EdgeInsets.only(top:4,bottom: 4), + padding: const EdgeInsets.only(top: 4, bottom: 4), child: TDUpload( files: files, multiple: true, @@ -816,7 +841,8 @@ class _TDFormPageState extends State { return; } files = _onValueChanged(files ?? [], imgList, type); - List imgs = files.map((e) => e.remotePath ?? e.assetPath).toList(); + List imgs = + files.map((e) => e.remotePath ?? e.assetPath).toList(); setState(() { _formItemNotifier['photo'].upDataForm(imgs.join(',')); }); @@ -827,7 +853,8 @@ class _TDFormPageState extends State { btnGroup: null); } - List _onValueChanged(List fileList, List value, TDUploadType event) { + List _onValueChanged(List fileList, + List value, TDUploadType event) { switch (event) { case TDUploadType.add: fileList.addAll(value); @@ -837,7 +864,8 @@ class _TDFormPageState extends State { break; case TDUploadType.replace: final firstReplaceFile = value.first; - final index = fileList.indexWhere((file) => file.key == firstReplaceFile.key); + final index = + fileList.indexWhere((file) => file.key == firstReplaceFile.key); if (index != -1) { fileList[index] = firstReplaceFile; } @@ -846,91 +874,88 @@ class _TDFormPageState extends State { return fileList; } + /// todo /// 横 竖 排版模式切换按钮 Widget _buildArrangementSwitch(BuildContext buildContext) { final theme = TDTheme.of(context); - return Container( - decoration: BoxDecoration( - color: theme.whiteColor1, - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Expanded( - child: TDButton( - text: '水平排布', - shape: TDButtonShape.round, - style: TDButtonStyle(backgroundColor: horizontalButtonColor), - textStyle: TextStyle( - fontWeight: FontWeight.w700, - color: horizontalTextColor, - ), - onTap: () { - setState(() { - if (horizontalButton) { - /// 置换按钮状态 - horizontalButton = false; - verticalButton = true; - - /// 置换按钮颜色 - final currentVerticalColor = verticalButtonColor; - verticalButtonColor = horizontalButtonColor; - horizontalButtonColor = currentVerticalColor; - - /// 置换文字颜色 - final currentTextColor = verticalTextColor; - verticalTextColor = horizontalTextColor; - horizontalTextColor = currentTextColor; - _isFormHorizontal = true; - print(_isFormHorizontal); - } - }); - }, - ), + return Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Expanded( + child: TDButton( + text: '水平排布', + shape: TDButtonShape.round, + style: TDButtonStyle(backgroundColor: horizontalButtonColor), + textStyle: TextStyle( + fontWeight: FontWeight.w700, + color: horizontalTextColor, ), - const SizedBox(width: 8), - Expanded( - child: TDButton( - text: '竖直排布', - shape: TDButtonShape.round, - style: TDButtonStyle(backgroundColor: verticalButtonColor), - textStyle: TextStyle( - fontWeight: FontWeight.w700, - color: verticalTextColor, - ), - onTap: () { - setState(() { - if (verticalButton) { - /// 置换按钮状态 - horizontalButton = true; - verticalButton = false; - - /// 置换按钮颜色 - final currentVerticalColor = verticalButtonColor; - verticalButtonColor = horizontalButtonColor; - horizontalButtonColor = currentVerticalColor; - - /// 置换文字颜色 - final currentTextColor = verticalTextColor; - verticalTextColor = horizontalTextColor; - horizontalTextColor = currentTextColor; - - _isFormHorizontal = false; - print(_isFormHorizontal); - } - }); - }, - ), + onTap: () { + setState(() { + if (horizontalButton) { + /// 置换按钮状态 + horizontalButton = false; + verticalButton = true; + + /// 置换按钮颜色 + final currentVerticalColor = verticalButtonColor; + verticalButtonColor = horizontalButtonColor; + horizontalButtonColor = currentVerticalColor; + + /// 置换文字颜色 + final currentTextColor = verticalTextColor; + verticalTextColor = horizontalTextColor; + horizontalTextColor = currentTextColor; + _isFormHorizontal = true; + print(_isFormHorizontal); + } + }); + }, + ), + ), + const SizedBox(width: 8), + Expanded( + child: TDButton( + text: '竖直排布', + shape: TDButtonShape.round, + style: TDButtonStyle(backgroundColor: verticalButtonColor), + textStyle: TextStyle( + fontWeight: FontWeight.w700, + color: verticalTextColor, ), - ], - ))); + onTap: () { + setState(() { + if (verticalButton) { + /// 置换按钮状态 + horizontalButton = true; + verticalButton = false; + + /// 置换按钮颜色 + final currentVerticalColor = verticalButtonColor; + verticalButtonColor = horizontalButtonColor; + horizontalButtonColor = currentVerticalColor; + + /// 置换文字颜色 + final currentTextColor = verticalTextColor; + verticalTextColor = horizontalTextColor; + horizontalTextColor = currentTextColor; + + _isFormHorizontal = false; + print(_isFormHorizontal); + } + }); + }, + ), + ), + ], + )); } Widget _buildSwitchWithBase(BuildContext context) { - return _buildItem( - context, - TDSwitch( + return TDCell( + title: '禁用态', + rightIconWidget: TDSwitch( isOn: _formDisableState, onChanged: (value) { setState(() { @@ -939,40 +964,6 @@ class _TDFormPageState extends State { return false; }, ), - title: '禁用态', - ); - } - - @Demo(group: 'switch') - Widget _buildItem(BuildContext context, Widget switchItem, {String? title, String? desc}) { - final theme = TDTheme.of(context); - Widget current = Row( - children: [ - Expanded( - child: TDText( - title ?? '', - textColor: theme.fontGyColor1, - )), - TDText( - desc ?? '', - textColor: theme.grayColor6, - ), - SizedBox(child: switchItem) - ], - ); - current = Padding( - padding: const EdgeInsets.symmetric(vertical: 1), - child: SizedBox( - child: Container( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: current, - ), - color: Colors.white, - ), - height: 56, - ), ); - return Column(mainAxisSize: MainAxisSize.min, children: [current]); } } diff --git a/tdesign-component/example/lib/page/td_icon_page.dart b/tdesign-component/example/lib/page/td_icon_page.dart index dc92ecd77..a1e45ef3c 100644 --- a/tdesign-component/example/lib/page/td_icon_page.dart +++ b/tdesign-component/example/lib/page/td_icon_page.dart @@ -14,7 +14,7 @@ class TDIconPage extends StatefulWidget { class _TDIconPageState extends State { bool showBorder = false; - dynamic iconList = []; + Iterable iconList = []; var isLoading = false; @@ -33,24 +33,31 @@ class _TDIconPageState extends State { exampleCodeGroup: 'icon', children: [ ExampleModule( - title: 'icon示例', children: [ExampleItem(desc: 'icon数量: ${iconList.length}', builder: _showAllIcons)]) + title: 'icon示例', + children: [ + ExampleItem( + desc: 'icon数量: ${iconList.length}', + builder: _showAllIcons, + ) + ], + ) ]); } @Demo(group: 'icon') Widget _showAllIcons(BuildContext context) { return Container( - color: Colors.white, alignment: Alignment.center, child: Column( children: [ Container( - padding: const EdgeInsets.only(left: 16), + padding: const EdgeInsets.all(16), alignment: Alignment.topLeft, child: const Wrap( children: [ TDText('筛选Icon请前往TDesign官网(长按网址可复制):'), - SelectableText('https://tdesign.tencent.com/vue/components/icon') + SelectableText( + 'https://tdesign.tencent.com/vue/components/icon') ], ), ), @@ -80,71 +87,57 @@ class _TDIconPageState extends State { }); }, ), - Container( - child: TDButton( - text: showBorder ? '隐藏边框' : '显示边框', - shape: TDButtonShape.filled, - onTap: () { + TDCell( + title: '显示边框', + noteWidget: TDSwitch( + isOn: showBorder, + onChanged: (value) { setState(() { - showBorder = !showBorder; + showBorder = value; }); + return value; }, ), - margin: const EdgeInsets.only(bottom: 16), ), Builder(builder: (context) { if (iconList.isEmpty) { return Container( height: 300, alignment: Alignment.center, - child: isLoading ? const TDText('加载中...') : const TDText('暂无内容'), + child: + isLoading ? const TDText('加载中...') : const TDText('暂无内容'), ); } + + var width = MediaQuery.of(context).size.width * 0.4; + return SizedBox( - height: MediaQuery.of(context).size.height - 150, - child: ListView.builder( - itemCount: (iconList.length + 1) ~/ 2, - itemBuilder: (context,index){ - var index1 = index ~/ 2; - var index2 = index1 + 1; - var iconData1 = iconList.elementAt(index1); - var iconData2; - if(iconList.length > index2){ - iconData2 = iconList.elementAt(index2); - } - return Row( - children: [ - SizedBox( - height: 100, - width: 175, + height: MediaQuery.of(context).size.height * 0.7, + child: SingleChildScrollView( + child: Wrap( + spacing: 16, + runSpacing: 18, + children: iconList.map((item) { + return SizedBox( + width: width, child: Column( + mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - color: showBorder ? TDTheme.of(context).brandDisabledColor : Colors.transparent, - child: Icon(iconData1), + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: showBorder + ? TDTheme.of(context).brandDisabledColor + : Colors.transparent, + ), + child: Icon(item, size: 32), ), - TDText(iconData1.name) + TDText(item.name) ], ), - ), - if (iconData2 != null) - SizedBox( - height: 100, - width: 175, - child: Column( - children: [ - Container( - color: showBorder ? TDTheme.of(context).brandDisabledColor : Colors.transparent, - child: Icon(iconData2), - ), - TDText(iconData2.name) - ], - ), - ) - ], - ); - }), - ); + ); + }).toList()), + )); }) ], ), diff --git a/tdesign-component/example/lib/page/td_image_page.dart b/tdesign-component/example/lib/page/td_image_page.dart index fd08b1afe..eedf45cbb 100644 --- a/tdesign-component/example/lib/page/td_image_page.dart +++ b/tdesign-component/example/lib/page/td_image_page.dart @@ -1,10 +1,10 @@ -import 'package:flutter/material.dart'; +import 'dart:io'; +import 'package:flutter/material.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; -import 'dart:io'; class TDImagePage extends StatefulWidget { const TDImagePage({Key? key}) : super(key: key); @@ -17,6 +17,7 @@ class TDImageState extends State with SingleTickerProviderStateMixin { late Animation animation; late AnimationController animationController; + @override void initState() { super.initState(); @@ -216,7 +217,6 @@ class TDImageState extends State child: TDText( '裁剪', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), const TDImage( @@ -226,6 +226,7 @@ class TDImageState extends State ], ); } + /* 图片拉伸 */ @Demo(group: 'image') Widget _imageStretch(BuildContext context) { @@ -237,14 +238,13 @@ class TDImageState extends State child: TDText( '拉伸', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), Container( - color: Colors.black, + color: TDTheme.of(context).bgColorContainerHover, width: 121, height: 72, - child: Stack( + child: const Stack( alignment: Alignment.center, children: [ TDImage( @@ -259,6 +259,7 @@ class TDImageState extends State ], ); } + /* 图片适应高 */ @Demo(group: 'image') Widget _imageFitHeight(BuildContext context) { @@ -270,13 +271,12 @@ class TDImageState extends State child: TDText( '适应高', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), Container( width: 89, height: 72, - color: Colors.black, + color: TDTheme.of(context).bgColorContainerHover, child: const TDImage( assetUrl: 'assets/img/image.png', type: TDImageType.fitHeight, @@ -285,6 +285,7 @@ class TDImageState extends State ], ); } + /* 图片适应宽 */ @Demo(group: 'image') Widget _imageFitWidth(BuildContext context) { @@ -296,13 +297,12 @@ class TDImageState extends State child: TDText( '适应宽', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), Container( width: 72, height: 89, - color: Colors.black, + color: TDTheme.of(context).bgColorContainerHover, child: const TDImage( assetUrl: 'assets/img/image.png', type: TDImageType.fitWidth, @@ -311,6 +311,7 @@ class TDImageState extends State ], ); } + /* 方形 */ @Demo(group: 'image') Widget _imageSquare(BuildContext context) { @@ -322,7 +323,6 @@ class TDImageState extends State child: TDText( '方形', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), const TDImage( @@ -332,6 +332,7 @@ class TDImageState extends State ], ); } + /* 圆角方形 */ @Demo(group: 'image') Widget _imageRoundedSquare(BuildContext context) { @@ -343,7 +344,6 @@ class TDImageState extends State child: TDText( '圆角方形', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), const TDImage( @@ -355,6 +355,7 @@ class TDImageState extends State ], ); } + /* 圆形 */ @Demo(group: 'image') Widget _imageCircle(BuildContext context) { @@ -366,7 +367,6 @@ class TDImageState extends State child: TDText( '圆形', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), const TDImage( @@ -378,18 +378,18 @@ class TDImageState extends State ], ); } + /* 加载默认提示 */ @Demo(group: 'image') Widget _loadingDefault(BuildContext context) { return Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(bottom: 16), child: TDText( '加载默认提示', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), Container( @@ -401,13 +401,14 @@ class TDImageState extends State BorderRadius.circular(TDTheme.of(context).radiusDefault)), child: Container( alignment: Alignment.center, - color: TDTheme.of(context).grayColor2, + color: TDTheme.of(context).bgColorContainerHover, child: Icon( TDIcons.ellipsis, size: 22, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ))), - // 实际组件写法如下:上面仅为加载展示 + + /// @tips 实际组件写法如下:上面仅为加载展示 // const TDImage( // imgUrl: // 'https://images.pexels.com/photos/842711/pexels-photo-842711.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2', @@ -416,18 +417,18 @@ class TDImageState extends State ], ); } + /* 加载自定义提示 */ @Demo(group: 'image') Widget _loadingCustom(BuildContext context) { return Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(bottom: 16), child: TDText( '加载自定义提示', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), Container( @@ -439,7 +440,7 @@ class TDImageState extends State BorderRadius.circular(TDTheme.of(context).radiusDefault)), child: Container( alignment: Alignment.center, - color: TDTheme.of(context).grayColor2, + color: TDTheme.of(context).bgColorContainerHover, child: RotationTransition( turns: animation, alignment: Alignment.center, @@ -465,18 +466,18 @@ class TDImageState extends State ], ); } + /* 失败默认提示 */ @Demo(group: 'image') Widget _failDefault(BuildContext context) { return Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(bottom: 16), child: TDText( '失败默认提示', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), const TDImage( @@ -486,18 +487,18 @@ class TDImageState extends State ], ); } + /* 失败自定义提示 */ @Demo(group: 'image') Widget _failCustom(BuildContext context) { return Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(bottom: 16), child: TDText( '失败自定义提示', font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor2.withOpacity(0.6), ), ), TDImage( @@ -506,8 +507,6 @@ class TDImageState extends State '加载失败', forceVerticalCenter: true, font: TDTheme.of(context).fontBodyExtraSmall, - fontWeight: FontWeight.w500, - textColor: TDTheme.of(context).fontGyColor3, ), type: TDImageType.roundedSquare, ), @@ -517,7 +516,7 @@ class TDImageState extends State @Demo(group: 'image') Widget _imageFile(BuildContext context) { - return Container( + return SizedBox( width: 72, height: 72, child: TDImage( diff --git a/tdesign-component/example/lib/page/td_image_viewer_page.dart b/tdesign-component/example/lib/page/td_image_viewer_page.dart index 11ccea9c8..bc324b389 100644 --- a/tdesign-component/example/lib/page/td_image_viewer_page.dart +++ b/tdesign-component/example/lib/page/td_image_viewer_page.dart @@ -4,6 +4,16 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../annotation/demo.dart'; import '../base/example_widget.dart'; +final List actionSheetItems = [ + TDActionSheetItem(label: '保存图片', icon: const Icon(TDIcons.save)), + TDActionSheetItem(label: '删除图片', icon: const Icon(TDIcons.delete)), +]; + +final List images = [ + 'https://tdesign.gtimg.com/mobile/demos/swiper1.png', + 'https://tdesign.gtimg.com/mobile/demos/swiper2.png', +]; + class TDImageViewerPage extends StatefulWidget { const TDImageViewerPage({Key? key}) : super(key: key); @@ -15,7 +25,6 @@ class _TDImageViewerPageState extends State { @override Widget build(BuildContext context) { return ExamplePage( - backgroundColor: const Color(0xFFF0F2F5), title: tdTitle(), desc: '用于图片内容的缩略展示与查看。', exampleCodeGroup: 'image_viewer', @@ -34,11 +43,6 @@ class _TDImageViewerPageState extends State { ); } - var images = [ - 'https://tdesign.gtimg.com/mobile/demos/swiper1.png', - 'https://tdesign.gtimg.com/mobile/demos/swiper2.png', - ]; - @Demo(group: 'image_viewer') Widget _basicImageViewer(BuildContext context) { return TDButton( @@ -55,10 +59,6 @@ class _TDImageViewerPageState extends State { @Demo(group: 'image_viewer') Widget _actionImageViewer(BuildContext context) { - var delImages = [ - 'https://tdesign.gtimg.com/mobile/demos/swiper1.png', - 'https://tdesign.gtimg.com/mobile/demos/swiper2.png', - ]; return TDButton( type: TDButtonType.ghost, theme: TDButtonTheme.primary, @@ -68,7 +68,7 @@ class _TDImageViewerPageState extends State { onTap: () { TDImageViewer.showImageViewer( context: context, - images: delImages, + images: images, showIndex: true, deleteBtn: true, ); @@ -91,10 +91,11 @@ class _TDImageViewerPageState extends State { deleteBtn: true, showIndex: true, onLongPress: (index) { - Navigator.of(context).push(TDSlidePopupRoute( - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: _getSheetItem, - )); + TDActionSheet( + context, + visible: true, + items: actionSheetItems, + ); }, ); }, @@ -116,10 +117,11 @@ class _TDImageViewerPageState extends State { showIndex: true, height: 140, onLongPress: (index) { - Navigator.of(context).push(TDSlidePopupRoute( - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: _getSheetItem, - )); + TDActionSheet( + context, + visible: true, + items: actionSheetItems, + ); }, ); }, @@ -141,10 +143,11 @@ class _TDImageViewerPageState extends State { showIndex: true, width: 180, onLongPress: (index) { - Navigator.of(context).push(TDSlidePopupRoute( - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: _getSheetItem, - )); + TDActionSheet( + context, + visible: true, + items: actionSheetItems, + ); }, ); }, @@ -153,11 +156,6 @@ class _TDImageViewerPageState extends State { @Demo(group: 'image_viewer') Widget _descImageViewer(BuildContext context) { - var delImages = [ - 'https://tdesign.gtimg.com/mobile/demos/swiper1.png', - 'https://tdesign.gtimg.com/mobile/demos/swiper2.png', - ]; - var labels = ['图片标题1', '图片标题2']; return TDButton( type: TDButtonType.ghost, theme: TDButtonTheme.primary, @@ -167,42 +165,10 @@ class _TDImageViewerPageState extends State { onTap: () { TDImageViewer.showImageViewer( context: context, - images: delImages, - labels: labels, + images: images, + labels: ['图片标题1', '图片标题2'], ); }, ); } - - Widget _getSheetItem(BuildContext context) { - return Container( - width: double.infinity, - height: 120, - color: Colors.white, - child: Column( - children: [ - const SizedBox(height: 16), - Text( - '保存图片', - style: TextStyle( - color: TDTheme.of(context).fontGyColor1, - decoration: TextDecoration.none, - fontSize: 14, - fontWeight: FontWeight.w400, - ), - ), - const TDDivider(margin: EdgeInsets.symmetric(vertical: 10),), - Text( - '删除图片', - style: TextStyle( - color: TDTheme.of(context).fontGyColor1, - decoration: TextDecoration.none, - fontSize: 14, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ); - } } diff --git a/tdesign-component/example/lib/page/td_indexes_page.dart b/tdesign-component/example/lib/page/td_indexes_page.dart index a91741d40..aa2510b26 100644 --- a/tdesign-component/example/lib/page/td_indexes_page.dart +++ b/tdesign-component/example/lib/page/td_indexes_page.dart @@ -83,7 +83,19 @@ const _list = [ }, { 'index': 'J', - 'children': ['揭阳', '吉林', '晋江', '吉安', '胶州', '嘉兴', '济南', '鸡西', '荆州', '江门', '基隆'], + 'children': [ + '揭阳', + '吉林', + '晋江', + '吉安', + '胶州', + '嘉兴', + '济南', + '鸡西', + '荆州', + '江门', + '基隆' + ], }, { 'index': 'K', @@ -150,21 +162,20 @@ Widget _buildSimple(BuildContext context) { slideTransitionFrom: SlideTransitionFrom.right, modalTop: renderBox?.size.height, builder: (context) { - return Container( - color: Colors.white, - child: TDIndexes( - indexList: indexList, - builderContent: (context, index) { - final list = _list.firstWhere((element) => element['index'] == index)['children'] as List; - return TDCellGroup( - cells: list - .map((e) => TDCell( - title: e, - )) - .toList(), - ); - }, - ), + return TDIndexes( + indexList: indexList, + builderContent: (context, index) { + final list = _list.firstWhere( + (element) => element['index'] == index)['children'] + as List; + return TDCellGroup( + cells: list + .map((e) => TDCell( + title: e, + )) + .toList(), + ); + }, ); }, ), @@ -189,22 +200,21 @@ Widget _buildOther(BuildContext context) { slideTransitionFrom: SlideTransitionFrom.right, modalTop: renderBox?.size.height, builder: (context) { - return Container( - color: Colors.white, - child: TDIndexes( - indexList: indexList, - capsuleTheme: true, - builderContent: (context, index) { - final list = _list.firstWhere((element) => element['index'] == index)['children'] as List; - return TDCellGroup( - cells: list - .map((e) => TDCell( - title: e, - )) - .toList(), - ); - }, - ), + return TDIndexes( + indexList: indexList, + capsuleTheme: true, + builderContent: (context, index) { + final list = _list.firstWhere( + (element) => element['index'] == index)['children'] + as List; + return TDCellGroup( + cells: list + .map((e) => TDCell( + title: e, + )) + .toList(), + ); + }, ); }, ), @@ -229,28 +239,32 @@ Widget _buildCustomIndexes(BuildContext context) { slideTransitionFrom: SlideTransitionFrom.right, modalTop: renderBox?.size.height, builder: (context) { - return Container( - color: Colors.white, - child: TDIndexes( - indexList: indexList, - builderIndex: (context, index, isActive) { - return Text('自定义 ${index}', style: TextStyle(color: isActive ? Colors.red : Colors.black),); - }, - builderContent: (context, index) { - final list = _list.firstWhere((element) => element['index'] == index)['children'] as List; - return TDCellGroup( - cells: list - .map((e) => TDCell( - title: e, - )) - .toList(), - ); - }, - ), + return TDIndexes( + indexList: indexList, + builderIndex: (context, index, isActive) { + return TDText( + '自定义 ${index}', + textColor: isActive + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).textColorPrimary, + ); + }, + builderContent: (context, index) { + final list = _list.firstWhere( + (element) => element['index'] == index)['children'] + as List; + return TDCellGroup( + cells: list + .map((e) => TDCell( + title: e, + )) + .toList(), + ); + }, ); }, ), ); }, ); -} \ No newline at end of file +} diff --git a/tdesign-component/example/lib/page/td_input_page.dart b/tdesign-component/example/lib/page/td_input_page.dart index 9088f7a14..97377804b 100644 --- a/tdesign-component/example/lib/page/td_input_page.dart +++ b/tdesign-component/example/lib/page/td_input_page.dart @@ -1,9 +1,10 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; -import 'dart:async'; class TDInputViewPage extends StatefulWidget { const TDInputViewPage({Key? key}) : super(key: key); @@ -53,9 +54,8 @@ class _TDInputViewPageState extends State { @override Widget build(BuildContext context) { - var childBuilder = (context){ + var childBuilder = (context) { return ExamplePage( - backgroundColor: const Color(0xFFF0F2F5), title: tdTitle(), desc: '用于在预设的一组选项中执行单项选择,并呈现选择结果。', exampleCodeGroup: 'input', @@ -73,7 +73,8 @@ class _TDInputViewPageState extends State { ExampleItem(desc: '带操作输入框', builder: _basicTypeWithHandleIconOne), ExampleItem(builder: _basicTypeWithHandleIconTwo), ExampleItem(builder: _basicTypeWithHandleIconThree), - ExampleItem(desc: '带图标输入框', builder: _basicTypeWithLeftIconLeftLabel), + ExampleItem( + desc: '带图标输入框', builder: _basicTypeWithLeftIconLeftLabel), ExampleItem(builder: _basicTypeWithLeftIcon), ExampleItem(desc: '特定类型输入框', builder: _specialTypePassword), ExampleItem(builder: _specialTypeVerifyCode), @@ -105,18 +106,22 @@ class _TDInputViewPageState extends State { ExampleItem(desc: '长文本样式', builder: _customLongTextStyle), ExampleItem(desc: '隐藏底部分割线', builder: _hideBottomDivider), ExampleItem(desc: '自定义高度-使用SizeBox', builder: _customHeight), - ExampleItem(desc: '获取焦点时点击外部区域事件响应-onTapOutside', builder: _onTapOutside), - ExampleItem(desc: '设置contentPadding内容与分割线对齐', builder: _contentPadding) + ExampleItem( + desc: '获取焦点时点击外部区域事件响应-onTapOutside', builder: _onTapOutside), + ExampleItem( + desc: '设置contentPadding内容与分割线对齐', builder: _contentPadding) ], ); }; - if(PlatformUtil.isWeb){ - return FutureBuilder(future: awaitFontLoad(), builder: (context, s){ - if(s.data == null){ - return Container(); - } - return childBuilder.call(context); - }); + if (PlatformUtil.isWeb) { + return FutureBuilder( + future: awaitFontLoad(), + builder: (context, s) { + if (s.data == null) { + return Container(); + } + return childBuilder.call(context); + }); } return childBuilder.call(context); } @@ -128,7 +133,6 @@ class _TDInputViewPageState extends State { TDInput( leftLabel: 'Label Text', controller: controller[0], - backgroundColor: Colors.white, hintText: 'Please enter text', onChanged: (text) { setState(() {}); @@ -153,7 +157,6 @@ class _TDInputViewPageState extends State { leftLabel: '标签文字', required: true, controller: controller[1], - backgroundColor: Colors.white, hintText: '请输入文字', onChanged: (text) { setState(() {}); @@ -177,7 +180,6 @@ class _TDInputViewPageState extends State { TDInput( leftLabel: '标签文字', controller: controller[2], - backgroundColor: Colors.white, hintText: '请输入文字(选填)', onChanged: (text) { setState(() {}); @@ -200,7 +202,6 @@ class _TDInputViewPageState extends State { children: [ TDInput( controller: controller[3], - backgroundColor: Colors.white, hintText: '请输入文字', onChanged: (text) { setState(() {}); @@ -225,7 +226,6 @@ class _TDInputViewPageState extends State { controller: controller[4], hintText: '请输入文字', additionInfo: '辅助说明', - backgroundColor: Colors.white, onChanged: (text) { setState(() {}); }, @@ -247,7 +247,6 @@ class _TDInputViewPageState extends State { hintText: '请输入文字', maxLength: 10, additionInfo: '最大输入10个字符', - backgroundColor: Colors.white, onChanged: (text) { setState(() {}); }, @@ -272,7 +271,6 @@ class _TDInputViewPageState extends State { hintText: '请输入文字', inputFormatters: [Chinese2Formatter(10)], additionInfo: '最大输入10个字符,汉字算两个', - backgroundColor: Colors.white, onChanged: (text) { setState(() {}); }, @@ -290,11 +288,10 @@ class _TDInputViewPageState extends State { TDInput( leftLabel: '标签文字', controller: controller[7], - backgroundColor: Colors.white, hintText: '请输入文字', rightBtn: Icon( TDIcons.error_circle_filled, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ), onBtnTap: () { TDToast.showText('点击右侧按钮', context: context); @@ -321,7 +318,6 @@ class _TDInputViewPageState extends State { TDInput( leftLabel: '标签文字', controller: controller[8], - backgroundColor: Colors.white, hintText: '请输入文字', rightBtn: Container( alignment: Alignment.center, @@ -354,11 +350,10 @@ class _TDInputViewPageState extends State { return TDInput( leftLabel: '标签文字', controller: controller[9], - backgroundColor: Colors.white, hintText: '请输入文字', rightBtn: Icon( TDIcons.user_avatar, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ), onBtnTap: () { TDToast.showText('点击操作按钮', context: context); @@ -381,7 +376,6 @@ class _TDInputViewPageState extends State { leftIcon: const Icon(TDIcons.app), leftLabel: '标签文字', controller: controller[10], - backgroundColor: Colors.white, hintText: '请输入文字', onChanged: (text) { setState(() {}); @@ -405,7 +399,6 @@ class _TDInputViewPageState extends State { TDInput( leftIcon: const Icon(TDIcons.app), controller: controller[11], - backgroundColor: Colors.white, hintText: '请输入文字', onChanged: (text) { setState(() {}); @@ -432,15 +425,14 @@ class _TDInputViewPageState extends State { obscureText: !browseOn, leftLabel: '输入密码', hintText: '请输入密码', - backgroundColor: Colors.white, rightBtn: browseOn ? Icon( TDIcons.browse, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ) : Icon( TDIcons.browse_off, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ), onBtnTap: () { setState(() { @@ -466,14 +458,13 @@ class _TDInputViewPageState extends State { controller: controller[13], leftLabel: '验证码', hintText: '输入验证码', - backgroundColor: Colors.white, rightBtn: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 0.5, height: 24, - color: TDTheme.of(context).grayColor3, + color: TDTheme.of(context).componentBorderColor, ), const SizedBox( width: 16, @@ -506,7 +497,6 @@ class _TDInputViewPageState extends State { controller: controller[14], leftLabel: '手机号', hintText: '输入手机号', - backgroundColor: Colors.white, rightBtn: SizedBox( width: 98, child: Row( @@ -517,15 +507,16 @@ class _TDInputViewPageState extends State { child: Container( width: 0.5, height: 24, - color: TDTheme.of(context).grayColor3, + color: TDTheme.of(context).componentBorderColor, ), ), _countdownTime > 0 ? TDText( '${countDownText}(${_countdownTime}秒)', - textColor: TDTheme.of(context).fontGyColor4, + textColor: TDTheme.of(context).textColorDisabled, ) - : TDText(confirmText, textColor: TDTheme.of(context).brandNormalColor), + : TDText(confirmText, + textColor: TDTheme.of(context).brandNormalColor), ], ), ), @@ -556,9 +547,9 @@ class _TDInputViewPageState extends State { controller: controller[15], leftLabel: '价格', hintText: '0.00', - backgroundColor: Colors.white, textAlign: TextAlign.end, - rightWidget: TDText('元', textColor: TDTheme.of(context).fontGyColor1), + rightWidget: + TDText('元', textColor: TDTheme.of(context).textColorPrimary), ), const SizedBox( height: 16, @@ -574,9 +565,8 @@ class _TDInputViewPageState extends State { controller: controller[16], leftLabel: '数量', hintText: '填写个数', - backgroundColor: Colors.white, textAlign: TextAlign.end, - rightWidget: TDText('个', textColor: TDTheme.of(context).fontGyColor1), + rightWidget: TDText('个', textColor: TDTheme.of(context).textColorPrimary), ); } @@ -587,7 +577,6 @@ class _TDInputViewPageState extends State { TDInput( leftLabel: '标签文字', controller: controller[17], - backgroundColor: Colors.white, hintText: '请输入文字', additionInfo: '错误提示说明', additionInfoColor: TDTheme.of(context).errorColor6, @@ -612,7 +601,6 @@ class _TDInputViewPageState extends State { leftLabel: '标签文字', readOnly: true, // 不可编辑文字 则不必带入controller - backgroundColor: Colors.white, hintText: '不可编辑文字', ); } @@ -626,7 +614,6 @@ class _TDInputViewPageState extends State { spacer: TDInputSpacer(iconLabelSpace: 4), leftLabel: '标签超长时最多十个字', controller: controller[18], - backgroundColor: Colors.white, hintText: '请输入文字', onChanged: (text) { setState(() {}); @@ -649,10 +636,9 @@ class _TDInputViewPageState extends State { type: TDInputType.normal, leftLabel: '标签文字', controller: controller[19], - backgroundColor: Colors.white, hintText: '输入文字超长不超过两行输入文字超长不超过两行', hintTextStyle: TextStyle( - color: TDTheme.of(context).fontGyColor1, + color: TDTheme.of(context).textColorPrimary, ), maxLines: 2, ); @@ -666,10 +652,9 @@ class _TDInputViewPageState extends State { leftLabel: '标签文字', controller: controller[20], hintText: '请输入文字', - backgroundColor: Colors.white, rightBtn: Icon( TDIcons.error_circle_filled, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ), onBtnTap: () { TDToast.showText('点击右侧按钮', context: context); @@ -692,7 +677,6 @@ class _TDInputViewPageState extends State { leftLabel: '标签文字', controller: controller[21], hintText: '请输入文字', - backgroundColor: Colors.white, onChanged: (text) { setState(() {}); }, @@ -709,7 +693,6 @@ class _TDInputViewPageState extends State { alignment: Alignment.center, padding: const EdgeInsets.only(top: 16, bottom: 24), width: MediaQuery.of(context).size.width, - color: Colors.white, child: TDInput( type: TDInputType.cardStyle, cardStyle: TDCardStyle.topText, @@ -719,7 +702,7 @@ class _TDInputViewPageState extends State { hintText: '请输入文字', rightBtn: Icon( TDIcons.error_circle_filled, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ), onBtnTap: () { TDToast.showText('点击右侧按钮', context: context); @@ -742,7 +725,6 @@ class _TDInputViewPageState extends State { TDInput( leftLabel: '左对齐', controller: controller[23], - backgroundColor: Colors.white, hintText: '请输入文字', onChanged: (text) { setState(() {}); @@ -766,7 +748,6 @@ class _TDInputViewPageState extends State { TDInput( leftLabel: '居中', controller: controller[24], - backgroundColor: Colors.white, contentAlignment: TextAlign.center, hintText: '请输入文字', onChanged: (text) { @@ -791,7 +772,6 @@ class _TDInputViewPageState extends State { TDInput( leftLabel: '右对齐', controller: controller[25], - backgroundColor: Colors.white, contentAlignment: TextAlign.end, hintText: '请输入文字', onChanged: (text) { @@ -837,22 +817,20 @@ class _TDInputViewPageState extends State { alignment: Alignment.center, padding: const EdgeInsets.only(top: 16, bottom: 24), width: MediaQuery.of(context).size.width, - color: Colors.white, child: TDInput( - type: TDInputType.longText, - cardStyle: TDCardStyle.topText, - width: MediaQuery.of(context).size.width - 32, - cardStyleTopText: '标签文字', - controller: controller, - hintText: '请输入文字', - rightBtn: Icon( - TDIcons.error_circle_filled, - color: TDTheme.of(context).fontGyColor3, - ), - onBtnTap: () { - TDToast.showText('点击右侧按钮', context: context); - } - ), + type: TDInputType.longText, + cardStyle: TDCardStyle.topText, + width: MediaQuery.of(context).size.width - 32, + cardStyleTopText: '标签文字', + controller: controller, + hintText: '请输入文字', + rightBtn: Icon( + TDIcons.error_circle_filled, + color: TDTheme.of(context).textColorPlaceholder, + ), + onBtnTap: () { + TDToast.showText('点击右侧按钮', context: context); + }), ); } @@ -862,7 +840,6 @@ class _TDInputViewPageState extends State { return TDInput( leftLabel: '标签文字', controller: controller, - backgroundColor: Colors.white, hintText: '请输入文字', showBottomDivider: false, ); @@ -881,7 +858,6 @@ class _TDInputViewPageState extends State { size: TDInputSize.small, leftLabel: '标签文字', controller: controller, - backgroundColor: Colors.white, hintText: '请输入文字', needClear: true, ), @@ -902,7 +878,6 @@ class _TDInputViewPageState extends State { size: TDInputSize.small, leftLabel: '标签文字', controller: controller, - backgroundColor: Colors.white, hintText: '请输入文字', onTapOutside: (event) { TDToast.showText('点击输入框外部区域', context: context); @@ -924,24 +899,24 @@ class _TDInputViewPageState extends State { TDInput( size: TDInputSize.small, controller: controller, - backgroundColor: Colors.white, - contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10), + contentPadding: + const EdgeInsets.symmetric(vertical: 10, horizontal: 10), hintText: '请输入文字', ), TDInput( type: TDInputType.twoLine, size: TDInputSize.small, controller: controller, - backgroundColor: Colors.white, - contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 50), + contentPadding: + const EdgeInsets.symmetric(vertical: 10, horizontal: 50), hintText: '请输入文字', ), TDInput( type: TDInputType.normalMaxTwoLine, size: TDInputSize.small, controller: controller, - backgroundColor: Colors.white, - contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 70), + contentPadding: + const EdgeInsets.symmetric(vertical: 10, horizontal: 70), hintText: '请输入文字', ), ], diff --git a/tdesign-component/example/lib/page/td_link_page.dart b/tdesign-component/example/lib/page/td_link_page.dart index d918fe81e..571ead356 100644 --- a/tdesign-component/example/lib/page/td_link_page.dart +++ b/tdesign-component/example/lib/page/td_link_page.dart @@ -15,9 +15,8 @@ class _TDLinkViewPageState extends State { @override Widget build(BuildContext context) { return ExamplePage( - backgroundColor: const Color(0xFFF0F2F5), title: tdTitle(), - desc: '当功能使用图标即可表意清楚时,可使用纯图标悬浮按钮,例如:添加、发布。', + desc: '文字超链接用于跳转一个新页面,如当前项目跳转,友情链接等。', exampleCodeGroup: 'link', children: [ ExampleModule(title: '组件类型', children: [ @@ -39,9 +38,10 @@ class _TDLinkViewPageState extends State { @Demo(group: 'link') Widget _basicTypeBasic(BuildContext context) { return Container( - color: TDTheme.of(context).whiteColor1, + height: 48, + color: TDTheme.of(context).bgColorContainer, child: Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: _buildLinksWithType(TDLinkType.basic), )); } @@ -54,28 +54,22 @@ class _TDLinkViewPageState extends State { type: type, size: TDLinkSize.small, ), - const SizedBox( - height: 48, - width: 80, - ), TDLink( label: '跳转链接', style: TDLinkStyle.defaultStyle, type: type, size: TDLinkSize.small, ), - const SizedBox( - height: 16, - ), ]; } @Demo(group: 'link') Widget _withUnderline(BuildContext context) { return Container( - color: TDTheme.of(context).whiteColor1, + height: 48, + color: TDTheme.of(context).bgColorContainer, child: Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: _buildLinksWithType(TDLinkType.withUnderline), )); } @@ -83,9 +77,10 @@ class _TDLinkViewPageState extends State { @Demo(group: 'link') Widget _withSuffixIcon(BuildContext context) { return Container( - color: TDTheme.of(context).whiteColor1, + height: 48, + color: TDTheme.of(context).bgColorContainer, child: Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: _buildLinksWithType(TDLinkType.withSuffixIcon), )); } @@ -93,9 +88,10 @@ class _TDLinkViewPageState extends State { @Demo(group: 'link') Widget _withPrefixIcon(BuildContext context) { return Container( - color: TDTheme.of(context).whiteColor1, + height: 48, + color: TDTheme.of(context).bgColorContainer, child: Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: _buildLinksWithType(TDLinkType.withPrefixIcon), )); } @@ -112,30 +108,32 @@ class _TDLinkViewPageState extends State { Column _buildLinkWithStyles(TDLinkState state) { return Column( + // spacing: 16, children: [ Container( - color: TDTheme.of(context).whiteColor1, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _buildLinkWithTypeAndState(TDLinkStyle.primary, state), - const SizedBox(height: 48, width: 50), - _buildLinkWithTypeAndState(TDLinkStyle.defaultStyle, state), - const SizedBox(height: 48, width: 50), - _buildLinkWithTypeAndState(TDLinkStyle.danger, state), - ], - )), + height: 48, + color: TDTheme.of(context).bgColorContainer, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildLinkWithTypeAndState(TDLinkStyle.primary, state), + _buildLinkWithTypeAndState(TDLinkStyle.defaultStyle, state), + _buildLinkWithTypeAndState(TDLinkStyle.danger, state), + ], + ), + ), const SizedBox(height: 16), Container( - color: TDTheme.of(context).whiteColor1, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _buildLinkWithTypeAndState(TDLinkStyle.warning, state), - const SizedBox(height: 48, width: 50), - _buildLinkWithTypeAndState(TDLinkStyle.success, state), - ], - )), + height: 48, + color: TDTheme.of(context).bgColorContainer, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildLinkWithTypeAndState(TDLinkStyle.warning, state), + _buildLinkWithTypeAndState(TDLinkStyle.success, state), + ], + ), + ), ], ); } @@ -153,14 +151,13 @@ class _TDLinkViewPageState extends State { @Demo(group: 'link') Widget _buildLinkSizes(BuildContext context) { return Container( - color: TDTheme.of(context).whiteColor1, + height: 48, + color: TDTheme.of(context).bgColorContainer, child: Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildLinkWithSizeAndStyle(TDLinkStyle.primary, TDLinkSize.small), - const SizedBox(height: 48, width: 40), _buildLinkWithSizeAndStyle(TDLinkStyle.primary, TDLinkSize.medium), - const SizedBox(height: 48, width: 40), _buildLinkWithSizeAndStyle(TDLinkStyle.primary, TDLinkSize.large), ], )); diff --git a/tdesign-component/example/lib/page/td_loading_page.dart b/tdesign-component/example/lib/page/td_loading_page.dart index f13013582..4ae269fc8 100644 --- a/tdesign-component/example/lib/page/td_loading_page.dart +++ b/tdesign-component/example/lib/page/td_loading_page.dart @@ -18,21 +18,17 @@ class TDLoadingPage extends StatefulWidget { } class _TDLoadingPageState extends State { - var rowSpace = const SizedBox( - width: 52, - ); - @override Widget build(BuildContext context) { return ExamplePage( title: tdTitle(), - backgroundColor: TDTheme.of(context).whiteColor1, exampleCodeGroup: 'loading', desc: '用于表示页面或操作的加载状态,给予用户反馈的同时减缓等待的焦虑感,由一个或一组反馈动效组成。', children: [ ExampleModule(title: '组件类型', children: [ ExampleItem(desc: '纯图标', builder: _buildPureIconLoading), - ExampleItem(desc: '图标加文字横向', builder: _buildTextIconHorizontalLoading), + ExampleItem( + desc: '图标加文字横向', builder: _buildTextIconHorizontalLoading), ExampleItem(desc: '图标加文字竖向', builder: _buildTextIconVerticalLoading), ExampleItem(desc: '纯文字', builder: _buildPureTextLoading), ]), @@ -97,193 +93,194 @@ class _TDLoadingPageState extends State { desc: '验证居中问题', ignoreCode: true, builder: (_) { - var list = const [ - TDLoading( - size: TDLoadingSize.large, - icon: TDLoadingIcon.circle, - text: '加载中…', - axis: Axis.vertical, - ), - TDLoading( - size: TDLoadingSize.large, - icon: TDLoadingIcon.activity, - text: '加载中…', - axis: Axis.vertical, - ), - ]; - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - children: list.fold( - [], - (previousValue, element) => [ - ...previousValue, - Container( - color: TDTheme.of(context).grayColor6, - child: element, - ), - rowSpace - ]))); + return const Row( + // spacing: 36, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TDLoading( + size: TDLoadingSize.large, + icon: TDLoadingIcon.circle, + text: '加载中…', + axis: Axis.vertical, + ), + SizedBox(width: 36), + TDLoading( + size: TDLoadingSize.large, + icon: TDLoadingIcon.activity, + text: '加载中…', + axis: Axis.vertical, + ), + ]); }), ExampleItem( desc: '展示/隐藏Loading', ignoreCode: true, builder: (_) { - var list = [ - TDButton( - text: '展示Loading', - theme: TDButtonTheme.primary, - onTap: () { - TDLoadingController.show(context); - }, - ), - const SizedBox(width: 24,), - const TDButton( - text: '隐藏Loading', - theme: TDButtonTheme.primary, - onTap: TDLoadingController.dismiss, - ), - ]; - return Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: Row(children: list, )); + return Row( + // spacing: 36, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TDButton( + text: '展示Loading', + theme: TDButtonTheme.primary, + onTap: () { + TDLoadingController.show(context); + }, + ), + const SizedBox(width: 36), + const TDButton( + text: '隐藏Loading', + theme: TDButtonTheme.primary, + onTap: TDLoadingController.dismiss, + ), + ], + ); }) ], ); } - @Demo(group: 'loading') - Widget _buildRow(List list) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row(children: list.fold([], (previousValue, element) => [...previousValue, element, rowSpace])),)); - } - /// 纯图标 @Demo(group: 'loading') Widget _buildPureIconLoading(BuildContext context) { - return _buildRow([ - const TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.circle, - ), - const TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.activity, - ), - TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.point, - iconColor: TDTheme.of(context).brandNormalColor, - ), - ]); + return Row( + // spacing: 36, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.circle, + ), + const SizedBox(width: 36), + const TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.activity, + ), + const SizedBox(width: 36), + TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.point, + iconColor: TDTheme.of(context).brandNormalColor, + ), + ], + ); } /// 图标加文字横向 @Demo(group: 'loading') Widget _buildTextIconHorizontalLoading(BuildContext context) { - return _buildRow(const [ - TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.circle, - text: '加载中…', - axis: Axis.horizontal, - ), - TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.activity, - text: '加载中…', - axis: Axis.horizontal, - ), - ]); + return const Row( + // spacing: 36, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.circle, + text: '加载中…', + axis: Axis.horizontal, + ), + const SizedBox(width: 36), + TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.activity, + text: '加载中…', + axis: Axis.horizontal, + ), + ], + ); } /// 图标加文字竖向 @Demo(group: 'loading') Widget _buildTextIconVerticalLoading(BuildContext context) { - return _buildRow(const [ - TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.circle, - text: '加载中…', - axis: Axis.vertical, - ), - TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.activity, - text: '加载中…', - axis: Axis.vertical, - ), - ]); + return const Row( + // spacing: 36, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.circle, + text: '加载中…', + axis: Axis.vertical, + ), + SizedBox(width: 36), + TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.activity, + text: '加载中…', + axis: Axis.vertical, + ), + ], + ); } /// 纯文字 @Demo(group: 'loading') Widget _buildPureTextLoading(BuildContext context) { - return _buildRow([ - const TDLoading( - size: TDLoadingSize.small, - text: '加载中…', - ), - TDLoading( - size: TDLoadingSize.small, - text: '加载失败', - textColor: TDTheme.of(context).fontGyColor3, - ), - TDLoading( - size: TDLoadingSize.small, - text: '加载失败', - refreshWidget: GestureDetector( - child: TDText( - '刷新', - font: TDTheme.of(context).fontBodySmall, - textColor: TDTheme.of(context).brandNormalColor, + return Row( + // spacing: 36, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const TDLoading( + size: TDLoadingSize.small, + text: '加载中…', + ), + const SizedBox(width: 36), + TDLoading( + size: TDLoadingSize.small, + text: '加载失败', + textColor: TDTheme.of(context).textColorPlaceholder, + ), + const SizedBox(width: 36), + TDLoading( + size: TDLoadingSize.small, + text: '加载失败', + refreshWidget: GestureDetector( + child: TDText( + '刷新', + font: TDTheme.of(context).fontBodySmall, + textColor: TDTheme.of(context).brandNormalColor, + ), + onTap: () { + TDToast.showText('刷新', context: context); + }, ), - onTap: () { - TDToast.showText('刷新', context: context); - }, ), - ), - ]); + ], + ); } /// 大尺寸 @Demo(group: 'loading') Widget _buildLargeLoading(BuildContext context) { - return _buildRow([ - const TDLoading( - size: TDLoadingSize.large, - icon: TDLoadingIcon.circle, - text: '加载中…', - axis: Axis.horizontal, - ), - ]); + return const TDLoading( + size: TDLoadingSize.large, + icon: TDLoadingIcon.circle, + text: '加载中…', + axis: Axis.horizontal, + ); } /// 中尺寸 @Demo(group: 'loading') Widget _buildMediumLoading(BuildContext context) { - return _buildRow([ - const TDLoading( - size: TDLoadingSize.medium, - icon: TDLoadingIcon.circle, - text: '加载中…', - axis: Axis.horizontal, - ), - ]); + return const TDLoading( + size: TDLoadingSize.medium, + icon: TDLoadingIcon.circle, + text: '加载中…', + axis: Axis.horizontal, + ); } /// 小尺寸 @Demo(group: 'loading') Widget _buildSmallLoading(BuildContext context) { - return _buildRow([ - const TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.circle, - text: '加载中…', - axis: Axis.horizontal, - ), - ]); + return const TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.circle, + text: '加载中…', + axis: Axis.horizontal, + ); } double _currentSliderValue = 1000; @@ -291,36 +288,35 @@ class _TDLoadingPageState extends State { /// 自定义尺寸 @Demo(group: 'loading') Widget _buildCustomSpeedLoading(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TDLoading( - size: TDLoadingSize.small, - icon: TDLoadingIcon.circle, - axis: Axis.horizontal, - text: '加载中…', - duration: _currentSliderValue.round(), + return Column( + // spacing: 16, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + TDLoading( + size: TDLoadingSize.small, + icon: TDLoadingIcon.circle, + axis: Axis.horizontal, + text: '加载中…', + duration: _currentSliderValue.round(), + ), + const SizedBox(height: 16), + TDSlider( + value: _currentSliderValue, + sliderThemeData: TDSliderThemeData( + context: context, + max: 2000, + min: -20, + divisions: 100, + showThumbValue: true, + scaleFormatter: (value) => value.toInt().toString(), ), - TDSlider(value: _currentSliderValue, - sliderThemeData: TDSliderThemeData( - context: context, - max: 2000, - min: -20, - divisions: 100, - showThumbValue: true, - scaleFormatter: (value) => value.toInt().toString(), - ), - onChanged: (double value) { - setState(() { - _currentSliderValue = value; - }); - },) - ], - ), + onChanged: (double value) { + setState(() { + _currentSliderValue = value; + }); + }, + ) + ], ); } } diff --git a/tdesign-component/example/lib/page/td_message_page.dart b/tdesign-component/example/lib/page/td_message_page.dart index 217214881..fed9981e4 100644 --- a/tdesign-component/example/lib/page/td_message_page.dart +++ b/tdesign-component/example/lib/page/td_message_page.dart @@ -3,22 +3,16 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; -class TDMessagePage extends StatefulWidget { - const TDMessagePage({Key? key}) : super(key: key); +class TDMessagePage extends StatelessWidget { + const TDMessagePage({super.key}); - @override - State createState() => _TDMessagePageState(); -} - -class _TDMessagePageState extends State { final _commonContent = '这是一条普通的通知信息'; final longContent = '这是一条普通的通知信息看,这是一条普通的通知信息,这是一条普通的通知信息'; @override Widget build(BuildContext context) { return ExamplePage( - title: tdTitle(), - backgroundColor: Colors.white, + title: tdTitle(context), desc: '用于轻量级反馈或提示,不会打断用户操作。', exampleCodeGroup: 'message', children: [ @@ -45,7 +39,6 @@ class _TDMessagePageState extends State { text: '纯文字的通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( @@ -70,7 +63,6 @@ class _TDMessagePageState extends State { text: '带图标的通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( @@ -91,7 +83,6 @@ class _TDMessagePageState extends State { text: '带关闭的通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( @@ -117,7 +108,6 @@ class _TDMessagePageState extends State { text: '可滚动的通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( @@ -141,7 +131,6 @@ class _TDMessagePageState extends State { text: '带按钮的通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( @@ -155,7 +144,6 @@ class _TDMessagePageState extends State { name: '按钮', uri: Uri.parse('https://tdesign.tencent.com/'), ), - // link: '按钮', onLinkClick: () { print('link clicked!'); }); @@ -169,7 +157,6 @@ class _TDMessagePageState extends State { text: '普通通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( @@ -191,7 +178,6 @@ class _TDMessagePageState extends State { text: '成功通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( @@ -213,7 +199,6 @@ class _TDMessagePageState extends State { text: '警示通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( @@ -234,7 +219,6 @@ class _TDMessagePageState extends State { text: '错误通知', size: TDButtonSize.large, type: TDButtonType.outline, - width: 450, theme: TDButtonTheme.primary, onTap: () { TDMessage.showMessage( diff --git a/tdesign-component/example/lib/page/td_navbar_page.dart b/tdesign-component/example/lib/page/td_navbar_page.dart index 99161137a..490e757ec 100644 --- a/tdesign-component/example/lib/page/td_navbar_page.dart +++ b/tdesign-component/example/lib/page/td_navbar_page.dart @@ -18,56 +18,23 @@ class TDNavBarPage extends StatelessWidget { ExampleModule( title: '组件类型', children: [ - ExampleItem( - desc: '基础H5导航栏', - builder: _baseH5Navbar, - ), - ExampleItem( - builder: _leftMultiAction - ), - ExampleItem( - builder: _rightMultiAction, - ), - ExampleItem( - desc: '带搜索导航栏', - builder: _searchNavbar, - ), - ExampleItem( - desc: '带图片导航栏', - builder: _logoNavbar - ), + ExampleItem(desc: '基础H5导航栏', builder: _baseH5Navbar), + ExampleItem(builder: _leftMultiAction), + ExampleItem(builder: _rightMultiAction), + ExampleItem(desc: '带搜索导航栏', builder: _searchNavbar), + ExampleItem(desc: '带图片导航栏', builder: _logoNavbar), ], ), - ExampleModule( - title: '组件样式', - children: [ - ExampleItem( - desc: '标题对齐', - builder: _titleCenterNavbar, - ), - ExampleItem( - builder: _titleLeftNavbar, - ), - - ExampleItem( - desc: '标题尺寸', - builder: _titleNormalNavbar, - ), - ExampleItem( - builder: _titleBelowNavbar, - ), - ExampleItem( - desc: '自定义颜色', - builder: _setBgColorNavbar, - ), - ] - ) + ExampleModule(title: '组件样式', children: [ + ExampleItem(desc: '标题对齐', builder: _titleCenterNavbar), + ExampleItem(builder: _titleLeftNavbar), + ExampleItem(desc: '标题尺寸', builder: _titleNormalNavbar), + ExampleItem(builder: _titleBelowNavbar), + ExampleItem(desc: '自定义颜色', builder: _setBgColorNavbar), + ]) ], test: [ - ExampleItem( - desc: '底部阴影', - builder: _shadowNavbar, - ), + ExampleItem(desc: '底部阴影', builder: _shadowNavbar), ], ); } @@ -75,11 +42,11 @@ class TDNavBarPage extends StatelessWidget { @Demo(group: 'navbar') Widget _baseH5Navbar(BuildContext context) { return const TDNavBar( - height: 48, - titleFontWeight: FontWeight.w600, - title: titleText, - screenAdaptation: false, - useDefaultBack: true, + height: 48, + titleFontWeight: FontWeight.w600, + title: titleText, + screenAdaptation: false, + useDefaultBack: true, ); } @@ -98,71 +65,73 @@ class TDNavBarPage extends StatelessWidget { ], rightBarItems: [ TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24) - ] - ), + ]), ); } @Demo(group: 'navbar') Widget _rightMultiAction(BuildContext context) { return Padding( - padding: const EdgeInsets.only(top: 16), - child: TDNavBar( - height: 48, - title: titleText, - titleFontWeight: FontWeight.w600, - screenAdaptation: false, - useDefaultBack: true, - rightBarItems: [ - TDNavBarItem(icon: TDIcons.home, iconSize: 24, ), - TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24,) - ] - ), + padding: const EdgeInsets.only(top: 16), + child: TDNavBar( + height: 48, + title: titleText, + titleFontWeight: FontWeight.w600, + screenAdaptation: false, + useDefaultBack: true, + rightBarItems: [ + TDNavBarItem( + icon: TDIcons.home, + iconSize: 24, + ), + TDNavBarItem( + icon: TDIcons.ellipsis, + iconSize: 24, + ) + ]), ); } @Demo(group: 'navbar') - Widget _searchNavbar(BuildContext context){ + Widget _searchNavbar(BuildContext context) { return TDNavBar( - useDefaultBack: false, - screenAdaptation: false, - centerTitle: false, - titleMargin: 0, - titleWidget: TDSearchBar( - needCancel: false, - autoHeight: true, - padding: const EdgeInsets.fromLTRB(0, 2, 0, 2), - placeHolder: '搜索预设文案', - mediumStyle: true, - style: TDSearchStyle.round, - onTextChanged: (String text) { - print('input:$text'); - }, - ), - rightBarItems: [ - TDNavBarItem(icon: TDIcons.home,iconSize: 24), - TDNavBarItem(icon: TDIcons.ellipsis,iconSize: 24) - ] - ); + useDefaultBack: false, + screenAdaptation: false, + centerTitle: false, + titleMargin: 0, + titleWidget: TDSearchBar( + needCancel: false, + autoHeight: true, + padding: const EdgeInsets.fromLTRB(0, 2, 0, 2), + placeHolder: '搜索预设文案', + mediumStyle: true, + style: TDSearchStyle.round, + onTextChanged: (String text) { + print('input:$text'); + }, + ), + rightBarItems: [ + TDNavBarItem(icon: TDIcons.home, iconSize: 24), + TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24) + ]); } @Demo(group: 'navbar') - Widget _logoNavbar(BuildContext context){ + Widget _logoNavbar(BuildContext context) { return TDNavBar( useDefaultBack: false, screenAdaptation: false, centerTitle: false, titleMargin: 0, - titleWidget: const TDImage( + titleWidget: const TDImage( assetUrl: 'assets/img/td_brand.png', width: 102, height: 24, ), rightBarItems: [ - TDNavBarItem(icon: TDIcons.home,iconSize: 24), - TDNavBarItem(icon: TDIcons.ellipsis,iconSize: 24) - ] - ); + TDNavBarItem(icon: TDIcons.home, iconSize: 24), + TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24) + ]); } @Demo(group: 'navbar') @@ -174,10 +143,9 @@ class TDNavBarPage extends StatelessWidget { screenAdaptation: false, useDefaultBack: true, rightBarItems: [ - TDNavBarItem(icon: TDIcons.home,iconSize: 24), - TDNavBarItem(icon: TDIcons.ellipsis,iconSize: 24) - ] - ); + TDNavBarItem(icon: TDIcons.home, iconSize: 24), + TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24) + ]); } @Demo(group: 'navbar') @@ -193,10 +161,9 @@ class TDNavBarPage extends StatelessWidget { screenAdaptation: false, useDefaultBack: true, rightBarItems: [ - TDNavBarItem(icon: TDIcons.home,iconSize: 24), - TDNavBarItem(icon: TDIcons.ellipsis,iconSize: 24) - ] - ), + TDNavBarItem(icon: TDIcons.home, iconSize: 24), + TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24) + ]), ); } @@ -209,23 +176,26 @@ class TDNavBarPage extends StatelessWidget { screenAdaptation: false, useDefaultBack: true, rightBarItems: [ - TDNavBarItem(icon: TDIcons.home,iconSize: 24), - TDNavBarItem(icon: TDIcons.ellipsis,iconSize: 24) - ] - ); + TDNavBarItem(icon: TDIcons.home, iconSize: 24), + TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24) + ]); } @Demo(group: 'navbar') Widget _titleBelowNavbar(BuildContext context) { return Padding( - padding: const EdgeInsets.only(top: 16), - child: TDNavBar( + padding: const EdgeInsets.only(top: 16), + child: TDNavBar( height: 104, title: '返回', - titleColor: const Color.fromRGBO(0, 0, 0, 0.9), + titleColor: TDTheme.of(context).textColorPrimary, belowTitleWidget: SizedBox( height: 56, - child: TDText(titleText, font: Font(size: 28, lineHeight: 52), fontWeight: FontWeight.w600,), + child: TDText( + titleText, + font: Font(size: 28, lineHeight: 52), + fontWeight: FontWeight.w600, + ), ), titleFont: Font(size: 16, lineHeight: 24), centerTitle: false, @@ -233,13 +203,12 @@ class TDNavBarPage extends StatelessWidget { screenAdaptation: false, useDefaultBack: false, leftBarItems: [ - TDNavBarItem(icon: TDIcons.chevron_left,iconSize: 24), + TDNavBarItem(icon: TDIcons.chevron_left, iconSize: 24), ], rightBarItems: [ - TDNavBarItem(icon: TDIcons.home,iconSize: 24), - TDNavBarItem(icon: TDIcons.ellipsis,iconSize: 24) - ] - ), + TDNavBarItem(icon: TDIcons.home, iconSize: 24), + TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24) + ]), ); } @@ -254,13 +223,17 @@ class TDNavBarPage extends StatelessWidget { useDefaultBack: false, screenAdaptation: false, leftBarItems: [ - TDNavBarItem(icon: TDIcons.chevron_left, iconSize: 24, iconColor: Colors.white), + TDNavBarItem( + icon: TDIcons.chevron_left, + iconSize: 24, + iconColor: Colors.white), ], rightBarItems: [ - TDNavBarItem(icon: TDIcons.home, iconSize: 24, iconColor: Colors.white), - TDNavBarItem(icon: TDIcons.ellipsis, iconSize: 24, iconColor: Colors.white) - ] - ); + TDNavBarItem( + icon: TDIcons.home, iconSize: 24, iconColor: Colors.white), + TDNavBarItem( + icon: TDIcons.ellipsis, iconSize: 24, iconColor: Colors.white) + ]); } @Demo(group: 'navbar') @@ -275,7 +248,7 @@ class TDNavBarPage extends StatelessWidget { BoxShadow( blurRadius: 4, offset: const Offset(0, 4), - color: TDTheme.of(context).grayColor5, + color: TDTheme.of(context).componentBorderColor, ) ], ); diff --git a/tdesign-component/example/lib/page/td_notice_bar_page.dart b/tdesign-component/example/lib/page/td_notice_bar_page.dart index 770f9301a..e32d71135 100644 --- a/tdesign-component/example/lib/page/td_notice_bar_page.dart +++ b/tdesign-component/example/lib/page/td_notice_bar_page.dart @@ -19,16 +19,17 @@ class TDNoticeBarPage extends StatelessWidget { title: tdTitle(context), exampleCodeGroup: 'noticeBar', desc: '在导航栏下方,用于给用户显示提示消息。', - backgroundColor: Colors.white, - children: [ + children: const [ ExampleModule(title: '组件类型', children: [ ExampleItem(desc: '纯文字的公告栏', builder: _textNoticeBar), ExampleItem(desc: '可滚动的公告栏', builder: _scrollNoticeBar), - ExampleItem(builder: _scrollIconNoticeBar), + ExampleItem( + padding: EdgeInsets.only(top: 16), builder: _scrollIconNoticeBar), ExampleItem(desc: '带图标的公告栏', builder: _iconNoticeBar), ExampleItem(desc: '带关闭的公告栏', builder: _closeNoticeBar), ExampleItem(desc: '带入口的公告栏', builder: _entranceNoticeBar1), - ExampleItem(builder: _entranceNoticeBar2), + ExampleItem( + padding: EdgeInsets.only(top: 16), builder: _entranceNoticeBar2), ExampleItem(desc: '自定义样式的公告栏', builder: _customNoticeBar), ]), ExampleModule(title: '组件状态', children: [ @@ -41,7 +42,7 @@ class TDNoticeBarPage extends StatelessWidget { ExampleItem(desc: '卡片顶部', builder: _cardNoticeBar), ]) ], - test: [ + test: const [ ExampleItem(desc: '带点击事件的公告栏', builder: _tapNoticeBar), ExampleItem(desc: '自定义左侧内容的公告栏', builder: _leftNoticeBar), ExampleItem(desc: '垂直滚动的公告栏', builder: _stepNoticeBar), @@ -52,13 +53,15 @@ class TDNoticeBarPage extends StatelessWidget { @Demo(group: 'noticeBar') Widget _textNoticeBar(BuildContext context) { - return const TDNoticeBar(context: '这是一条普通的通知信息'); + return const TDNoticeBar( + content: '这是一条普通的通知信息', + ); } @Demo(group: 'noticeBar') Widget _scrollNoticeBar(BuildContext context) { return const TDNoticeBar( - context: '提示文字描述提示文字描述提示文字描述提示文字描述提示文字', + content: '提示文字描述提示文字描述提示文字描述提示文字描述提示文字', marquee: true, speed: 50, ); @@ -66,21 +69,18 @@ Widget _scrollNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _scrollIconNoticeBar(BuildContext context) { - return const Padding( - padding: EdgeInsets.only(top: 16), - child: TDNoticeBar( - context: '提示文字描述提示文字描述提示文字描述提示文字描述提示文字', - speed: 50, - prefixIcon: TDIcons.sound, - marquee: true, - ), + return const TDNoticeBar( + content: '提示文字描述提示文字描述提示文字描述提示文字描述提示文字', + speed: 50, + prefixIcon: TDIcons.sound, + marquee: true, ); } @Demo(group: 'noticeBar') Widget _iconNoticeBar(BuildContext context) { return const TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条普通的通知信息', prefixIcon: TDIcons.error_circle_filled, ); } @@ -88,7 +88,7 @@ Widget _iconNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _closeNoticeBar(BuildContext context) { return const TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条普通的通知信息', prefixIcon: TDIcons.error_circle_filled, suffixIcon: TDIcons.close, ); @@ -97,7 +97,7 @@ Widget _closeNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _entranceNoticeBar1(BuildContext context) { return const TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条普通的通知信息', prefixIcon: TDIcons.error_circle_filled, right: TDButton( text: '文字按钮', @@ -112,30 +112,28 @@ Widget _entranceNoticeBar1(BuildContext context) { @Demo(group: 'noticeBar') Widget _entranceNoticeBar2(BuildContext context) { - return const Padding( - padding: EdgeInsets.only(top: 16), - child: TDNoticeBar( - context: '这是一条普通的通知信息', - prefixIcon: TDIcons.error_circle_filled, - suffixIcon: TDIcons.chevron_right, - ), + return const TDNoticeBar( + content: '这是一条普通的通知信息', + prefixIcon: TDIcons.error_circle_filled, + suffixIcon: TDIcons.chevron_right, ); } @Demo(group: 'noticeBar') Widget _customNoticeBar(BuildContext context) { return TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条普通的通知信息', prefixIcon: TDIcons.notification, suffixIcon: TDIcons.chevron_right, - style: TDNoticeBarStyle(backgroundColor: TDTheme.of(context).grayColor3), + style: + TDNoticeBarStyle(backgroundColor: TDTheme.of(context).bgColorComponent), ); } @Demo(group: 'noticeBar') Widget _normalNoticeBar(BuildContext context) { return const TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条普通的通知信息', prefixIcon: TDIcons.error_circle_filled, theme: TDNoticeBarTheme.info, ); @@ -144,8 +142,8 @@ Widget _normalNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _successNoticeBar(BuildContext context) { return const TDNoticeBar( - context: '这是一条普通的通知信息', - prefixIcon: TDIcons.error_circle_filled, + content: '这是一条成功的通知信息', + prefixIcon: TDIcons.check_circle_filled, theme: TDNoticeBarTheme.success, ); } @@ -153,7 +151,7 @@ Widget _successNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _warningNoticeBar(BuildContext context) { return const TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条警示的通知信息', prefixIcon: TDIcons.error_circle_filled, theme: TDNoticeBarTheme.warning, ); @@ -162,7 +160,7 @@ Widget _warningNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _errorNoticeBar(BuildContext context) { return const TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条错误的通知信息', prefixIcon: TDIcons.error_circle_filled, theme: TDNoticeBarTheme.error, ); @@ -175,7 +173,7 @@ Widget _cardNoticeBar(BuildContext context) { margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( color: TDNoticeBarStyle.generateTheme(context).backgroundColor, - borderRadius: const BorderRadius.all(Radius.circular(9)), + borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: const [ BoxShadow( color: Color(0x0d000000), @@ -206,16 +204,16 @@ Widget _cardNoticeBar(BuildContext context) { ), clipBehavior: Clip.hardEdge, child: const TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条普通的通知信息', prefixIcon: TDIcons.error_circle_filled, suffixIcon: TDIcons.chevron_right, ), ), Container( height: 150, - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(12)), + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorContainer, + borderRadius: const BorderRadius.all(Radius.circular(12)), ), ) ], @@ -226,7 +224,7 @@ Widget _cardNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _tapNoticeBar(BuildContext context) { return TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条普通的通知信息', prefixIcon: TDIcons.error_circle_filled, suffixIcon: TDIcons.chevron_right, onTap: (trigger) { @@ -238,7 +236,7 @@ Widget _tapNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _leftNoticeBar(BuildContext context) { return const TDNoticeBar( - context: '这是一条普通的通知信息', + content: '这是一条普通的通知信息', suffixIcon: TDIcons.chevron_right, left: TDButton( text: '文本', @@ -254,7 +252,12 @@ Widget _leftNoticeBar(BuildContext context) { @Demo(group: 'noticeBar') Widget _stepNoticeBar(BuildContext context) { return const TDNoticeBar( - context: ['君不见黄河之水天上来', '奔流到海不复回', '君不见'], + context: [ + '君不见黄河之水天上来', + '奔流到海不复回', + '君不见', + '这是一条很长很长的消息提醒内容测试这是一条很长很长的消息提醒内容测试' + ], direction: Axis.vertical, prefixIcon: TDIcons.sound, marquee: true, diff --git a/tdesign-component/example/lib/page/td_picker_page.dart b/tdesign-component/example/lib/page/td_picker_page.dart index 5e65432f2..43cd04059 100644 --- a/tdesign-component/example/lib/page/td_picker_page.dart +++ b/tdesign-component/example/lib/page/td_picker_page.dart @@ -4,7 +4,6 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; - class TDPickerPage extends StatefulWidget { const TDPickerPage({Key? key}) : super(key: key); @@ -19,6 +18,7 @@ class _TDPickerPageState extends State { String selected_3 = ''; List> data_2 = []; String selected_4 = ''; + String selected_5 = ''; Map data_3 = { '广东省': { '深圳市': ['南山区南山区南山区南山区南山区', '宝安区', '罗湖区', '福田区'], @@ -41,7 +41,7 @@ class _TDPickerPageState extends State { }, }; - Map data_test = { + Map dataTest = { '广东省': { '深圳市': ['南山区', '宝安区', '罗湖区', '福田区'], '广州市': ['天河区', '越秀区', '白云区', '花都区'], @@ -53,7 +53,19 @@ class _TDPickerPageState extends State { '温州市': ['鹿城区', '瑞安市', '乐清市'] }, '江苏省': { - '南京市': ['玄武区', '秦淮区', '建邺区', '鼓楼区', '浦口区', '栖霞区', '雨花台区', '江宁区', '六合区', '溧水区', '高淳区'], + '南京市': [ + '玄武区', + '秦淮区', + '建邺区', + '鼓楼区', + '浦口区', + '栖霞区', + '雨花台区', + '江宁区', + '六合区', + '溧水区', + '高淳区' + ], '无锡市': ['梁溪区', '锡山区', '惠山区', '滨湖区', '新吴区'], '徐州市': ['鼓楼区', '云龙区', '贾汪区', '泉山区', '铜山区'], '常州市': ['天宁区', '钟楼区', '新北区', '武进区', '金坛区'], @@ -164,13 +176,10 @@ class _TDPickerPageState extends State { } }; - - String selected_5 = ''; - @override void initState() { var list = []; - for(var i = 2022; i >= 2000; i--) { + for (var i = 2022; i >= 2000; i--) { list.add('${i}年'); } data_2.add(list); @@ -198,135 +207,198 @@ class _TDPickerPageState extends State { children: [ ExampleItem(desc: '带标题选择器', builder: buildAreaWithTitle), ExampleItem(desc: '无标题选择器', builder: buildAreaWithoutTitle), + ExampleItem(desc: '不使用弹窗、不带顶部内容', builder: buildWithoutHeader), ], ) ], test: [ ExampleItem( desc: '自定义left/right text', builder: buildCustomLeftRightText), - ExampleItem( - desc: '级联选择保持下一级选项', builder: buildKeepMultiArea), + ExampleItem(desc: '级联选择保持下一级选项', builder: buildKeepMultiArea), ], ); } @Demo(group: 'picker') Widget buildArea(BuildContext context) { - return GestureDetector( - onTap: (){ - TDPicker.showMultiPicker(context, title: '选择地区', - onConfirm: (selected) { - setState(() { - selected_1 = '${data_1[selected[0]]}'; - }); - Navigator.of(context).pop(); - }, data: [data_1]); + const title = '选择地区'; + return TDCell( + title: title, + note: selected_1.isEmpty ? '请选择' : selected_1, + arrow: true, + onClick: (click) { + TDPicker.showMultiPicker( + context, + title: title, + onConfirm: (selected) { + setState(() { + selected_1 = '${data_1[selected[0]]}'; + }); + Navigator.of(context).pop(); + }, + data: [data_1], + ); }, - child: buildSelectRow(context, selected_1, '选择地区'), ); } @Demo(group: 'picker') Widget buildTime(BuildContext context) { - return GestureDetector( - onTap: (){ - TDPicker.showMultiPicker(context, title: '选择时间', - onConfirm: (selected) { - setState(() { - selected_2 = '${data_2[0][selected[0]]} ${data_2[1][selected[1]]}'; - }); - Navigator.of(context).pop(); - }, data: data_2); + const title = '选择时间'; + return TDCell( + title: title, + note: selected_2.isEmpty ? '请选择' : selected_2, + arrow: true, + onClick: (click) { + TDPicker.showMultiPicker( + context, + title: title, + onConfirm: (selected) { + print('selected ${selected}'); + setState(() { + selected_2 = + '${data_2[0][selected[0]]} ${data_2[1][selected[1]]}'; + }); + Navigator.of(context).pop(); + }, + data: data_2, + ); }, - child: buildSelectRow(context, selected_2, '选择时间'), ); } @Demo(group: 'picker') Widget buildMultiArea(BuildContext context) { - return GestureDetector( - onTap: (){ - TDPicker.showMultiLinkedPicker(context, - title: '选择地区', + const title = '选择地区'; + return TDCell( + title: title, + note: selected_3.isEmpty ? '请选择' : selected_3, + arrow: true, + onClick: (click) { + TDPicker.showMultiLinkedPicker( + context, + title: title, onConfirm: (selected) { setState(() { selected_3 = '${selected[0]} ${selected[1]} ${selected[2]}'; }); Navigator.of(context).pop(); }, + data: dataTest, columnNum: 3, - data: data_test, // ← 这里添加了必需的 data 参数 - initialData: ['广东省', '深圳市', '南山区'], - + initialData: ['浙江省', '杭州市', '西湖区'], ); }, - child: buildSelectRow(context, selected_3, '选择地区'), ); } @Demo(group: 'picker') Widget buildAreaWithTitle(BuildContext context) { - return GestureDetector( - onTap: (){ - TDPicker.showMultiPicker(context, title: '选择地区', - onConfirm: (selected) { - setState(() { - selected_4 = '${data_1[selected[0]]}'; - }); - Navigator.of(context).pop(); - }, data: [data_1]); + const title = '选择地区'; + return TDCell( + title: title, + note: selected_4.isEmpty ? '请选择' : selected_4, + arrow: true, + onClick: (click) { + TDPicker.showMultiPicker( + context, + title: '带标题选择器', + onConfirm: (selected) { + setState(() { + selected_4 = '${data_1[selected[0]]}'; + }); + Navigator.of(context).pop(); + }, + data: [data_1], + ); }, - child: buildSelectRow(context, selected_4, '带标题选择器'), ); } @Demo(group: 'picker') Widget buildAreaWithoutTitle(BuildContext context) { - return GestureDetector( - onTap: (){ - TDPicker.showMultiPicker(context, title: '', - onConfirm: (selected) { - setState(() { - selected_5 = '${data_1[selected[0]]}'; - }); - Navigator.of(context).pop(); - }, data: [data_1]); + return TDCell( + title: '选择地区', + note: selected_5.isEmpty ? '请选择' : selected_5, + arrow: true, + onClick: (click) { + TDPicker.showMultiPicker( + context, + // 不传或传空字符串、null,则不显示标题 + // title: '', + onConfirm: (selected) { + setState(() { + selected_5 = '${data_1[selected[0]]}'; + }); + Navigator.of(context).pop(); + }, + data: [data_1], + ); }, - child: buildSelectRow(context, selected_5, '无标题选择器'), + ); + } + + @Demo(group: 'picker') + Widget buildWithoutHeader(BuildContext context) { + return TDMultiPicker( + /// 不显示header内容 + header: false, + /// todo onChange + onConfirm: (selected) { + setState(() { + selected_5 = '${data_1[selected[0]]}'; + }); + Navigator.of(context).pop(); + }, + data: [data_1], ); } @Demo(group: 'picker') Widget buildCustomLeftRightText(BuildContext context) { - return Column( - children: [ - GestureDetector( - onTap: () { - TDPicker.showMultiPicker(context, - leftText: '自定义取消', - rightText: '自定义确认', - title: '基础选择器', onConfirm: (selected) { - setState(() { - selected_5 = '${data_1[selected[0]]}'; - }); - Navigator.of(context).pop(); - }, data: [data_1]); + return TDCellGroup( + cells: [ + TDCell( + title: '基础选择器', + note: selected_5.isEmpty ? '请选择' : selected_5, + arrow: true, + onClick: (click) { + TDPicker.showMultiPicker( + context, + leftText: '自定义取消', + rightText: '自定义确认', + title: '基础选择器', + onConfirm: (selected) { + setState(() { + selected_5 = '${data_1[selected[0]]}'; + }); + Navigator.of(context).pop(); + }, + data: [data_1], + ); }, - child: buildSelectRow(context, selected_5, '基础选择器'), ), - GestureDetector( - onTap: () { - TDPicker.showMultiLinkedPicker(context, - leftText: '自定义取消', - rightText: '自定义确认', - title: '联动选择器', onConfirm: (selected) { - setState(() { - selected_3 = '${selected[0]} ${selected[1]} ${selected[2]}'; - }); - Navigator.of(context).pop(); - }, data: data_3, columnNum: 3, initialData: ['浙江省', '杭州市', '西湖区']); + TDCell( + title: '联动选择器', + note: selected_3.isEmpty ? '请选择' : selected_3, + arrow: true, + onClick: (click) { + TDPicker.showMultiLinkedPicker( + context, + leftText: '自定义取消', + rightText: '自定义确认', + title: '联动选择器', + onConfirm: (selected) { + setState(() { + selected_3 = '${selected[0]} ${selected[1]} ${selected[2]}'; + }); + Navigator.of(context).pop(); + }, + data: data_3, + columnNum: 3, + initialData: ['浙江省', '杭州市', '西湖区'], + ); }, - child: buildSelectRow(context, selected_3, '联动选择器'), ) ], ); @@ -334,63 +406,26 @@ class _TDPickerPageState extends State { @Demo(group: 'picker') Widget buildKeepMultiArea(BuildContext context) { - return GestureDetector( - onTap: (){ - TDPicker.showMultiLinkedPicker(context, title: '选择地区', - onConfirm: (selected) { - setState(() { - selected_3 = '${selected[0]} ${selected[1]} ${selected[2]}'; - }); - Navigator.of(context).pop(); - }, - data: data_3, - columnNum: 3, - keepSameSelection: true, - initialData: ['广东省', '深圳市', '罗湖区']); + return TDCell( + title: '选择地区', + note: selected_3.isEmpty ? '请选择' : selected_3, + arrow: true, + onClick: (click) { + TDPicker.showMultiLinkedPicker( + context, + title: '选择地区', + onConfirm: (selected) { + setState(() { + selected_3 = '${selected[0]} ${selected[1]} ${selected[2]}'; + }); + Navigator.of(context).pop(); + }, + data: data_3, + columnNum: 3, + keepSameSelection: true, + initialData: ['广东省', '深圳市', '罗湖区'], + ); }, - child: buildSelectRow(context, selected_3, '选择地区'), - ); - } - - Widget buildSelectRow(BuildContext context, String output, String title) { - return Container( - color: TDTheme.of(context).whiteColor1, - height: 56, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 16, top: 16, bottom: 16), - child: TDText(title, font: TDTheme.of(context).fontBodyLarge,), - ), - Expanded(child: Padding( - padding: const EdgeInsets.only(right: 16, left: 16), - child: Row( - children: [ - Expanded(child: TDText( - output, - font: TDTheme.of(context).fontBodyLarge, - textColor: TDTheme.of(context).fontGyColor3.withOpacity(0.4), - maxLines: 1, - overflow: TextOverflow.ellipsis, - )), - Padding( - padding: const EdgeInsets.only(left: 2), - child: Icon( - TDIcons.chevron_right, - color: TDTheme.of(context).fontGyColor3.withOpacity(0.4),), - ), - ], - ), - )), - ], - ), - const TDDivider(margin: EdgeInsets.only(left: 16, ),) - ], - ), ); } } diff --git a/tdesign-component/example/lib/page/td_popover_page.dart b/tdesign-component/example/lib/page/td_popover_page.dart index 05bce06ab..ce0f15480 100644 --- a/tdesign-component/example/lib/page/td_popover_page.dart +++ b/tdesign-component/example/lib/page/td_popover_page.dart @@ -12,13 +12,26 @@ class TDPopoverPage extends StatefulWidget { } class _TDPopoverPage extends State { + TDPopoverTheme theme = TDPopoverTheme.light; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + theme = Theme.of(context).brightness == Brightness.dark + ? TDPopoverTheme.light + : TDPopoverTheme.dark; + }); + }); + } + @override Widget build(BuildContext context) { return ExamplePage( title: tdTitle(), desc: '用于文字提示的气泡框。', exampleCodeGroup: 'popover', - backgroundColor: TDTheme.of(context).whiteColor1, children: [ ExampleModule( title: '组件类型', @@ -41,15 +54,12 @@ class _TDPopoverPage extends State { direction: Axis.horizontal, children: [ Expanded( - flex: 1, child: CodeWrapper(builder: _buildDarkPopover), ), Expanded( - flex: 1, child: CodeWrapper(builder: _buildLightPopover), ), Expanded( - flex: 1, child: CodeWrapper(builder: _buildInfoPopover), ), ], @@ -58,15 +68,12 @@ class _TDPopoverPage extends State { direction: Axis.horizontal, children: [ Expanded( - flex: 1, child: CodeWrapper(builder: _buildSuccessPopover), ), Expanded( - flex: 1, child: CodeWrapper(builder: _buildWarningPopover), ), Expanded( - flex: 1, child: CodeWrapper(builder: _buildErrorPopover), ), ], @@ -87,15 +94,12 @@ class _TDPopoverPage extends State { direction: Axis.horizontal, children: [ Expanded( - flex: 1, child: CodeWrapper(builder: _buildTopLeftPopover), ), Expanded( - flex: 1, child: CodeWrapper(builder: _buildTopPopover), ), Expanded( - flex: 1, child: CodeWrapper(builder: _buildTopRightPopover), ), ], @@ -114,15 +118,12 @@ class _TDPopoverPage extends State { direction: Axis.horizontal, children: [ Expanded( - flex: 1, child: CodeWrapper(builder: _buildBottomLeftPopover), ), Expanded( - flex: 1, child: CodeWrapper(builder: _buildBottomPopover), ), Expanded( - flex: 1, child: CodeWrapper(builder: _buildBottomRightPopover), ), ], @@ -141,7 +142,6 @@ class _TDPopoverPage extends State { direction: Axis.horizontal, children: [ Expanded( - flex: 1, child: Column( children: [ CodeWrapper(builder: _buildRightTopPopover), @@ -150,10 +150,7 @@ class _TDPopoverPage extends State { ], ), ), - const Expanded( - flex: 1, - child: SizedBox(), - ), + const Expanded(child: SizedBox()), ], ), ); @@ -169,12 +166,8 @@ class _TDPopoverPage extends State { child: Flex( direction: Axis.horizontal, children: [ - const Expanded( - flex: 1, - child: SizedBox(), - ), + const Expanded(child: SizedBox()), Expanded( - flex: 1, child: Column( children: [ CodeWrapper(builder: _buildLeftTopPopover), @@ -214,9 +207,9 @@ class _TDPopoverPage extends State { text: '带箭头', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { - TDPopover.showPopover(context: _, content: '弹出气泡内容'); + TDPopover.showPopover( + context: _, content: '弹出气泡内容', theme: theme); }, ); }, @@ -233,35 +226,37 @@ class _TDPopoverPage extends State { text: '不带箭头', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( - context: _, content: '弹出气泡内容', showArrow: false); + context: _, content: '弹出气泡内容', showArrow: false, theme: theme); }, ); }, ); } + // @todo Widget _buildPopoverList(BuildContext context) { + var textStyle = TextStyle( + color: theme == TDPopoverTheme.light + ? TDTheme.of(context).fontGyColor1 + : TDTheme.of(context).fontWhColor1); + return Column( children: [ Container( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24), - child: TDText('选项1', - style: TextStyle(color: TDTheme.of(context).whiteColor1)), + child: TDText('选项1', style: textStyle), ), - TDDivider(color: TDTheme.of(context).whiteColor1, height: 0.5), + const TDDivider(height: 0.5), Container( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24), - child: TDText('选项2', - style: TextStyle(color: TDTheme.of(context).whiteColor1)), + child: TDText('选项2', style: textStyle), ), - TDDivider(color: TDTheme.of(context).whiteColor1, height: 0.5), + const TDDivider(height: 0.5), Container( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24), - child: TDText('选项3', - style: TextStyle(color: TDTheme.of(context).whiteColor1)), + child: TDText('选项3', style: textStyle), ), ], ); @@ -275,11 +270,11 @@ class _TDPopoverPage extends State { text: '自定义内容', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, padding: const EdgeInsets.all(0), + theme: theme, width: 108, height: 148, contentWidget: _buildPopoverList(context), @@ -302,7 +297,6 @@ class _TDPopoverPage extends State { text: '深色', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, @@ -327,7 +321,6 @@ class _TDPopoverPage extends State { text: '浅色', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, @@ -353,7 +346,6 @@ class _TDPopoverPage extends State { text: '品牌色', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, @@ -379,7 +371,6 @@ class _TDPopoverPage extends State { text: '成功色', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, @@ -405,7 +396,6 @@ class _TDPopoverPage extends State { text: '警告色', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, @@ -431,7 +421,6 @@ class _TDPopoverPage extends State { text: '错误色', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, @@ -457,12 +446,12 @@ class _TDPopoverPage extends State { text: '顶部左', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.topLeft, + theme: theme, ); }, ); @@ -483,12 +472,12 @@ class _TDPopoverPage extends State { text: '顶部中', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.top, + theme: theme, ); }, ); @@ -509,12 +498,12 @@ class _TDPopoverPage extends State { text: '顶部右', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.topRight, + theme: theme, ); }, ); @@ -535,12 +524,12 @@ class _TDPopoverPage extends State { text: '底部左', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.bottomLeft, + theme: theme, ); }, ); @@ -561,12 +550,12 @@ class _TDPopoverPage extends State { text: '底部中', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.bottom, + theme: theme, ); }, ); @@ -587,12 +576,12 @@ class _TDPopoverPage extends State { text: '底部右', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.bottomRight, + theme: theme, ); }, ); @@ -613,12 +602,12 @@ class _TDPopoverPage extends State { text: '右侧上', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.rightTop, + theme: theme, ); }, ); @@ -639,12 +628,12 @@ class _TDPopoverPage extends State { text: '右侧中', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.right, + theme: theme, ); }, ); @@ -665,12 +654,12 @@ class _TDPopoverPage extends State { text: '右侧下', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.rightBottom, + theme: theme, ); }, ); @@ -691,12 +680,12 @@ class _TDPopoverPage extends State { text: '左侧上', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.leftTop, + theme: theme, ); }, ); @@ -717,12 +706,12 @@ class _TDPopoverPage extends State { text: '左侧中', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.left, + theme: theme, ); }, ); @@ -743,12 +732,12 @@ class _TDPopoverPage extends State { text: '左侧下', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, content: '弹出气泡内容', placement: TDPopoverPlacement.leftBottom, + theme: theme, ); }, ); @@ -769,12 +758,12 @@ class _TDPopoverPage extends State { text: '多行内容', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, width: 200, content: '弹出气泡内容弹出气泡内容弹出气泡内容弹出气泡内容', + theme: theme, ); }, ); @@ -795,12 +784,12 @@ class _TDPopoverPage extends State { text: '自定义圆角', type: TDButtonType.outline, theme: TDButtonTheme.primary, - onTap: () { TDPopover.showPopover( context: _, width: 200, radius: BorderRadius.circular(16), + theme: theme, content: '弹出气泡内容弹出气泡内容弹出气泡内容弹出气泡内容', ); }, diff --git a/tdesign-component/example/lib/page/td_popup_page.dart b/tdesign-component/example/lib/page/td_popup_page.dart index 13ed6a17f..5381d73ab 100644 --- a/tdesign-component/example/lib/page/td_popup_page.dart +++ b/tdesign-component/example/lib/page/td_popup_page.dart @@ -6,27 +6,14 @@ import '../base/example_widget.dart'; /// /// TDPopup演示 /// -class TDPopupPage extends StatefulWidget { - const TDPopupPage({Key? key}) : super(key: key); - - @override - State createState() { - return TDPopupPageState(); - } -} - -class TDPopupPageState extends State { - @override - void initState() { - super.initState(); - } +class TDPopupPage extends StatelessWidget { + const TDPopupPage({super.key}); @override Widget build(BuildContext context) { return ExamplePage( - title: tdTitle(), + title: tdTitle(context), padding: const EdgeInsets.only(top: 16), - backgroundColor: Colors.white, exampleCodeGroup: 'popup', desc: '由其他控件触发,屏幕滑出或弹出一块自定义内容区域', navBarKey: navBarkey, @@ -66,8 +53,8 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, + Navigator.of(context).push( + TDSlidePopupRoute( slideTransitionFrom: SlideTransitionFrom.bottom, builder: (context) { return TDPopupBottomConfirmPanel( @@ -80,14 +67,12 @@ class TDPopupPageState extends State { }, rightText: '关闭', rightTextColor: TDTheme.of(context).errorNormalColor, - rightClick: () { - Navigator.maybePop(context); - }, - child: Container( - height: 200, - ), + rightClick: () => Navigator.maybePop(context), + child: Container(height: 200), ); - })); + }, + ), + ); }, ); }), @@ -101,21 +86,18 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return TDPopupBottomDisplayPanel( - title: '标题文字标题文字标题文字标题文字标题文字标题文字标题文字', - closeColor: TDTheme.of(context).errorNormalColor, - closeClick: () { - Navigator.maybePop(context); - }, - child: Container( - height: 200, - ), - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return TDPopupBottomDisplayPanel( + title: '标题文字标题文字标题文字标题文字标题文字标题文字标题文字', + closeColor: TDTheme.of(context).errorNormalColor, + closeClick: () => Navigator.maybePop(context), + child: Container(height: 200), + ); + }), + ); }, ); }), @@ -123,125 +105,114 @@ class TDPopupPageState extends State { desc: '修改圆角', builder: (_) { return Column( + // spacing: 16, mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '底部弹出层-修改圆角', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, + TDButton( + text: '底部弹出层-修改圆角', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( slideTransitionFrom: SlideTransitionFrom.bottom, builder: (context) { return TDPopupBottomDisplayPanel( title: '标题文字标题文字标题文字标题文字标题文字标题文字标题文字', - closeColor: TDTheme.of(context).errorNormalColor, + closeColor: + TDTheme.of(context).errorNormalColor, + closeClick: () => Navigator.maybePop(context), + child: Container(height: 200), + radius: 6, + ); + }), + ); + }, + ), + const SizedBox(height: 16), + TDButton( + text: '底部弹出层-修改圆角', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return TDPopupBottomConfirmPanel( + title: '标题文字标题文字标题文字标题文字标题文字标题文字标题文字', + leftText: '点这里确认!', + leftTextColor: + TDTheme.of(context).brandNormalColor, + leftClick: () { + TDToast.showText('确认', context: context); + Navigator.maybePop(context); + }, + rightText: '关闭', + rightTextColor: + TDTheme.of(context).errorNormalColor, + rightClick: () => Navigator.maybePop(context), + child: Container(height: 200), + radius: 6, + ); + }), + ); + }, + ), + const SizedBox(height: 16), + TDButton( + text: '居中弹出层-修改圆角', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.center, + builder: (context) { + return TDPopupCenterPanel( + closeColor: + TDTheme.of(context).errorNormalColor, closeClick: () { Navigator.maybePop(context); }, - child: Container( - height: 200, - ), + child: const SizedBox(height: 240, width: 240), radius: 6, ); - })); - }, - ), + }), + ); + }, + ), + const SizedBox(height: 16), + TDButton( + text: '居中弹出层-底部关闭-修改圆角', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.center, + builder: (context) { + return TDPopupCenterPanel( + closeUnderBottom: true, + closeClick: () { + Navigator.maybePop(context); + }, + child: const SizedBox(height: 240, width: 240), + radius: 6, + ); + }), + ); + }, ), - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '底部弹出层-修改圆角', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return TDPopupBottomConfirmPanel( - title: '标题文字标题文字标题文字标题文字标题文字标题文字标题文字', - leftText: '点这里确认!', - leftTextColor: TDTheme.of(context).brandNormalColor, - leftClick: () { - TDToast.showText('确认', context: context); - Navigator.maybePop(context); - }, - rightText: '关闭', - rightTextColor: TDTheme.of(context).errorNormalColor, - rightClick: () { - Navigator.maybePop(context); - }, - child: Container( - height: 200, - ), - radius: 6, - ); - })); - }, - )), - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '居中弹出层-修改圆角', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.center, - builder: (context) { - return TDPopupCenterPanel( - closeColor: TDTheme.of(context).errorNormalColor, - closeClick: () { - Navigator.maybePop(context); - }, - child: const SizedBox( - height: 240, - width: 240, - ), - radius: 6, - ); - })); - }, - )), - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '居中弹出层-底部关闭-修改圆角', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.center, - builder: (context) { - return TDPopupCenterPanel( - closeUnderBottom: true, - closeClick: () { - Navigator.maybePop(context); - }, - child: const SizedBox( - height: 240, - width: 240, - ), - radius: 6, - ); - })); - }, - )), ], ); }), @@ -255,15 +226,15 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - var renderBox = navBarkey.currentContext!.findRenderObject() as RenderBox; + var renderBox = + navBarkey.currentContext!.findRenderObject() as RenderBox; Navigator.of(context).push( TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, slideTransitionFrom: SlideTransitionFrom.right, modalTop: renderBox.size.height, builder: (context) { return Container( - color: Colors.white, + color: TDTheme.of(context).bgColorContainer, width: 280, ); }, @@ -279,26 +250,24 @@ class TDPopupPageState extends State { return Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceAround, + // spacing: 16, children: [ - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '底部弹出层-键盘弹默认遮挡', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, + TDButton( + text: '底部弹出层-键盘弹默认遮挡', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( slideTransitionFrom: SlideTransitionFrom.bottom, builder: (context) { return TDPopupBottomDisplayPanel( title: '标题文字标题文字标题文字标题文字标题文字标题文字标题文字', - closeColor: TDTheme.of(context).errorNormalColor, - closeClick: () { - Navigator.maybePop(context); - }, + closeColor: + TDTheme.of(context).errorNormalColor, + closeClick: () => Navigator.maybePop(context), child: Material( child: SizedBox( height: 100, @@ -308,33 +277,32 @@ class TDPopupPageState extends State { hintText: '请输入文字', maxLength: 10, additionInfo: '最大输入10个字符', - backgroundColor: Colors.white, ), ), ), radius: 6, ); - })); - }, - ), + }), + ); + }, ), - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '底部弹出层-键盘弹出不遮挡', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, + const SizedBox(height: 16), + TDButton( + text: '底部弹出层-键盘弹出不遮挡', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( slideTransitionFrom: SlideTransitionFrom.bottom, focusMove: true, builder: (context) { return TDPopupBottomDisplayPanel( title: '标题文字标题文字标题文字标题文字标题文字标题文字标题文字', - closeColor: TDTheme.of(context).errorNormalColor, + closeColor: + TDTheme.of(context).errorNormalColor, closeClick: () { Navigator.maybePop(context); }, @@ -347,160 +315,148 @@ class TDPopupPageState extends State { hintText: '请输入文字', maxLength: 10, additionInfo: '最大输入10个字符', - backgroundColor: Colors.white, ), ), ), radius: 6, ); - })); - }, - ), + }), + ); + }, ), - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '居中弹出层-键盘弹出不遮挡', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.center, - focusMove: true, - builder: (context) { - return TDPopupCenterPanel( - closeColor: TDTheme.of(context).errorNormalColor, - closeClick: () { - Navigator.maybePop(context); - }, - child: Material( - child: SizedBox( - height: 340, - child: Column( - children: [ - TDInput( - type: TDInputType.normal, - leftLabel: '标签文字1', - hintText: '请输入文字1', - maxLength: 10, - backgroundColor: Colors.white, - ), - TDInput( - type: TDInputType.normal, - leftLabel: '标签文字2', - hintText: '请输入文字2', - maxLength: 10, - backgroundColor: Colors.white, - ), - TDInput( - type: TDInputType.normal, - leftLabel: '标签文字3', - hintText: '请输入文字3', - maxLength: 10, - backgroundColor: Colors.white, - ), - TDInput( - type: TDInputType.normal, - leftLabel: '标签文字4', - hintText: '请输入文字4', - maxLength: 10, - backgroundColor: Colors.white, - ), - TDInput( - type: TDInputType.normal, - leftLabel: '会被键盘遮挡的输入框1', - hintText: '会被键盘遮挡小部分', - maxLength: 10, - backgroundColor: Colors.white, - ), - TDInput( - type: TDInputType.normal, - leftLabel: '会被键盘遮挡的输入框2', - hintText: '会被键盘遮挡全遮挡', - maxLength: 10, - backgroundColor: Colors.white, - ) - ], + const SizedBox(height: 16), + TDButton( + text: '居中弹出层-键盘弹出不遮挡', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.center, + focusMove: true, + builder: (context) { + return TDPopupCenterPanel( + closeColor: + TDTheme.of(context).errorNormalColor, + closeClick: () { + Navigator.maybePop(context); + }, + child: SizedBox( + height: 340, + child: Column( + children: [ + TDInput( + type: TDInputType.normal, + leftLabel: '标签文字1', + hintText: '请输入文字1', + maxLength: 10, ), - ), + TDInput( + type: TDInputType.normal, + leftLabel: '标签文字2', + hintText: '请输入文字2', + maxLength: 10, + ), + TDInput( + type: TDInputType.normal, + leftLabel: '标签文字3', + hintText: '请输入文字3', + maxLength: 10, + ), + TDInput( + type: TDInputType.normal, + leftLabel: '标签文字4', + hintText: '请输入文字4', + maxLength: 10, + ), + TDInput( + type: TDInputType.normal, + leftLabel: '会被键盘遮挡的输入框1', + hintText: '会被键盘遮挡小部分', + maxLength: 10, + ), + TDInput( + type: TDInputType.normal, + leftLabel: '会被键盘遮挡的输入框2', + hintText: '会被键盘遮挡全遮挡', + maxLength: 10, + ) + ], ), - radius: 6, - ); - })); - }, - )) + ), + radius: 6, + ); + }), + ); + }, + ) ], ); }), ExampleItem( + /// todo fix 动画闪烁 desc: '可拖动全屏', builder: (_) { return Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceAround, + // spacing: 16, children: [ - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '可拖动全屏', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return TDPopupBottomDisplayPanel( - title: '标题文字', - draggable: true, - closeColor: TDTheme.of(context).errorNormalColor, - closeClick: () { - Navigator.maybePop(context); - }, - child: Container( - height: 200, - ), + TDButton( + text: '可拖动全屏', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return TDPopupBottomDisplayPanel( + title: '标题文字', + draggable: true, + closeColor: + TDTheme.of(context).errorNormalColor, + closeClick: () { + Navigator.maybePop(context); + }, + child: Container(height: 200), + ); + }), ); - })); - }, - )), - Container( - margin: const EdgeInsets.all(8), - child: TDButton( - text: '可拖动全屏-带标题及操作', - isBlock: true, - theme: TDButtonTheme.primary, - type: TDButtonType.outline, - size: TDButtonSize.large, - onTap: () { - - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return TDPopupBottomConfirmPanel( - title: '标题文字', - draggable: true, - leftClick: () { - Navigator.maybePop(context); - }, - rightClick: () { - TDToast.showText('确定', context: context); - Navigator.maybePop(context); - }, - child: Container( - height: 200, - ), - ); - })); - }, - )), + }, + ), + const SizedBox(height: 16), + TDButton( + text: '可拖动全屏-带标题及操作', + isBlock: true, + theme: TDButtonTheme.primary, + type: TDButtonType.outline, + size: TDButtonSize.large, + onTap: () { + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return TDPopupBottomConfirmPanel( + title: '标题文字', + draggable: true, + leftClick: () { + Navigator.maybePop(context); + }, + rightClick: () { + TDToast.showText('确定', context: context); + Navigator.maybePop(context); + }, + child: Container(height: 200), + ); + }), + ); + }, + ), ]); }, ), @@ -517,21 +473,22 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.top, - open: () { - print('open'); - }, - opened: () { - print('opened'); - }, - builder: (context) { - return Container( - color: Colors.white, - height: 240, - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.top, + open: () { + print('open'); + }, + opened: () { + print('opened'); + }, + builder: (context) { + return Container( + color: TDTheme.of(context).bgColorContainer, + height: 240, + ); + }), + ); }, ); } @@ -545,15 +502,16 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.left, - builder: (context) { - return Container( - color: Colors.white, - width: 280, - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.left, + builder: (context) { + return Container( + color: TDTheme.of(context).bgColorContainer, + width: 280, + ); + }), + ); }, ); } @@ -567,16 +525,21 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.center, - builder: (context) { - return Container( - color: Colors.white, - width: 240, - height: 240, - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.center, + builder: (context) { + return Container( + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorContainer, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusLarge), + ), + width: 240, + height: 240, + ); + }), + ); }, ); } @@ -590,15 +553,16 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return Container( - color: Colors.white, - height: 240, - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return Container( + color: TDTheme.of(context).bgColorContainer, + height: 240, + ); + }), + ); }, ); } @@ -612,15 +576,16 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.right, - builder: (context) { - return Container( - color: Colors.white, - width: 280, - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.right, + builder: (context) { + return Container( + color: TDTheme.of(context).bgColorContainer, + width: 280, + ); + }), + ); }, ); } @@ -634,8 +599,8 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, + Navigator.of(context).push( + TDSlidePopupRoute( slideTransitionFrom: SlideTransitionFrom.bottom, builder: (context) { return TDPopupBottomConfirmPanel( @@ -647,11 +612,11 @@ class TDPopupPageState extends State { TDToast.showText('确定', context: context); Navigator.maybePop(context); }, - child: Container( - height: 200, - ), + child: Container(height: 200), ); - })); + }, + ), + ); }, ); } @@ -695,20 +660,19 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return TDPopupBottomDisplayPanel( - title: '标题文字', - closeClick: () { - Navigator.maybePop(context); - }, - child: Container( - height: 200, - ), - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return TDPopupBottomDisplayPanel( + title: '标题文字', + closeClick: () { + Navigator.maybePop(context); + }, + child: Container(height: 200), + ); + }), + ); }, ); } @@ -722,21 +686,20 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return TDPopupBottomDisplayPanel( - title: '标题文字', - titleLeft: true, - closeClick: () { - Navigator.maybePop(context); - }, - child: Container( - height: 200, - ), - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return TDPopupBottomDisplayPanel( + title: '标题文字', + titleLeft: true, + closeClick: () { + Navigator.maybePop(context); + }, + child: Container(height: 200), + ); + }), + ); }, ); } @@ -750,19 +713,18 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return TDPopupBottomDisplayPanel( - closeClick: () { - Navigator.maybePop(context); - }, - child: Container( - height: 200, - ), - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return TDPopupBottomDisplayPanel( + closeClick: () { + Navigator.maybePop(context); + }, + child: Container(height: 200), + ); + }), + ); }, ); } @@ -776,21 +738,20 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return TDPopupBottomDisplayPanel( - title: '标题文字', - hideClose: true, - // closeClick: () { - // Navigator.maybePop(context); - // }, - child: Container( - height: 200, - ), - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return TDPopupBottomDisplayPanel( + title: '标题文字', + hideClose: true, + // closeClick: () { + // Navigator.maybePop(context); + // }, + child: Container(height: 200), + ); + }), + ); }, ); } @@ -804,21 +765,19 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - isDismissible: false, - slideTransitionFrom: SlideTransitionFrom.center, - builder: (context) { - return TDPopupCenterPanel( - closeClick: () { - Navigator.maybePop(context); - }, - child: const SizedBox( - width: 240, - height: 240, - ), - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + isDismissible: false, + slideTransitionFrom: SlideTransitionFrom.center, + builder: (context) { + return TDPopupCenterPanel( + closeClick: () { + Navigator.maybePop(context); + }, + child: const SizedBox(width: 240, height: 240), + ); + }), + ); }, ); } @@ -832,22 +791,20 @@ class TDPopupPageState extends State { type: TDButtonType.outline, size: TDButtonSize.large, onTap: () { - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - isDismissible: false, - slideTransitionFrom: SlideTransitionFrom.center, - builder: (context) { - return TDPopupCenterPanel( - closeUnderBottom: true, - closeClick: () { - Navigator.maybePop(context); - }, - child: const SizedBox( - width: 240, - height: 240, - ), - ); - })); + Navigator.of(context).push( + TDSlidePopupRoute( + isDismissible: false, + slideTransitionFrom: SlideTransitionFrom.center, + builder: (context) { + return TDPopupCenterPanel( + closeUnderBottom: true, + closeClick: () { + Navigator.maybePop(context); + }, + child: const SizedBox(width: 240, height: 240), + ); + }), + ); }, ); } diff --git a/tdesign-component/example/lib/page/td_progress_page.dart b/tdesign-component/example/lib/page/td_progress_page.dart index 2737b6e58..50e683ac2 100644 --- a/tdesign-component/example/lib/page/td_progress_page.dart +++ b/tdesign-component/example/lib/page/td_progress_page.dart @@ -9,8 +9,6 @@ import '../base/example_widget.dart'; class TDProgressPage extends StatefulWidget { const TDProgressPage({Key? key}) : super(key: key); - final examplePadding = const EdgeInsets.symmetric(horizontal: 16); - @override State createState() { return _TDProgressPageState(); @@ -26,105 +24,95 @@ class _TDProgressPageState extends State { double microProgressValue = 0.3; Timer? _microTimer; + double value = 0.1; + + bool isPlusOperation = true; + @override Widget build(BuildContext context) { return ExamplePage( - title: tdTitle(), - desc: '用于展示任务当前的进度', - exampleCodeGroup: 'progress', - backgroundColor: TDTheme.of().whiteColor1, - padding: const EdgeInsets.symmetric(vertical: 8), - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem( - desc: '线性进度条', - padding: widget.examplePadding, - builder: _buildRightLabelLinear), - ExampleItem( - desc: '百分比内显', - padding: widget.examplePadding, - builder: _buildInsideLabelLinear), - ExampleItem( - desc: '环形进度条', - padding: widget.examplePadding, - center: false, - builder: _buildCircle), - ExampleItem( - desc: '微型环形进度条', - padding: widget.examplePadding, - center: false, - builder: _buildMicro), - ExampleItem( - desc: '按钮进度条', - padding: widget.examplePadding, - builder: _buildButton), - ExampleItem( - desc: '微型按钮进度条', - padding: widget.examplePadding, - center: false, - builder: _buildMicroButton), - ]), - ExampleModule(title: '组件状态', children: [ - ExampleItem( - desc: '线性进度条', - padding: widget.examplePadding, - builder: _buildPrimary), - ExampleItem(padding: widget.examplePadding, builder: _buildWarning), - ExampleItem(padding: widget.examplePadding, builder: _buildDanger), - ExampleItem(padding: widget.examplePadding, builder: _buildSuccess), - ExampleItem( - desc: '环形进度条', - padding: widget.examplePadding, - center: false, - builder: _buildCirclePrimary), - ExampleItem( - padding: widget.examplePadding, - center: false, - builder: _buildCircleWarning), - ExampleItem( - padding: widget.examplePadding, - center: false, - builder: _buildCircleDanger), - ExampleItem( - padding: widget.examplePadding, - center: false, - builder: _buildCircleSuccess), - ]) - ]); + title: tdTitle(), + desc: '用于展示任务当前的进度', + exampleCodeGroup: 'progress', + padding: const EdgeInsets.all(16), + children: [ + ExampleModule(title: '组件类型', children: [ + ExampleItem(desc: '线性进度条', builder: _buildRightLabelLinear), + ExampleItem(desc: '百分比内显', builder: _buildInsideLabelLinear), + ExampleItem(desc: '环形进度条', builder: _buildCircle), + ExampleItem(desc: '微型环形进度条', builder: _buildMicro), + ExampleItem(desc: '按钮进度条', builder: _buildButton), + ExampleItem(desc: '微型按钮进度条', builder: _buildMicroButton), + ]), + ExampleModule(title: '组件状态', children: [ + ExampleItem(desc: '线性进度条', builder: _buildPrimary), + ExampleItem(builder: _buildWarning), + ExampleItem(builder: _buildDanger), + ExampleItem(builder: _buildSuccess), + ExampleItem(builder: _buildPrimaryInside), + ExampleItem(builder: _buildWarningInside), + ExampleItem(builder: _buildDangerInside), + ExampleItem(builder: _buildSuccessInside), + ExampleItem(desc: '环形进度条', builder: _buildCirclePrimary), + ExampleItem(builder: _buildCircleWarning), + ExampleItem(builder: _buildCircleDanger), + ExampleItem(builder: _buildCircleSuccess), + ]) + ], + floatingActionButton: FloatingActionButton( + child: Icon( + isPlusOperation ? TDIcons.plus : TDIcons.minus, + ), + onPressed: () { + setState(() { + // 加到1时为减,减到0时为加 + value += isPlusOperation ? 0.05 : -0.05; + if (value >= 1) { + isPlusOperation = false; + } + if (value <= 0) { + isPlusOperation = true; + } + }); + }, + ), + ); } @Demo(group: 'progress') Widget _buildRightLabelLinear(BuildContext context) { return TDProgress( - type: TDProgressType.linear, - value: 0.8, - strokeWidth: 6, - progressLabelPosition: TDProgressLabelPosition.right); + type: TDProgressType.linear, + value: value, + strokeWidth: 6, + progressLabelPosition: TDProgressLabelPosition.right, + ); } @Demo(group: 'progress') Widget _buildInsideLabelLinear(BuildContext context) { - return TDProgress(type: TDProgressType.linear, value: 0.8); + return TDProgress(type: TDProgressType.linear, value: value); } @Demo(group: 'progress') Widget _buildCircle(BuildContext context) { - return TDProgress(type: TDProgressType.circular, value: 0.3); + return TDProgress(type: TDProgressType.circular, value: value); } @Demo(group: 'progress') Widget _buildMicro(BuildContext context) { - return TDProgress(type: TDProgressType.micro, value: 0.75); + return TDProgress(type: TDProgressType.micro, value: value); } @Demo(group: 'progress') Widget _buildButton(BuildContext context) { return TDProgress( - type: TDProgressType.button, - onTap: _toggleProgress, - onLongPress: _resetProgress, - value: progressValue, - label: buttonLabel); + type: TDProgressType.button, + onTap: _toggleProgress, + onLongPress: _resetProgress, + value: progressValue, + label: buttonLabel, + ); } @Demo(group: 'progress') @@ -133,82 +121,131 @@ class _TDProgressPageState extends State { type: TDProgressType.micro, value: microProgressValue, onTap: _toggleMicroProgress, - label: TDIconLabel(isPlaying ? Icons.pause : Icons.play_arrow, - color: TDTheme.of(context).brandNormalColor), + label: TDIconLabel( + isPlaying ? Icons.pause : Icons.play_arrow, + color: TDTheme.of(context).brandNormalColor, + ), ); } @Demo(group: 'progress') Widget _buildPrimary(BuildContext context) { return TDProgress( - type: TDProgressType.linear, - progressStatus: TDProgressStatus.primary, - value: 0.8, - strokeWidth: 6, - progressLabelPosition: TDProgressLabelPosition.right); + type: TDProgressType.linear, + progressStatus: TDProgressStatus.primary, + value: value, + strokeWidth: 6, + progressLabelPosition: TDProgressLabelPosition.right, + ); } @Demo(group: 'progress') Widget _buildWarning(BuildContext context) { return TDProgress( - type: TDProgressType.linear, - progressStatus: TDProgressStatus.warning, - value: 0.8, - strokeWidth: 6, - progressLabelPosition: TDProgressLabelPosition.right, + type: TDProgressType.linear, + progressStatus: TDProgressStatus.warning, + value: value, + strokeWidth: 6, + progressLabelPosition: TDProgressLabelPosition.right, ); } @Demo(group: 'progress') Widget _buildDanger(BuildContext context) { return TDProgress( - type: TDProgressType.linear, - progressStatus: TDProgressStatus.danger, - value: 0.8, - strokeWidth: 6, - progressLabelPosition: TDProgressLabelPosition.right); + type: TDProgressType.linear, + progressStatus: TDProgressStatus.danger, + value: value, + strokeWidth: 6, + progressLabelPosition: TDProgressLabelPosition.right, + ); } @Demo(group: 'progress') Widget _buildSuccess(BuildContext context) { return TDProgress( - type: TDProgressType.linear, - progressStatus: TDProgressStatus.success, - value: 0.8, - strokeWidth: 6, - progressLabelPosition: TDProgressLabelPosition.right); + type: TDProgressType.linear, + progressStatus: TDProgressStatus.success, + value: 1, + strokeWidth: 6, + progressLabelPosition: TDProgressLabelPosition.right, + ); + } + + @Demo(group: 'progress') + Widget _buildPrimaryInside(BuildContext context) { + return TDProgress( + type: TDProgressType.linear, + progressStatus: TDProgressStatus.primary, + value: value, + progressLabelPosition: TDProgressLabelPosition.inside, + ); + } + + @Demo(group: 'progress') + Widget _buildWarningInside(BuildContext context) { + return TDProgress( + type: TDProgressType.linear, + progressStatus: TDProgressStatus.warning, + value: value, + progressLabelPosition: TDProgressLabelPosition.inside, + ); + } + + @Demo(group: 'progress') + Widget _buildDangerInside(BuildContext context) { + return TDProgress( + type: TDProgressType.linear, + progressStatus: TDProgressStatus.danger, + value: value, + progressLabelPosition: TDProgressLabelPosition.inside, + ); + } + + @Demo(group: 'progress') + Widget _buildSuccessInside(BuildContext context) { + return TDProgress( + type: TDProgressType.linear, + progressStatus: TDProgressStatus.success, + value: 1, + progressLabelPosition: TDProgressLabelPosition.inside, + ); } @Demo(group: 'progress') Widget _buildCirclePrimary(BuildContext context) { return TDProgress( - type: TDProgressType.circular, - progressStatus: TDProgressStatus.primary, - value: 0.3); + type: TDProgressType.circular, + progressStatus: TDProgressStatus.primary, + value: value, + ); } @Demo(group: 'progress') Widget _buildCircleWarning(BuildContext context) { return TDProgress( - type: TDProgressType.circular, - progressStatus: TDProgressStatus.warning, - value: 0.3); + type: TDProgressType.circular, + progressStatus: TDProgressStatus.warning, + value: value, + ); } @Demo(group: 'progress') Widget _buildCircleDanger(BuildContext context) { return TDProgress( - type: TDProgressType.circular, - progressStatus: TDProgressStatus.danger, - value: 0.3); + type: TDProgressType.circular, + progressStatus: TDProgressStatus.danger, + value: value, + ); } @Demo(group: 'progress') Widget _buildCircleSuccess(BuildContext context) { return TDProgress( - type: TDProgressType.circular, - progressStatus: TDProgressStatus.success, - value: 1); + type: TDProgressType.circular, + progressStatus: TDProgressStatus.success, + value: 1, + ); } void _toggleProgress() { diff --git a/tdesign-component/example/lib/page/td_radio_page.dart b/tdesign-component/example/lib/page/td_radio_page.dart index 24455a2e7..899f4a820 100644 --- a/tdesign-component/example/lib/page/td_radio_page.dart +++ b/tdesign-component/example/lib/page/td_radio_page.dart @@ -27,7 +27,6 @@ class TDRadioPageState extends State { return ExamplePage( title: tdTitle(), exampleCodeGroup: 'radio', - backgroundColor: const Color(0xfff6f6f6), children: [ ExampleModule(title: '组件类型', children: [ ExampleItem(desc: '纵向单选框', builder: _verticalRadios), @@ -50,7 +49,8 @@ class TDRadioPageState extends State { ExampleItem(desc: '横向单选框-显示下划线', builder: _showBottomLine), ExampleItem(desc: '横向单选框-自定义下划线', builder: _customBottomLine), ExampleItem(desc: '横向单选框-自定义颜色和字体尺寸', builder: _customColorAndFont), - ExampleItem(desc: '横向单选框-自定义禁用字体颜色', builder: _customDisableColorAndFont), + ExampleItem( + desc: '横向单选框-自定义禁用字体颜色', builder: _customDisableColorAndFont), ExampleItem(desc: '横向单选框-自定义选框左侧间距', builder: _customRadioLeftSpace), ], ); @@ -65,11 +65,12 @@ class TDRadioPageState extends State { descriptionWidget: TDRadioGroup( selectId: '0', direction: Axis.horizontal, - directionalTdRadios: const [TDRadio( - id: '0', - title: '单选标题0', - showDivider: false, - ), + directionalTdRadios: const [ + TDRadio( + id: '0', + title: '单选标题0', + showDivider: false, + ), TDRadio( id: '1', title: '单选标题1', @@ -434,7 +435,7 @@ class TDRadioPageState extends State { subTitle: '描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息', radioStyle: TDRadioStyle.circle, enable: false, - disableColor: TDTheme.of(context).errorColor1, + disableColor: TDTheme.of(context).errorDisabledColor, titleFont: TDTheme.of(context).fontBodySmall, subTitleFont: TDTheme.of(context).fontBodyExtraSmall, ), @@ -443,7 +444,7 @@ class TDRadioPageState extends State { title: '选项禁用-默认', radioStyle: TDRadioStyle.circle, enable: false, - disableColor: TDTheme.of(context).errorColor1, + disableColor: TDTheme.of(context).errorDisabledColor, titleFont: TDTheme.of(context).fontBodySmall, subTitleFont: TDTheme.of(context).fontBodyExtraSmall, ), @@ -454,15 +455,15 @@ class TDRadioPageState extends State { @Demo(group: '') Widget _customRadioLeftSpace(BuildContext context) { - return TDRadio( - id: '0', - title: '选项禁用-已选', - subTitle: '描述信息', - radioStyle: TDRadioStyle.circle, - checkBoxLeftSpace: 0, - disableColor: TDTheme.of(context).errorColor1, - titleFont: TDTheme.of(context).fontBodySmall, - subTitleFont: TDTheme.of(context).fontBodyExtraSmall, + return TDRadio( + id: '0', + title: '选项禁用-已选', + subTitle: '描述信息', + radioStyle: TDRadioStyle.circle, + checkBoxLeftSpace: 0, + disableColor: TDTheme.of(context).errorDisabledColor, + titleFont: TDTheme.of(context).fontBodySmall, + subTitleFont: TDTheme.of(context).fontBodyExtraSmall, ); } } diff --git a/tdesign-component/example/lib/page/td_radius_page.dart b/tdesign-component/example/lib/page/td_radius_page.dart index be9e76197..1673a28ba 100644 --- a/tdesign-component/example/lib/page/td_radius_page.dart +++ b/tdesign-component/example/lib/page/td_radius_page.dart @@ -33,8 +33,9 @@ class TDRadiusPage extends StatelessWidget { width: 100, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).brandNormalColor, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusSmall)), + color: TDTheme.of(context).brandNormalColor, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusSmall), + ), ); } @@ -44,9 +45,9 @@ class TDRadiusPage extends StatelessWidget { width: 100, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).brandNormalColor, - borderRadius: - BorderRadius.circular(TDTheme.of(context).radiusDefault)), + color: TDTheme.of(context).brandNormalColor, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + ), ); } @@ -56,8 +57,9 @@ class TDRadiusPage extends StatelessWidget { width: 100, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).brandNormalColor, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), + color: TDTheme.of(context).brandNormalColor, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge), + ), ); } @@ -67,9 +69,10 @@ class TDRadiusPage extends StatelessWidget { width: 100, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).brandNormalColor, - borderRadius: - BorderRadius.circular(TDTheme.of(context).radiusExtraLarge)), + color: TDTheme.of(context).brandNormalColor, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusExtraLarge), + ), ); } @@ -80,21 +83,22 @@ class TDRadiusPage extends StatelessWidget { width: 100, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).brandNormalColor, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusRound)), + color: TDTheme.of(context).brandNormalColor, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusRound), + ), ); } @Demo(group: 'radius') Widget _buildRadiusCircle(BuildContext context) { - // 圆形与胶囊型一致,如果长款一致即是圆形 + // 圆形与胶囊型一致,如果长宽一致即是圆形 return Container( width: 50, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).brandNormalColor, - borderRadius: - BorderRadius.circular(TDTheme.of(context).radiusCircle)), + color: TDTheme.of(context).brandNormalColor, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusCircle), + ), ); } } diff --git a/tdesign-component/example/lib/page/td_rate_page.dart b/tdesign-component/example/lib/page/td_rate_page.dart index 5984754ab..6f0617e8e 100644 --- a/tdesign-component/example/lib/page/td_rate_page.dart +++ b/tdesign-component/example/lib/page/td_rate_page.dart @@ -28,7 +28,6 @@ class TDRatePageState extends State { title: tdTitle(), desc: '用于对某行为/事物进行打分。', exampleCodeGroup: 'rate', - backgroundColor: TDTheme.of(context).grayColor2, children: [ ExampleModule(title: '组件类型', children: [ ExampleItem(desc: '实心评分', builder: _buildFilledRate), @@ -58,7 +57,8 @@ class TDRatePageState extends State { @Demo(group: 'rate') Widget _buildCusRate(BuildContext context) { - return const TDCell(title: '自定义评分', noteWidget: TDRate(value: 3, icon: [TDIcons.thumb_up])); + return const TDCell( + title: '自定义评分', noteWidget: TDRate(value: 3, icon: [TDIcons.thumb_up])); } @Demo(group: 'rate') @@ -73,21 +73,22 @@ class TDRatePageState extends State { @Demo(group: 'rate') Widget _buildMsgRate(BuildContext context) { - return Column(children: const [ - TDCell(title: '带描述评分', noteWidget: TDRate(value: 3, showText: true, texts: ['1分', '2分', '3分', '4分', '5分'])), - SizedBox(height: 16), + return const TDCellGroup(cells: [ + TDCell( + title: '带描述评分', + noteWidget: TDRate( + value: 3, showText: true, texts: ['1分', '2分', '3分', '4分', '5分'])), TDCell(title: '带描述评分', noteWidget: TDRate(value: 3, showText: true)) ]); } @Demo(group: 'rate') Widget _buildDRate(BuildContext context) { - return Column(children: const [ + return const TDCellGroup(cells: [ TDCell(title: '顶部显示', noteWidget: TDRate(placement: PlacementEnum.top)), - SizedBox(height: 16), TDCell(title: '不显示', noteWidget: TDRate(placement: PlacementEnum.none)), - SizedBox(height: 16), - TDCell(title: '底部显示', noteWidget: TDRate(placement: PlacementEnum.bottom)), + TDCell( + title: '底部显示', noteWidget: TDRate(placement: PlacementEnum.bottom)), ]); } @@ -98,21 +99,26 @@ class TDRatePageState extends State { @Demo(group: 'rate') Widget _buildHalfRate(BuildContext context) { - return const TDCell(title: '点击活滑动', noteWidget: TDRate(value: 3, allowHalf: true, onChange: print,)); + return const TDCell( + title: '点击活滑动', + noteWidget: TDRate( + value: 3, + allowHalf: true, + onChange: print, + )); } @Demo(group: 'rate') Widget _buildSizeRate(BuildContext context) { - return Column(children: const [ + return const TDCellGroup(cells: [ TDCell(title: '默认尺寸24', noteWidget: TDRate(value: 3)), - SizedBox(height: 16), TDCell(title: '小尺寸20', noteWidget: TDRate(value: 3, size: 20)), ]); } @Demo(group: 'rate') Widget _buildColorRate(BuildContext context) { - return Column(children: const [ + return const TDCellGroup(cells: [ TDCell( title: '填充评分', noteWidget: TDRate( @@ -120,8 +126,10 @@ class TDRatePageState extends State { allowHalf: true, color: [Color(0xFFFFC51C), Color(0xFFE8E8E8)], )), - SizedBox(height: 16), - TDCell(title: '线描评分', noteWidget: TDRate(value: 2.5, allowHalf: true, color: [Color(0xFF00A870)])), + TDCell( + title: '线描评分', + noteWidget: + TDRate(value: 2.5, allowHalf: true, color: [Color(0xFF00A870)])), ]); } @@ -132,30 +140,29 @@ class TDRatePageState extends State { width: double.infinity, child: Center( child: TDRate( - value: 2, - size: 30, - showText: true, - // texts: ['非常糟糕', '有些糟糕', '可以尝试', '可以前往', '推荐前往'], - direction: Axis.vertical, - // mainAxisAlignment: MainAxisAlignment.center, - // textWidth: 64, - builderText: (context, value) { - return value == 0 - ? const SizedBox.shrink() - : Padding( - padding: EdgeInsets.only(top: TDTheme.of(context).spacer8), - child: TDText( - texts[(value - 1).toInt()], - font: TDTheme.of(context).fontTitleMedium, - textColor: TDTheme.of(context).warningColor5, - ), - ); - }, - ), + value: 2, + size: 30, + showText: true, + // texts: ['非常糟糕', '有些糟糕', '可以尝试', '可以前往', '推荐前往'], + direction: Axis.vertical, + // mainAxisAlignment: MainAxisAlignment.center, + // textWidth: 64, + builderText: (context, value) { + return value == 0 + ? const SizedBox.shrink() + : Padding( + padding: EdgeInsets.only(top: TDTheme.of(context).spacer8), + child: TDText( + texts[(value - 1).toInt()], + font: TDTheme.of(context).fontTitleMedium, + textColor: TDTheme.of(context).warningColor5, + ), + ); + }, + ), ), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - color: Colors.white, + color: TDTheme.of(context).bgColorContainer, ); } } diff --git a/tdesign-component/example/lib/page/td_refresh_page.dart b/tdesign-component/example/lib/page/td_refresh_page.dart index 92c8211f1..5d3853a0a 100644 --- a/tdesign-component/example/lib/page/td_refresh_page.dart +++ b/tdesign-component/example/lib/page/td_refresh_page.dart @@ -39,38 +39,42 @@ class _TdPullDownRefreshPageState extends State { // 下拉样式 header: TDRefreshHeader(), child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), child: Column( + // spacing: 16, children: [ Container( height: 171, alignment: Alignment.center, decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, - borderRadius: BorderRadius.all(Radius.circular(TDTheme.of(context).radiusLarge))), - margin: const EdgeInsets.only(left: 16, right: 16), + color: TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.all( + Radius.circular(TDTheme.of(context).radiusLarge))), child: TDText( PlatformUtil.isWeb ? 'Web暂不支持下拉,请下载安装apk体验' : '拖拽该区域演示 顶部下拉刷新', font: TDTheme.of(context).fontBodyLarge, - textColor: TDTheme.of(context).fontGyColor4, + textColor: TDTheme.of(context).textColorPlaceholder, ), ), + const SizedBox(height: 16), Container( height: 70, alignment: Alignment.center, decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, - borderRadius: BorderRadius.all(Radius.circular(TDTheme.of(context).radiusLarge))), - margin: const EdgeInsets.only(top: 16, left: 16, right: 16), + color: TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.all( + Radius.circular(TDTheme.of(context).radiusLarge))), child: TDText( '下拉刷新次数:${count}', font: TDTheme.of(context).fontBodyLarge, - textColor: TDTheme.of(context).fontGyColor4, + textColor: TDTheme.of(context).textColorPlaceholder, ), ), const SizedBox(height: 500), ], ), - ), + )), // 下拉刷新回调 onRefresh: () { Future.delayed(const Duration(seconds: 2), () { diff --git a/tdesign-component/example/lib/page/td_result_page.dart b/tdesign-component/example/lib/page/td_result_page.dart index 1f43052ad..512a161f4 100644 --- a/tdesign-component/example/lib/page/td_result_page.dart +++ b/tdesign-component/example/lib/page/td_result_page.dart @@ -3,14 +3,9 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; -class TDResultPage extends StatefulWidget { - const TDResultPage({Key? key}) : super(key: key); +class TDResultPage extends StatelessWidget { + const TDResultPage({super.key}); - @override - State createState() => _TDResultPageState(); -} - -class _TDResultPageState extends State { @override Widget build(BuildContext context) { return ExamplePage( @@ -25,8 +20,7 @@ class _TDResultPageState extends State { desc: '带描述的结果', ignoreCode: true, builder: _buildResultWithDescription), - ExampleItem( - desc: '自定义结果', ignoreCode: true, builder: _buildCustomResult), + ExampleItem(desc: '自定义结果', builder: _buildCustomResultContent), ExampleItem( desc: '页面示例', ignoreCode: true, builder: _buildPageExample), ]), @@ -36,60 +30,39 @@ class _TDResultPageState extends State { Widget _buildBasicResult(BuildContext context) { return Column( + // spacing: 32, children: [ - CodeWrapper( - builder: _buildBasicResultSuccess, - ), - const SizedBox(height: 48), - CodeWrapper( - builder: _buildBasicResultError, - ), - const SizedBox(height: 48), - CodeWrapper( - builder: _buildBasicResultWarning, - ), - const SizedBox(height: 48), - CodeWrapper( - builder: _buildBasicResultDefault, - ), + CodeWrapper(builder: _buildBasicResultSuccess), + const SizedBox(height: 32), + CodeWrapper(builder: _buildBasicResultError), + const SizedBox(height: 32), + CodeWrapper(builder: _buildBasicResultWarning), + const SizedBox(height: 32), + CodeWrapper(builder: _buildBasicResultDefault), ], ); } Widget _buildResultWithDescription(BuildContext context) { return Column( + // spacing: 32, children: [ - CodeWrapper( - builder: _buildResultWithDescriptionSuccess, - ), - const SizedBox(height: 48), - CodeWrapper( - builder: _buildResultWithDescriptionError, - ), - const SizedBox(height: 48), - CodeWrapper( - builder: _buildResultWithDescriptionWarning, - ), - const SizedBox(height: 48), - CodeWrapper( - builder: _buildResultWithDescriptionDefault, - ), + CodeWrapper(builder: _buildResultWithDescriptionSuccess), + const SizedBox(height: 32), + CodeWrapper(builder: _buildResultWithDescriptionError), + const SizedBox(height: 32), + CodeWrapper(builder: _buildResultWithDescriptionWarning), + const SizedBox(height: 32), + CodeWrapper(builder: _buildResultWithDescriptionDefault), ], ); } - Widget _buildCustomResult(BuildContext context) { - return CodeWrapper( - builder: _buildCustomResultContent, - ); - } - Widget _buildPageExample(BuildContext context) { return TDButton( - text: '页面示例', + text: '页面示例跳转', theme: TDButtonTheme.primary, size: TDButtonSize.large, - type: TDButtonType.outline, isBlock: true, onTap: () { Navigator.push( @@ -100,8 +73,9 @@ class _TDResultPageState extends State { title: const Text('Result 结果'), ), body: Column( + // spacing: 48, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - const SizedBox(height: 48), const TDResult( title: '成功状态', theme: TDResultTheme.success, @@ -112,11 +86,8 @@ class _TDResultPageState extends State { text: '返回', theme: TDButtonTheme.primary, size: TDButtonSize.large, - type: TDButtonType.outline, isBlock: true, - onTap: () { - Navigator.pop(context); - }, + onTap: () => Navigator.pop(context), ), ], ), diff --git a/tdesign-component/example/lib/page/td_search_bar_page.dart b/tdesign-component/example/lib/page/td_search_bar_page.dart index e5ca9c16d..6825da639 100644 --- a/tdesign-component/example/lib/page/td_search_bar_page.dart +++ b/tdesign-component/example/lib/page/td_search_bar_page.dart @@ -22,7 +22,6 @@ class _TDSearchBarPageState extends State { title: tdTitle(), desc: '用于一组预设数据中的选择。', exampleCodeGroup: 'search', - backgroundColor: TDTheme.of(context).grayColor2, children: [ ExampleModule( title: '组件类型', @@ -46,27 +45,13 @@ class _TDSearchBarPageState extends State { @Demo(group: 'search') Widget _buildDefaultSearchBar(BuildContext context) { - return _buildColumnWidgets( - context, - TDSearchBar( - placeHolder: '搜索预设文案', - onTextChanged: (String text) { - setState(() { - inputText = text; - }); - }, - )); - } - - @Demo(group: 'search') - Widget _buildColumnWidgets(BuildContext context, Widget widget) { - return Column( - children: [ - widget, - const SizedBox( - height: 16, - ), - ], + return TDSearchBar( + placeHolder: '搜索预设文案', + onTextChanged: (String text) { + setState(() { + inputText = text; + }); + }, ); } @@ -82,30 +67,28 @@ class _TDSearchBarPageState extends State { @Demo(group: 'search') Widget _buildSearchBarWithShape(BuildContext context) { return Column( + // spacing: 16, children: [ - _buildColumnWidgets( - context, - TDSearchBar( - placeHolder: '搜索预设文案', - style: TDSearchStyle.square, - onTextChanged: (String text) { - setState(() { - inputText = text; - }); - }, - ), + TDSearchBar( + placeHolder: '搜索预设文案', + // 方形 + style: TDSearchStyle.square, + onTextChanged: (String text) { + setState(() { + inputText = text; + }); + }, ), - _buildColumnWidgets( - context, - TDSearchBar( - placeHolder: '搜索预设文案', - style: TDSearchStyle.round, - onTextChanged: (String text) { - setState(() { - inputText = text; - }); - }, - ), + const SizedBox(height: 16), + TDSearchBar( + placeHolder: '搜索预设文案', + // 圆形 + style: TDSearchStyle.round, + onTextChanged: (String text) { + setState(() { + inputText = text; + }); + }, ), ], ); @@ -127,6 +110,7 @@ class _TDSearchBarPageState extends State { @Demo(group: 'search') Widget _buildSearchBarWithAction(BuildContext context) { return Column( + // spacing: 16, children: [ TDSearchBar( placeHolder: '搜索预设文案', @@ -143,15 +127,11 @@ class _TDSearchBarPageState extends State { }); }, ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 16), Container( padding: const EdgeInsets.only(left: 15), alignment: Alignment.centerLeft, - child: TDText( - '搜索框输入的内容:${searchText ?? ''}', - ), + child: TDText('搜索框输入的内容:${searchText ?? ''}'), ) ], ); diff --git a/tdesign-component/example/lib/page/td_shadows_page.dart b/tdesign-component/example/lib/page/td_shadows_page.dart index 9c31d50e5..5795b429b 100644 --- a/tdesign-component/example/lib/page/td_shadows_page.dart +++ b/tdesign-component/example/lib/page/td_shadows_page.dart @@ -11,7 +11,6 @@ class TDShadowsPage extends StatelessWidget { @override Widget build(BuildContext context) { return ExamplePage( - backgroundColor: TDTheme.of(context).whiteColor1, title: tdTitle(context), exampleCodeGroup: 'shadows', children: [ @@ -29,10 +28,10 @@ class TDShadowsPage extends StatelessWidget { width: 100, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).whiteColor1, - boxShadow: TDTheme.of(context).shadowsBase, - borderRadius: - BorderRadius.circular(TDTheme.of(context).radiusDefault)), + color: TDTheme.of(context).bgColorContainer, + boxShadow: TDTheme.of(context).shadowsBase, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + ), ); } @@ -42,10 +41,10 @@ class TDShadowsPage extends StatelessWidget { width: 100, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).whiteColor1, - boxShadow: TDTheme.of(context).shadowsMiddle, - borderRadius: - BorderRadius.circular(TDTheme.of(context).radiusDefault)), + color: TDTheme.of(context).bgColorContainer, + boxShadow: TDTheme.of(context).shadowsMiddle, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + ), ); } @@ -55,10 +54,10 @@ class TDShadowsPage extends StatelessWidget { width: 100, height: 50, decoration: BoxDecoration( - color: TDTheme.of(context).whiteColor1, - boxShadow: TDTheme.of(context).shadowsTop, - borderRadius: - BorderRadius.circular(TDTheme.of(context).radiusDefault)), + color: TDTheme.of(context).bgColorContainer, + boxShadow: TDTheme.of(context).shadowsTop, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + ), ); } } diff --git a/tdesign-component/example/lib/page/td_skeleton_page.dart b/tdesign-component/example/lib/page/td_skeleton_page.dart index b97f49a32..6fb370d88 100644 --- a/tdesign-component/example/lib/page/td_skeleton_page.dart +++ b/tdesign-component/example/lib/page/td_skeleton_page.dart @@ -1,25 +1,18 @@ import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../annotation/demo.dart'; import '../../base/example_widget.dart'; -class TDSkeletonPage extends StatefulWidget { - const TDSkeletonPage({Key? key}) : super(key: key); +class TDSkeletonPage extends StatelessWidget { + const TDSkeletonPage({super.key}); - @override - State createState() => _TDSkeletonPageState(); -} - -class _TDSkeletonPageState extends State { @override Widget build(BuildContext context) { return ExamplePage( - title: tdTitle(), + title: tdTitle(context), desc: '当网络较慢时,在页面真实数据加载之前,给用户展示出页面的大致结构。', exampleCodeGroup: 'skeleton', - backgroundColor: TDTheme.of(context).whiteColor1, children: [ ExampleModule( title: '类型', @@ -118,13 +111,13 @@ class _TDSkeletonPageState extends State { @Demo(group: 'skeleton') Widget _buildCellSkeleton(BuildContext context) { - var rowColsAvatar = TDSkeleton(theme: TDSkeletonTheme.avatar); - var rowColsImage = TDSkeleton.fromRowCol( + final rowColsAvatar = TDSkeleton(theme: TDSkeletonTheme.avatar); + final rowColsImage = TDSkeleton.fromRowCol( rowCol: TDSkeletonRowCol(objects: const [ - [TDSkeletonRowColObj.rect(width: 48, height: 48, flex: null)] + [TDSkeletonRowColObj.rect(width: 48, height: 48)] ]), ); - var rowColsContent = TDSkeleton.fromRowCol( + final rowColsContent = TDSkeleton.fromRowCol( rowCol: TDSkeletonRowCol( objects: const [ [TDSkeletonRowColObj(), TDSkeletonRowColObj.spacer(flex: 1)], @@ -134,8 +127,10 @@ class _TDSkeletonPageState extends State { ); return Column( + // spacing: 16, children: [ Row( + // spacing: 12, children: [ rowColsAvatar, const SizedBox(width: 12), @@ -144,6 +139,7 @@ class _TDSkeletonPageState extends State { ), const SizedBox(height: 16), Row( + // spacing: 12, children: [ rowColsImage, const SizedBox(width: 12), @@ -157,22 +153,22 @@ class _TDSkeletonPageState extends State { @Demo(group: 'skeleton') Widget _buildGridSkeleton(BuildContext context) { return Row( + // spacing: 16, mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - for (var i = 0; i < 5; i++) - TDSkeleton.fromRowCol( - rowCol: TDSkeletonRowCol(objects: const [ - [TDSkeletonRowColObj.rect(width: 48, height: 48, flex: null)], - [TDSkeletonRowColObj.text(width: 48, flex: null)], - ]), - ), - ], + children: List.generate(5, (index) { + return TDSkeleton.fromRowCol( + rowCol: TDSkeletonRowCol(objects: const [ + [TDSkeletonRowColObj.rect(width: 48, height: 48, flex: null)], + [TDSkeletonRowColObj.text(width: 48, flex: null)], + ]), + ); + }), ); } @Demo(group: 'skeleton') Widget _buildCombineSkeleton(BuildContext context) { - var rowCols = Flexible( + final rowCols = Flexible( child: LayoutBuilder( builder: (context, constraints) => Row(children: [ TDSkeleton.fromRowCol( @@ -180,16 +176,14 @@ class _TDSkeletonPageState extends State { objects: [ [ TDSkeletonRowColObj( - width: constraints.maxWidth*0.96, + width: constraints.maxWidth, height: constraints.maxWidth, flex: null, style: TDSkeletonRowColObjStyle( borderRadius: (context) => TDTheme.of(context).radiusExtraLarge)) ], - [TDSkeletonRowColObj.text( - width: constraints.maxWidth*0.96, - )], + [TDSkeletonRowColObj.text(width: constraints.maxWidth)], const [ TDSkeletonRowColObj.text(), TDSkeletonRowColObj.spacer(flex: 1), @@ -200,9 +194,10 @@ class _TDSkeletonPageState extends State { ]))); return Row( + // spacing: TDTheme.of(context).spacer16, children: [ rowCols, - SizedBox(width: TDTheme.of(context).spacer4), + SizedBox(width: TDTheme.of(context).spacer16), rowCols, ], ); diff --git a/tdesign-component/example/lib/page/td_slider_page.dart b/tdesign-component/example/lib/page/td_slider_page.dart index fa51ff4c4..8040ea498 100644 --- a/tdesign-component/example/lib/page/td_slider_page.dart +++ b/tdesign-component/example/lib/page/td_slider_page.dart @@ -7,17 +7,11 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; -class TDSliderPage extends StatefulWidget { - const TDSliderPage({Key? key}) : super(key: key); - - @override - State createState() => _TDSliderPageState(); -} - class DisplayRangeData { final Position currentPosition; final double currentTapValue; final Offset? tapOffset; + DisplayRangeData({ required this.currentPosition, required this.currentTapValue, @@ -25,6 +19,13 @@ class DisplayRangeData { }); } +class TDSliderPage extends StatefulWidget { + const TDSliderPage({Key? key}) : super(key: key); + + @override + State createState() => _TDSliderPageState(); +} + class _TDSliderPageState extends State { @override Widget build(BuildContext context) { @@ -34,54 +35,69 @@ class _TDSliderPageState extends State { exampleCodeGroup: 'slider', padding: const EdgeInsets.only(top: 8, bottom: 8), children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem(desc: '单游标滑块', builder: _buildSingleHandle), - ExampleItem(desc: '双游标滑块', builder: _buildDoubleHandle), - ExampleItem( - desc: '带数值单游标滑块 ', builder: _buildSingleHandleWithNumber), - ExampleItem( - desc: '带数值双游标滑块', builder: _buildDoubleHandleWithNumber), - ExampleItem(desc: '带刻度单游标滑块', builder: _buildSingleHandleWithScale), - ExampleItem(desc: '带刻度双游标滑块', builder: _buildDoubleHandleWithScale), - ]), - ExampleModule(title: '组件状态', children: [ - ExampleItem(desc: '禁用状态', builder: _buildDisableSingleHandle), - ExampleItem(builder: _buildDisableDoubleHandleWithNumber), - ExampleItem(builder: _buildDisableDoubleHandleWithScale), - ]), - ExampleModule(title: '组件事件', children: [ - ExampleItem(desc: 'onTap', builder: _buildOnTapSingleHandle), - ExampleItem(builder: _buildOnTapDoubleHandle), - ExampleItem( - desc: 'onThumbTextTap', - builder: _buildOnThumbTextTapSingleHandle), - ExampleItem(builder: _buildOnThumbTextTapDoubleHandle), - ]), - ExampleModule(title: '特殊样式', children: [ - ExampleItem( - desc: '胶囊型滑块', builder: _buildCapsuleSingleHandleWithNumber), - ExampleItem(builder: _buildCapsuleDoubleHandle), - ExampleItem(builder: _buildCapsuleSingleHandle), - ExampleItem(builder: _buildCapsuleDoubleHandleWithNumber), - ExampleItem(builder: _buildCapsuleSingleHandleWithScale), - ExampleItem(builder: _buildCapsuleDoubleHandleWithScale), - ExampleItem(desc: '胶囊型滑块', builder: _buildCapsule), - ExampleItem(desc: '自定义盒子样式', builder: _buildCustomDecoration), - ExampleItem(desc: '自定义滑轨颜色', builder: _buildCustomActiveColor), - ]), + ExampleModule( + title: '组件类型', + children: [ + ExampleItem(desc: '单游标滑块', builder: _buildSingleHandle), + ExampleItem(desc: '双游标滑块', builder: _buildDoubleHandle), + ExampleItem( + desc: '带数值单游标滑块 ', builder: _buildSingleHandleWithNumber), + ExampleItem( + desc: '带数值双游标滑块', builder: _buildDoubleHandleWithNumber), + ExampleItem( + desc: '带刻度单游标滑块', builder: _buildSingleHandleWithScale), + ExampleItem( + desc: '带刻度双游标滑块', builder: _buildDoubleHandleWithScale), + ], + ), + ExampleModule( + title: '组件状态', + children: [ + ExampleItem(desc: '禁用状态', builder: _buildDisableSingleHandle), + ExampleItem(builder: _buildDisableDoubleHandleWithNumber), + ExampleItem(builder: _buildDisableDoubleHandleWithScale), + ], + ), + ExampleModule( + title: '组件事件', + children: [ + ExampleItem(desc: 'onTap', builder: _buildOnTapSingleHandle), + ExampleItem(builder: _buildOnTapDoubleHandle), + ExampleItem( + desc: 'onThumbTextTap', + builder: _buildOnThumbTextTapSingleHandle), + ExampleItem(builder: _buildOnThumbTextTapDoubleHandle), + ], + ), + ExampleModule( + title: '特殊样式', + children: [ + ExampleItem( + desc: '胶囊型滑块', builder: _buildCapsuleSingleHandleWithNumber), + ExampleItem(builder: _buildCapsuleDoubleHandle), + ExampleItem(builder: _buildCapsuleSingleHandle), + ExampleItem(builder: _buildCapsuleDoubleHandleWithNumber), + ExampleItem(builder: _buildCapsuleSingleHandleWithScale), + ExampleItem(builder: _buildCapsuleDoubleHandleWithScale), + ExampleItem(desc: '胶囊型滑块 - 禁用状态', builder: _buildCapsule), + ExampleItem(desc: '自定义盒子样式', builder: _buildCustomDecoration), + ExampleItem(desc: '自定义滑轨颜色', builder: _buildCustomActiveColor), + ], + ), ]); } @Demo(group: 'slider') Widget _buildSingleHandle(BuildContext context) { return TDSlider( - sliderThemeData: TDSliderThemeData( - context: context, - min: 0, - max: 100, - ), - value: 10, - onChanged: (value) {}); + sliderThemeData: TDSliderThemeData( + context: context, + min: 0, + max: 100, + ), + value: 10, + onChanged: (value) {}, + ); } @Demo(group: 'slider') @@ -219,6 +235,7 @@ class _TDSliderPageState extends State { mainAxisSize: MainAxisSize.min, children: [ Row( + // spacing: 10, mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Value: ${currentValue.toStringAsFixed(1)}'), @@ -261,11 +278,13 @@ class _TDSliderPageState extends State { return Column( mainAxisSize: MainAxisSize.min, + // spacing: 10, children: [ ValueListenableBuilder( valueListenable: displayRangeDataNotifier, builder: (context, data, child) { return Row( + // spacing: 10, mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Position: ${data.currentPosition}'), @@ -309,8 +328,10 @@ class _TDSliderPageState extends State { builder: (context, setState) { return Column( mainAxisSize: MainAxisSize.min, + // spacing: 10, children: [ Row( + // spacing: 10, mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Value: ${currentValue.toStringAsFixed(1)}'), @@ -320,6 +341,7 @@ class _TDSliderPageState extends State { 'Tap at (${tapOffset!.dx.toStringAsFixed(0)}, ${tapOffset!.dy.toStringAsFixed(0)})'), ], ), + const SizedBox(height: 10), TDSlider( sliderThemeData: TDSliderThemeData( context: context, @@ -357,11 +379,13 @@ class _TDSliderPageState extends State { return Column( mainAxisSize: MainAxisSize.min, + // spacing: 10, children: [ ValueListenableBuilder( valueListenable: displayRangeDataNotifier, builder: (context, data, child) { return Row( + // spacing: 10, mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Position: ${data.currentPosition}'), @@ -378,7 +402,11 @@ class _TDSliderPageState extends State { const SizedBox(height: 10), TDRangeSlider( sliderThemeData: TDSliderThemeData( - context: context, min: 0, max: 100, showThumbValue: true), + context: context, + min: 0, + max: 100, + showThumbValue: true, + ), leftLabel: '0', rightLabel: '100', value: const RangeValues(10, 60), @@ -469,8 +497,8 @@ class _TDSliderPageState extends State { max: 100, scaleFormatter: (value) => value.toInt().toString(), )..updateSliderThemeData((data) => data.copyWith( - activeTickMarkColor: const Color(0xFFE7E7E7), - inactiveTickMarkColor: const Color(0xFFE7E7E7), + // activeTickMarkColor: TDTheme.of(context).componentBorderColor, + // inactiveTickMarkColor: TDTheme.of(context).componentStrokeColor, )), value: 60, onChanged: (value) {}, @@ -480,6 +508,7 @@ class _TDSliderPageState extends State { @Demo(group: 'slider') Widget _buildCapsule(BuildContext context) { return Column( + // spacing: 16, children: [ TDSlider( sliderThemeData: TDSliderThemeData.capsule( @@ -490,12 +519,8 @@ class _TDSliderPageState extends State { scaleFormatter: (value) => value.toInt().toString(), ), value: 40, - // divisions: 5, - onChanged: (value) {}, - ), - const SizedBox( - height: 16, ), + const SizedBox(height: 16), TDRangeSlider( sliderThemeData: TDSliderThemeData.capsule( context: context, @@ -504,12 +529,8 @@ class _TDSliderPageState extends State { scaleFormatter: (value) => value.toInt().toString(), ), value: const RangeValues(20, 60), - // divisions: 5, - onChanged: (value) {}, - ), - const SizedBox( - height: 16, ), + const SizedBox(height: 16), TDSlider( sliderThemeData: TDSliderThemeData.capsule( context: context, @@ -520,12 +541,8 @@ class _TDSliderPageState extends State { leftLabel: '0', rightLabel: '100', value: 40, - // divisions: 5, - onChanged: (value) {}, - ), - const SizedBox( - height: 16, ), + const SizedBox(height: 16), TDRangeSlider( sliderThemeData: TDSliderThemeData.capsule( context: context, @@ -537,12 +554,8 @@ class _TDSliderPageState extends State { value: const RangeValues(20, 60), leftLabel: '0', rightLabel: '100', - // divisions: 5, - onChanged: (value) {}, - ), - const SizedBox( - height: 16, ), + const SizedBox(height: 16), TDSlider( sliderThemeData: TDSliderThemeData.capsule( context: context, @@ -552,16 +565,12 @@ class _TDSliderPageState extends State { max: 100, scaleFormatter: (value) => value.toInt().toString(), )..updateSliderThemeData((data) => data.copyWith( - activeTickMarkColor: const Color(0xFFE7E7E7), - inactiveTickMarkColor: const Color(0xFFE7E7E7), + activeTickMarkColor: TDTheme.of(context).componentStrokeColor, + inactiveTickMarkColor: TDTheme.of(context).componentStrokeColor, )), value: 60, - // divisions: 5, - onChanged: (value) {}, - ), - const SizedBox( - height: 16, ), + const SizedBox(height: 16), TDRangeSlider( sliderThemeData: TDSliderThemeData.capsule( context: context, @@ -571,12 +580,10 @@ class _TDSliderPageState extends State { max: 100, scaleFormatter: (value) => value.toInt().toString(), )..updateSliderThemeData((data) => data.copyWith( - activeTickMarkColor: const Color(0xFFE7E7E7), - inactiveTickMarkColor: const Color(0xFFE7E7E7), + activeTickMarkColor: TDTheme.of(context).bgColorComponentActive, + inactiveTickMarkColor: TDTheme.of(context).bgColorComponent, )), value: const RangeValues(20, 60), - // divisions: 5, - onChanged: (value) {}, ) ], ); @@ -585,6 +592,7 @@ class _TDSliderPageState extends State { @Demo(group: 'slider') Widget _buildCustomDecoration(BuildContext context) { return Column( + // spacing: 16, children: [ TDSlider( sliderThemeData: TDSliderThemeData( @@ -597,9 +605,7 @@ class _TDSliderPageState extends State { // divisions: 5, onChanged: (value) {}, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), TDRangeSlider( sliderThemeData: TDSliderThemeData.capsule( context: context, @@ -626,8 +632,8 @@ class _TDSliderPageState extends State { max: 100, scaleFormatter: (value) => value.toInt().toString(), )..updateSliderThemeData((data) => data.copyWith( - activeTickMarkColor: const Color(0xFFE7E7E7), - inactiveTickMarkColor: const Color(0xFFE7E7E7), + // activeTickMarkColor: TDTheme.of(context).bgColorComponent, + // inactiveTickMarkColor: TDTheme.of(context).bgColorComponent, )), value: const RangeValues(20, 60), onChanged: (value) {}, @@ -637,6 +643,7 @@ class _TDSliderPageState extends State { @Demo(group: 'slider') Widget _buildCustomActiveColor(BuildContext context) { return Column( + // spacing: 16, children: [ TDSlider( sliderThemeData: TDSliderThemeData( @@ -650,9 +657,7 @@ class _TDSliderPageState extends State { // divisions: 5, onChanged: (value) {}, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), TDRangeSlider( sliderThemeData: TDSliderThemeData.capsule( activeTrackColor: Colors.green, diff --git a/tdesign-component/example/lib/page/td_stepper_page.dart b/tdesign-component/example/lib/page/td_stepper_page.dart index 3b1d7f7a3..8e1bd8783 100644 --- a/tdesign-component/example/lib/page/td_stepper_page.dart +++ b/tdesign-component/example/lib/page/td_stepper_page.dart @@ -24,26 +24,25 @@ class _TDStepperPageState extends State { } }, child: ExamplePage( - title: tdTitle(), - desc: '用于数量的增减。', - exampleCodeGroup: 'stepper', - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem(desc: '基础步进器', builder: _buildStepperWithBase), - ]), - ExampleModule(title: '组件状态', children: [ - ExampleItem( - desc: '最大最小状态', builder: _buildStepperWithMaxMinStatus), - ExampleItem(desc: '禁用状态', builder: _buildStepperWithDisableStatus) - ]), - ExampleModule(title: '组件样式', children: [ - ExampleItem(desc: '步进器样式', builder: _buildStepperWithTheme), - ExampleItem(desc: '步进器尺寸', builder: _buildStepperWithSize) - ]), - ], - test: [ - ExampleItem(desc: '自定义stepValue', builder: _customStepperValue), - ], + title: tdTitle(), + desc: '用于数量的增减。', + exampleCodeGroup: 'stepper', + children: [ + ExampleModule(title: '组件类型', children: [ + ExampleItem(desc: '基础步进器', builder: _buildStepperWithBase), + ]), + ExampleModule(title: '组件状态', children: [ + ExampleItem(desc: '最大最小状态', builder: _buildStepperWithMaxMinStatus), + ExampleItem(desc: '禁用状态', builder: _buildStepperWithDisableStatus) + ]), + ExampleModule(title: '组件样式', children: [ + ExampleItem(desc: '步进器样式', builder: _buildStepperWithTheme), + ExampleItem(desc: '步进器尺寸', builder: _buildStepperWithSize) + ]), + ], + test: [ + ExampleItem(desc: '自定义stepValue', builder: _customStepperValue), + ], ), ); } @@ -72,6 +71,14 @@ class _TDStepperPageState extends State { theme: TDStepperTheme.filled, disabled: true, ), + const TDStepper( + theme: TDStepperTheme.outline, + disabled: true, + ), + const TDStepper( + theme: TDStepperTheme.normal, + disabled: true, + ), ]); } @@ -102,7 +109,7 @@ class _TDStepperPageState extends State { return Container( decoration: BoxDecoration( - color: theme.whiteColor1, + color: theme.bgColorContainer, ), child: Padding( padding: const EdgeInsets.all(16), @@ -120,18 +127,24 @@ class _TDStepperPageState extends State { } var controller = TDStepperController()..value = 1; + @Demo(group: 'stepper') Widget _customStepperValue(BuildContext context) { return Container( - color: Colors.white, padding: const EdgeInsets.all(8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - TDStepper(theme: TDStepperTheme.filled, controller: controller,), - TDButton(text: 'value * 2', onTap: (){ - controller.value *= 2; - },) + TDStepper( + theme: TDStepperTheme.filled, + controller: controller, + ), + TDButton( + text: 'value * 2', + onTap: () { + controller.value *= 2; + }, + ) ], ), ); diff --git a/tdesign-component/example/lib/page/td_steps_page.dart b/tdesign-component/example/lib/page/td_steps_page.dart index 046367795..3639f9dc8 100644 --- a/tdesign-component/example/lib/page/td_steps_page.dart +++ b/tdesign-component/example/lib/page/td_steps_page.dart @@ -12,784 +12,681 @@ class TDStepsPage extends StatefulWidget { } class _TDStepsPageState extends State { + EdgeInsets exampleItemPadding = const EdgeInsets.symmetric(horizontal: 32); + @override Widget build(BuildContext context) { return ExamplePage( - backgroundColor: TDTheme.of(context).whiteColor1, title: tdTitle(), exampleCodeGroup: 'steps', - desc: 'Steps步骤条', + desc: '用于任务步骤展示或任务进度展示。', children: [ ExampleModule(title: '水平默认步骤条', children: [ - ExampleItem(desc: '水平默认步骤条1', builder: _buildBasicHSteps1), - ExampleItem(desc: '水平默认步骤条2', builder: _buildBasicHSteps2), - ExampleItem(desc: '水平默认步骤条3', builder: _buildBasicHSteps3), + ExampleItem( + desc: '水平默认步骤条1', + padding: exampleItemPadding, + builder: _buildBasicHSteps1, + ), + ExampleItem( + desc: '水平默认步骤条2', + padding: exampleItemPadding, + builder: _buildBasicHSteps2, + ), + ExampleItem( + desc: '水平默认步骤条3', + padding: exampleItemPadding, + builder: _buildBasicHSteps3, + ), ]), ExampleModule(title: '水平图标步骤条', children: [ - ExampleItem(desc: '水平图标步骤条1', builder: _buildHIconSteps1), - ExampleItem(desc: '水平图标步骤条2', builder: _buildHIconSteps2), - ExampleItem(desc: '水平图标步骤条3', builder: _buildHIconSteps3), + ExampleItem( + desc: '水平图标步骤条1', + padding: exampleItemPadding, + builder: _buildHIconSteps1, + ), + ExampleItem( + desc: '水平图标步骤条2', + padding: exampleItemPadding, + builder: _buildHIconSteps2, + ), + ExampleItem( + desc: '水平图标步骤条3', + padding: exampleItemPadding, + builder: _buildHIconSteps3, + ), ]), ExampleModule(title: '水平简略步骤条', children: [ - ExampleItem(desc: '水平简略步骤条1', builder: _buildSimpleHSteps1), - ExampleItem(desc: '水平简略步骤条2', builder: _buildSimpleHSteps2), - ExampleItem(desc: '水平简略步骤条3', builder: _buildSimpleHSteps3), + ExampleItem( + desc: '水平简略步骤条1', + padding: exampleItemPadding, + builder: _buildSimpleHSteps1, + ), + ExampleItem( + desc: '水平简略步骤条2', + padding: exampleItemPadding, + builder: _buildSimpleHSteps2, + ), + ExampleItem( + desc: '水平简略步骤条3', + padding: exampleItemPadding, + builder: _buildSimpleHSteps3, + ), ]), ExampleModule(title: '水平错误状态步骤条', children: [ - ExampleItem(desc: '水平错误状态基本步骤条', builder: _buildHErrorSteps1), - ExampleItem(desc: '水平错误状态图标步骤条', builder: _buildHErrorSteps2), - ExampleItem(desc: '水平错误状态简略步骤条', builder: _buildHErrorSteps3), + ExampleItem( + desc: '水平错误状态基本步骤条', + padding: exampleItemPadding, + builder: _buildHErrorSteps1, + ), + ExampleItem( + desc: '水平错误状态图标步骤条', + padding: exampleItemPadding, + builder: _buildHErrorSteps2, + ), + ExampleItem( + desc: '水平错误状态简略步骤条', + padding: exampleItemPadding, + builder: _buildHErrorSteps3, + ), ]), ExampleModule(title: '垂直步骤条', children: [ - ExampleItem(desc: '垂直默认步骤条', builder: _buildVBasicSteps), - ExampleItem(desc: '垂直图标步骤条', builder: _buildVIconSteps), - ExampleItem(desc: '垂直简略步骤条', builder: _buildVSimpleSteps), - ExampleItem(desc: '垂直错误状态基本步骤条', builder: _buildVErrorBasicSteps), - ExampleItem(desc: '垂直错误状态图标步骤条', builder: _buildVErrorIconSteps), - ExampleItem(desc: '垂直错误状态简略步骤条', builder: _buildVErrorSimpleSteps), ExampleItem( - desc: '垂直自定义标题基本步骤条', builder: _buildVCustomTitleBaseSteps), + desc: '垂直默认步骤条', + padding: exampleItemPadding, + builder: _buildVBasicSteps, + ), + ExampleItem( + desc: '垂直图标步骤条', + padding: exampleItemPadding, + builder: _buildVIconSteps, + ), + ExampleItem( + desc: '垂直简略步骤条', + padding: exampleItemPadding, + builder: _buildVSimpleSteps, + ), + ExampleItem( + desc: '垂直错误状态基本步骤条', + padding: exampleItemPadding, + builder: _buildVErrorBasicSteps, + ), ExampleItem( - desc: '垂直自定义内容基本步骤条', builder: _buildVCustomContentBaseSteps), + desc: '垂直错误状态图标步骤条', + padding: exampleItemPadding, + builder: _buildVErrorIconSteps, + ), + ExampleItem( + desc: '垂直错误状态简略步骤条', + padding: exampleItemPadding, + builder: _buildVErrorSimpleSteps, + ), + ExampleItem( + desc: '垂直自定义标题基本步骤条', + padding: exampleItemPadding, + builder: _buildVCustomTitleBaseSteps, + ), + ExampleItem( + desc: '垂直自定义内容基本步骤条', + padding: exampleItemPadding, + builder: _buildVCustomContentBaseSteps, + ), ]), - ExampleModule(title: 'Extension步骤条', children: [ + ExampleModule(title: 'Extension 步骤条', children: [ ExampleItem( - desc: 'Read-only Steps 纯展示水平步骤条', builder: _buildHReadOnlySteps), + desc: 'Read-only Steps 纯展示水平步骤条', + padding: exampleItemPadding, + builder: _buildHReadOnlySteps, + ), ExampleItem( - desc: 'Read-only Steps 纯展示垂直步骤条', builder: _buildVReadOnlySteps), + desc: 'Read-only Steps 纯展示垂直步骤条', + padding: exampleItemPadding, + builder: _buildVReadOnlySteps, + ), ExampleItem( - desc: 'Vertical Customize Steps 垂直自定义步骤条', - builder: _buildVCustomizeSteps), + desc: 'Vertical Customize Steps 垂直自定义步骤条', + padding: exampleItemPadding, + builder: _buildVCustomizeSteps, + ), ]), ], ); } - List basicHStepsListData1 = [ - TDStepsItemData(title: 'Steps1', content: 'Content1'), - TDStepsItemData(title: 'Steps2', content: 'Content2'), - ]; - /// 基本步骤1 @Demo(group: 'steps') Widget _buildBasicHSteps1(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: basicHStepsListData1, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Steps1', content: 'Content1'), + TDStepsItemData(title: 'Steps2', content: 'Content2'), + ], ); } - List basicHStepsListData2 = [ - TDStepsItemData(title: 'Steps1', content: 'Content1'), - TDStepsItemData(title: 'Steps2', content: 'Content2'), - TDStepsItemData(title: 'Steps3', content: 'Content3'), - ]; - /// 基本步骤2 @Demo(group: 'steps') Widget _buildBasicHSteps2(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: basicHStepsListData2, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Steps1', content: 'Content1'), + TDStepsItemData(title: 'Steps2', content: 'Content2'), + TDStepsItemData(title: 'Steps3', content: 'Content3'), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, ); } - List basicHStepsListData3 = [ - TDStepsItemData(title: 'Steps1', content: 'Content1'), - TDStepsItemData(title: 'Steps2', content: 'Content2'), - TDStepsItemData(title: 'Steps3', content: 'Content3'), - TDStepsItemData(title: 'Steps4', content: 'Content4'), - ]; - List basicStepsListData4 = [ - TDStepsItemData( - title: 'Steps1', content: 'Content1', successIcon: TDIcons.call), - TDStepsItemData(title: 'Steps2', content: 'Content2'), - TDStepsItemData( - title: 'Steps3', content: 'Content3', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps4', content: 'Content4', successIcon: TDIcons.call), - ]; - /// 基本步骤3 @Demo(group: 'steps') Widget _buildBasicHSteps3(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: basicHStepsListData3, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Steps1', content: 'Content1'), + TDStepsItemData(title: 'Steps2', content: 'Content2'), + TDStepsItemData(title: 'Steps3', content: 'Content3'), + TDStepsItemData(title: 'Steps4', content: 'Content4'), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, ); } - List hIconStepsListData1 = [ - TDStepsItemData( - title: 'Steps1', content: 'Content1', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps2', content: 'Content2', successIcon: TDIcons.call), - ]; - /// 水平图标步骤条1 @Demo(group: 'steps') Widget _buildHIconSteps1(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: hIconStepsListData1, - direction: TDStepsDirection.horizontal, - activeIndex: 0, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Steps1', + content: 'Content1', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Steps2', + content: 'Content2', + successIcon: TDIcons.cart, + ), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 0, ); } - List hIconStepsListData2 = [ - TDStepsItemData( - title: 'Steps1', content: 'Content1', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps2', content: 'Content2', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps3', content: 'Content3', successIcon: TDIcons.call), - ]; - - /// 水平图标步骤条1 + /// 水平图标步骤条2 @Demo(group: 'steps') Widget _buildHIconSteps2(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: hIconStepsListData2, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Steps1', + content: 'Content1', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Steps2', + content: 'Content2', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Steps3', + content: 'Content3', + successIcon: TDIcons.cart, + ), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, ); } - List hIconStepsListData3 = [ - TDStepsItemData( - title: 'Steps1', content: 'Content1', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps2', content: 'Content2', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps3', content: 'Content3', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps4', content: 'Content4', successIcon: TDIcons.call), - ]; - - /// 水平图标步骤条1 + /// 水平图标步骤条3 @Demo(group: 'steps') Widget _buildHIconSteps3(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: hIconStepsListData3, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Steps1', + content: 'Content1', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Steps2', + content: 'Content2', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Steps3', + content: 'Content3', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Steps4', + content: 'Content4', + successIcon: TDIcons.cart, + ), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, ); } - List simpleHStepsListData1 = [ - TDStepsItemData(title: 'Steps1', content: 'Content1'), - TDStepsItemData(title: 'Steps2', content: 'Content2'), - ]; - /// 水平简略步骤条1 @Demo(group: 'steps') Widget _buildSimpleHSteps1(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: simpleHStepsListData1, - direction: TDStepsDirection.horizontal, - activeIndex: 0, - simple: true, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Steps1', content: 'Content1'), + TDStepsItemData(title: 'Steps2', content: 'Content2'), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 0, + // 简略模式 + simple: true, ); } - List simpleHStepsListData2 = [ - TDStepsItemData(title: 'Steps1', content: 'Content1'), - TDStepsItemData(title: 'Steps2', content: 'Content2'), - TDStepsItemData(title: 'Steps3', content: 'Content3'), - ]; - /// 水平简略步骤条2 @Demo(group: 'steps') Widget _buildSimpleHSteps2(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: simpleHStepsListData2, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - simple: true, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Steps1', content: 'Content1'), + TDStepsItemData(title: 'Steps2', content: 'Content2'), + TDStepsItemData(title: 'Steps3', content: 'Content3'), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, + // 简略模式 + simple: true, ); } - List simpleHStepsListData3 = [ - TDStepsItemData(title: 'Steps1', content: 'Content1'), - TDStepsItemData(title: 'Steps2', content: 'Content2'), - TDStepsItemData(title: 'Steps3', content: 'Content3'), - TDStepsItemData(title: 'Steps4', content: 'Content4'), - ]; - /// 水平简略步骤条3 @Demo(group: 'steps') Widget _buildSimpleHSteps3(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: simpleHStepsListData3, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - simple: true, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Steps1', content: 'Content1'), + TDStepsItemData(title: 'Steps2', content: 'Content2'), + TDStepsItemData(title: 'Steps3', content: 'Content3'), + TDStepsItemData(title: 'Steps4', content: 'Content4'), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, + // 简略模式 + simple: true, ); } - List hErrorStepsListData1 = [ - TDStepsItemData(title: 'Steps1', content: 'Content1'), - TDStepsItemData(title: 'Error', content: 'Content2'), - TDStepsItemData(title: 'Steps3', content: 'Content3'), - TDStepsItemData(title: 'Steps4', content: 'Content4'), - ]; - - /// 水平简略步骤条3 + /// 水平错误状态基本步骤条 @Demo(group: 'steps') Widget _buildHErrorSteps1(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: hErrorStepsListData1, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - status: TDStepsStatus.error, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Steps1', content: 'Content1'), + TDStepsItemData(title: 'Error', content: 'Content2'), + TDStepsItemData(title: 'Steps3', content: 'Content3'), + TDStepsItemData(title: 'Steps4', content: 'Content4'), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, + // 错误状态 + status: TDStepsStatus.error, ); } - List hErrorStepsListData2 = [ - TDStepsItemData( - title: 'Steps1', content: 'Content1', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Error', - content: 'Content2', - successIcon: TDIcons.call, - errorIcon: TDIcons.close_circle), - TDStepsItemData( - title: 'Steps3', content: 'Content3', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps4', content: 'Content4', successIcon: TDIcons.call), - ]; - - /// 水平简略步骤条3 + /// 水平错误状态图标步骤条 @Demo(group: 'steps') Widget _buildHErrorSteps2(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: hErrorStepsListData2, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - status: TDStepsStatus.error, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Steps1', + content: 'Content1', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Error', + content: 'Content2', + successIcon: TDIcons.cart, + errorIcon: TDIcons.close_circle, + ), + TDStepsItemData( + title: 'Steps3', + content: 'Content3', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Steps4', + content: 'Content4', + successIcon: TDIcons.cart, + ), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, + // 错误状态 + status: TDStepsStatus.error, ); } - List hErrorStepsListData3 = [ - TDStepsItemData( - title: 'Steps1', content: 'Content1', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Error', - content: 'Content2', - successIcon: TDIcons.call, - errorIcon: TDIcons.close_circle), - TDStepsItemData( - title: 'Steps3', content: 'Content3', successIcon: TDIcons.call), - TDStepsItemData( - title: 'Steps4', content: 'Content4', successIcon: TDIcons.call), - ]; - - /// 水平简略步骤条3 + /// 水平错误状态简略步骤条 @Demo(group: 'steps') Widget _buildHErrorSteps3(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: hErrorStepsListData3, - direction: TDStepsDirection.horizontal, - activeIndex: 1, - status: TDStepsStatus.error, - simple: true, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Steps1', + content: 'Content1', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Error', + content: 'Content2', + successIcon: TDIcons.cart, + errorIcon: TDIcons.close_circle, + ), + TDStepsItemData( + title: 'Steps3', + content: 'Content3', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Steps4', + content: 'Content4', + successIcon: TDIcons.cart, + ), + ], + // 水平方向 + direction: TDStepsDirection.horizontal, + activeIndex: 1, + // 错误状态 + status: TDStepsStatus.error, + // 简略模式 + simple: true, ); } - List vBasicStepsListData = [ - TDStepsItemData(title: 'Filish', content: 'Customize content'), - TDStepsItemData(title: 'Process', content: 'Customize content'), - TDStepsItemData(title: 'Default', content: 'Customize content'), - TDStepsItemData(title: 'Default', content: 'Customize content'), - ]; - /// 垂直默认步骤条 @Demo(group: 'steps') Widget _buildVBasicSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vBasicStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 1, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Finish', content: 'Customize content'), + TDStepsItemData(title: 'Process', content: 'Customize content'), + TDStepsItemData(title: 'Default', content: 'Customize content'), + TDStepsItemData(title: 'Default', content: 'Customize content'), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 1, ); } - List vIconStepsListData = [ - TDStepsItemData( - title: 'Filish', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Process', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Default', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Default', - content: 'Customize content', - successIcon: TDIcons.cart), - ]; - /// 垂直图标步骤条 @Demo(group: 'steps') Widget _buildVIconSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vIconStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 1, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Finish', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Process', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Default', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Default', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 1, ); } - List vSimpleStepsListData = [ - TDStepsItemData( - title: 'Filish', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Process', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Default', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Default', - content: 'Customize content', - successIcon: TDIcons.cart), - ]; - /// 垂直简略步骤条 @Demo(group: 'steps') Widget _buildVSimpleSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vSimpleStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 1, - simple: true, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Finish', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Process', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Default', + content: 'Customize content', + successIcon: TDIcons.cart), + TDStepsItemData( + title: 'Default', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 1, + // 简略模式 + simple: true, ); } - List vErrorBasicStepsListData = [ - TDStepsItemData(title: 'Filish', content: 'Customize content'), - TDStepsItemData(title: 'Process', content: 'Customize content'), - TDStepsItemData(title: 'Default', content: 'Customize content'), - TDStepsItemData(title: 'Default', content: 'Customize content'), - ]; - /// 垂直错误状态基本步骤条 @Demo(group: 'steps') Widget _buildVErrorBasicSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vErrorBasicStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 1, - status: TDStepsStatus.error, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Finish', content: 'Customize content'), + TDStepsItemData(title: 'Process', content: 'Customize content'), + TDStepsItemData(title: 'Default', content: 'Customize content'), + TDStepsItemData(title: 'Default', content: 'Customize content'), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 1, + // 错误状态 + status: TDStepsStatus.error, ); } - List vErrorIconStepsListData = [ - TDStepsItemData( - title: 'Filish', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Process', - content: 'Customize content', - successIcon: TDIcons.cart, - errorIcon: TDIcons.close_circle), - TDStepsItemData( - title: 'Default', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Default', - content: 'Customize content', - successIcon: TDIcons.cart), - ]; - /// 垂直错误状态图标步骤条 @Demo(group: 'steps') Widget _buildVErrorIconSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vErrorIconStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 1, - status: TDStepsStatus.error, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Finish', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Process', + content: 'Customize content', + successIcon: TDIcons.cart, + errorIcon: TDIcons.close_circle, + ), + TDStepsItemData( + title: 'Default', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Default', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 1, + // 错误状态 + status: TDStepsStatus.error, ); } - List vErrorSimpleStepsListData = [ - TDStepsItemData( - title: 'Filish', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Process', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Default', - content: 'Customize content', - successIcon: TDIcons.cart), - TDStepsItemData( - title: 'Default', - content: 'Customize content', - successIcon: TDIcons.cart), - ]; - - /// 垂直错误状态图标步骤条 + /// 垂直错误状态简略步骤条 @Demo(group: 'steps') Widget _buildVErrorSimpleSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vErrorSimpleStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 1, - simple: true, - status: TDStepsStatus.error, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData( + title: 'Finish', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Process', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Default', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + TDStepsItemData( + title: 'Default', + content: 'Customize content', + successIcon: TDIcons.cart, + ), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 1, + // 简略模式 + simple: true, + // 错误状态 + status: TDStepsStatus.error, ); } - List vCustomTitleBasicStepsListData = [ - TDStepsItemData(title: 'Filish', content: 'Customize content'), - TDStepsItemData( - title: 'Process', - content: 'Customize content', - customTitle: Container( - margin: const EdgeInsets.only(bottom: 16, top: 4), - child: const Text( + /// 垂直自定义标题基本步骤条 + @Demo(group: 'steps') + Widget _buildVCustomTitleBaseSteps(BuildContext context) { + return TDSteps( + steps: [ + TDStepsItemData(title: 'Finish', content: 'Customize content'), + TDStepsItemData( + title: 'Process', + content: 'Customize content', + customTitle: const TDText( '这是一个很长很长的自定义标题,可以自动换行的一个标题内容', softWrap: true, maxLines: 2, overflow: TextOverflow.visible, ), - )), - TDStepsItemData(title: 'Default', content: 'Customize content'), - TDStepsItemData(title: 'Default', content: 'Customize content'), - ]; - - List vCustomContentBasicStepsListData = [ - TDStepsItemData(title: 'Filish', content: 'Customize content'), - TDStepsItemData( - title: '这是一个很长很长很长很长的文字,他是用来展示这个步骤的标题', - content: 'Customize content', - customContent: Container( - margin: const EdgeInsets.only(bottom: 16, top: 4), - child: ClipRRect( - borderRadius: BorderRadius.circular(6), - child: const TDImage( - assetUrl: 'assets/img/image.png', - type: TDImageType.square, - ), - ), - )), - TDStepsItemData(title: 'Default', content: 'Customize content'), - TDStepsItemData(title: 'Default', content: 'Customize content'), - ]; - - /// 垂直自定义标题基本步骤条 - @Demo(group: 'steps') - Widget _buildVCustomTitleBaseSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vCustomTitleBasicStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 1, - ), - ) - ], - ), + ), + TDStepsItemData(title: 'Default', content: 'Customize content'), + TDStepsItemData(title: 'Default', content: 'Customize content'), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 1, ); } /// 垂直自定义内容基本步骤条 @Demo(group: 'steps') Widget _buildVCustomContentBaseSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vCustomContentBasicStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 1, + return TDSteps( + steps: [ + TDStepsItemData(title: 'Finish', content: 'Customize content'), + TDStepsItemData( + title: '这是一个很长很长很长很长的文字,他是用来展示这个步骤的标题', + content: 'Customize content', + customContent: Container( + margin: const EdgeInsets.only(bottom: 16, top: 4), + child: const TDImage( + assetUrl: 'assets/img/image.png', + type: TDImageType.roundedSquare, ), - ) - ], - ), + ), + ), + TDStepsItemData(title: 'Default', content: 'Customize content'), + TDStepsItemData(title: 'Default', content: 'Customize content'), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 1, ); } - List hReadOnlyStepsListData = [ - TDStepsItemData(title: 'Filish', content: 'content'), - TDStepsItemData(title: 'Process', content: 'content'), - TDStepsItemData(title: 'Default', content: 'content'), - TDStepsItemData(title: 'Default', content: 'content'), - ]; - - /// 水平自定义内容基本步骤条 + /// Read-only Steps 纯展示水平步骤条 @Demo(group: 'steps') Widget _buildHReadOnlySteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: hReadOnlyStepsListData, - readOnly: true, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Finish', content: 'content'), + TDStepsItemData(title: 'Process', content: 'content'), + TDStepsItemData(title: 'Default', content: 'content'), + TDStepsItemData(title: 'Default', content: 'content'), + ], + // 只读模式 + readOnly: true, ); } - List vReadOnlyStepsListData = [ - TDStepsItemData(title: 'Filish', content: 'Customize content'), - TDStepsItemData(title: 'Process', content: 'Customize content'), - TDStepsItemData(title: 'Default', content: 'Customize content'), - TDStepsItemData(title: 'Default', content: 'Customize content'), - ]; - - /// 垂直自定义内容基本步骤条 + /// Read-only Steps 纯展示垂直步骤条 @Demo(group: 'steps') Widget _buildVReadOnlySteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vReadOnlyStepsListData, - direction: TDStepsDirection.vertical, - activeIndex: 0, - readOnly: true, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Finish', content: 'Customize content'), + TDStepsItemData(title: 'Process', content: 'Customize content'), + TDStepsItemData(title: 'Default', content: 'Customize content'), + TDStepsItemData(title: 'Default', content: 'Customize content'), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + activeIndex: 0, + // 只读模式 + readOnly: true, ); } - List vCustomizeStepsListData = [ - TDStepsItemData(title: 'Selected', content: ''), - TDStepsItemData(title: 'Selected', content: ''), - TDStepsItemData(title: 'Selected', content: ''), - TDStepsItemData(title: 'Please Selected', content: ''), - ]; - /// Vertical Customize Steps 垂直自定义步骤条 @Demo(group: 'steps') Widget _buildVCustomizeSteps(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - children: [ - Expanded( - flex: 1, - child: TDSteps( - steps: vCustomizeStepsListData, - direction: TDStepsDirection.vertical, - simple: true, - activeIndex: 3, - verticalSelect: true, - ), - ) - ], - ), + return TDSteps( + steps: [ + TDStepsItemData(title: 'Selected'), + TDStepsItemData(title: 'Selected'), + TDStepsItemData(title: 'Selected'), + TDStepsItemData(title: 'Please Selected'), + ], + // 垂直方向 + direction: TDStepsDirection.vertical, + // 简略模式 + simple: true, + activeIndex: 3, + // 步骤条垂直自定义步骤条选择模式 + verticalSelect: true, ); } } diff --git a/tdesign-component/example/lib/page/td_swipe_cell_page.dart b/tdesign-component/example/lib/page/td_swipe_cell_page.dart index d1811ad3e..e1d0e796e 100644 --- a/tdesign-component/example/lib/page/td_swipe_cell_page.dart +++ b/tdesign-component/example/lib/page/td_swipe_cell_page.dart @@ -11,40 +11,19 @@ class TDSwipeCellPage extends StatelessWidget { Widget build(BuildContext context) { return ExamplePage( title: tdTitle(context), - exampleCodeGroup: 'swipecell', - desc: '用于承载列表中的更多操作,通过左右滑动来展示,按钮的宽度固定高度根据列表高度而变化。', + exampleCodeGroup: 'SwipeCell', + desc: '用于承载列表中的更多操作,通过左右滑动来展示,按钮的宽度固定、高度根据列表高度而变化。', children: [ ExampleModule( title: '组件类型', children: [ - ExampleItem( - desc: '左滑单操作', - builder: _buildSwiperCell, - ), - ExampleItem( - desc: '左滑双操作', - builder: _buildSwiperMuliCell, - ), - ExampleItem( - desc: '左滑三操作', - builder: _buildSwiper3Cell, - ), - ExampleItem( - desc: '右滑单操作', - builder: _buildSwiperRightCell, - ), - ExampleItem( - desc: '左右滑操作', - builder: _buildSwiperRightLeftCell, - ), - ExampleItem( - desc: '带图标的滑动操作', - builder: _buildSwiperIconCell, - ), - ExampleItem( - desc: '带二次确认的操作', - builder: _buildSwiperConfirmCell, - ), + ExampleItem(desc: '左滑单操作', builder: _buildSwiperCell), + ExampleItem(desc: '左滑双操作', builder: _buildSwiperMuliCell), + ExampleItem(desc: '左滑三操作', builder: _buildSwiper3Cell), + ExampleItem(desc: '右滑单操作', builder: _buildSwiperRightCell), + ExampleItem(desc: '左右滑操作', builder: _buildSwiperRightLeftCell), + ExampleItem(desc: '带图标的滑动操作', builder: _buildSwiperIconCell), + ExampleItem(desc: '带二次确认的操作', builder: _buildSwiperConfirmCell), ], ), ], @@ -52,20 +31,30 @@ class TDSwipeCellPage extends StatelessWidget { ); } - @Demo(group: 'swipecell') + @Demo(group: 'SwipeCell') Widget _buildSwiperCell(BuildContext context) { // 屏幕宽度 var screenWidth = MediaQuery.of(context).size.width; var list = [ - {'id': '1', 'title': '左滑操作', 'note': '辅助信息', 'description': ''}, - {'id': '2', 'title': '左滑操作', 'note': '辅助信息', 'description': '一段很长很长的内容文字'}, + {'id': '1', 'title': '左滑单操作', 'note': '辅助信息', 'description': ''}, + { + 'id': '2', + 'title': '左滑单操作', + 'note': '辅助信息', + 'description': '一段很长很长的内容文字' + }, ]; final cellLength = ValueNotifier(list.length); return ValueListenableBuilder( valueListenable: cellLength, builder: (BuildContext context, value, Widget? child) { return TDCellGroup( - cells: list.map((e) => TDCell(title: e['title'], note: e['note'], description: e['description'])).toList(), + cells: list + .map((e) => TDCell( + title: e['title'], + note: e['note'], + description: e['description'])) + .toList(), builder: (context, cell, index) { return TDSwipeCell( slidableKey: ValueKey(list[index]['id']), @@ -83,7 +72,7 @@ class TDSwipeCellPage extends StatelessWidget { }, children: [ TDSwipeCellAction( - backgroundColor: TDTheme.of(context).errorColor6, + backgroundColor: TDTheme.of(context).errorNormalColor, label: '删除', onPressed: (context) { print('点击action'); @@ -103,7 +92,7 @@ class TDSwipeCellPage extends StatelessWidget { ); } - @Demo(group: 'swipecell') + @Demo(group: 'SwipeCell') Widget _buildSwiperMuliCell(BuildContext context) { // 屏幕宽度 var screenWidth = MediaQuery.of(context).size.width; @@ -113,25 +102,20 @@ class TDSwipeCellPage extends StatelessWidget { extentRatio: 120 / screenWidth, children: [ TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).warningColor4, + backgroundColor: TDTheme.of(context).warningNormalColor, label: '编辑', ), TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).errorColor6, + backgroundColor: TDTheme.of(context).errorNormalColor, label: '删除', ), ], ), - cell: const TDCell( - title: '左滑操作', - note: '辅助信息', - ), + cell: const TDCell(title: '左滑双操作', note: '辅助信息'), ); } - @Demo(group: 'swipecell') + @Demo(group: 'SwipeCell') Widget _buildSwiper3Cell(BuildContext context) { // 屏幕宽度 var screenWidth = MediaQuery.of(context).size.width; @@ -141,30 +125,24 @@ class TDSwipeCellPage extends StatelessWidget { extentRatio: 180 / screenWidth, children: [ TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).brandColor7, + backgroundColor: TDTheme.of(context).brandNormalColor, label: '保存', ), TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).warningColor4, + backgroundColor: TDTheme.of(context).warningNormalColor, label: '编辑', ), TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).errorColor6, + backgroundColor: TDTheme.of(context).errorNormalColor, label: '删除', ), ], ), - cell: const TDCell( - title: '左滑操作', - note: '辅助信息', - ), + cell: const TDCell(title: '左滑三操作', note: '辅助信息'), ); } - @Demo(group: 'swipecell') + @Demo(group: 'SwipeCell') Widget _buildSwiperRightCell(BuildContext context) { // 屏幕宽度 var screenWidth = MediaQuery.of(context).size.width; @@ -174,19 +152,16 @@ class TDSwipeCellPage extends StatelessWidget { extentRatio: 60 / screenWidth, children: [ TDSwipeCellAction( - backgroundColor: TDTheme.of(context).brandColor7, + backgroundColor: TDTheme.of(context).brandNormalColor, label: '选择', ), ], ), - cell: const TDCell( - title: '右滑操作', - note: '辅助信息', - ), + cell: const TDCell(title: '右滑操作', note: '辅助信息'), ); } - @Demo(group: 'swipecell') + @Demo(group: 'SwipeCell') Widget _buildSwiperRightLeftCell(BuildContext context) { // 屏幕宽度 var screenWidth = MediaQuery.of(context).size.width; @@ -196,7 +171,7 @@ class TDSwipeCellPage extends StatelessWidget { extentRatio: 60 / screenWidth, children: [ TDSwipeCellAction( - backgroundColor: TDTheme.of(context).brandColor7, + backgroundColor: TDTheme.of(context).brandNormalColor, label: '选择', ), ], @@ -205,149 +180,120 @@ class TDSwipeCellPage extends StatelessWidget { extentRatio: 120 / screenWidth, children: [ TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).warningColor4, + backgroundColor: TDTheme.of(context).warningNormalColor, label: '编辑', ), TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).errorColor6, + backgroundColor: TDTheme.of(context).errorNormalColor, label: '删除', ), ], ), - cell: const TDCell( - title: '左右滑操作', - note: '辅助信息', - ), + cell: const TDCell(title: '左右滑操作', note: '辅助信息'), ); } - @Demo(group: 'swipecell') + @Demo(group: 'SwipeCell') Widget _buildSwiperIconCell(BuildContext context) { // 屏幕宽度 var screenWidth = MediaQuery.of(context).size.width; - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: 3, - itemBuilder: (context, index) { - if (index == 0) { - return TDSwipeCell( - groupTag: 'test', - right: TDSwipeCellPanel( - extentRatio: (80 + 80) / screenWidth, - children: [ - TDSwipeCellAction( - flex: 80, - backgroundColor: TDTheme.of(context).warningColor4, - icon: TDIcons.edit, - label: '编辑', - ), - TDSwipeCellAction( - flex: 80, - backgroundColor: TDTheme.of(context).errorColor6, - icon: TDIcons.delete, - label: '删除', - ), - ], - ), - cell: const TDCell( - title: '左滑操作', - note: '辅助信息', - ), - ); - } else if (index == 1) { - return TDSwipeCell( - groupTag: 'test', - right: TDSwipeCellPanel( - extentRatio: 120 / screenWidth, - children: [ - TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).warningColor4, - icon: TDIcons.edit, - ), - TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).errorColor6, - icon: TDIcons.delete, - ), - ], - ), - cell: const TDCell( - title: '左滑操作', - note: '辅助信息', - ), - ); - } else { - return TDSwipeCell( - groupTag: 'test', - right: TDSwipeCellPanel( - extentRatio: 120 / screenWidth, - children: [ - TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).warningColor4, - direction: Axis.vertical, - icon: TDIcons.edit, - label: '编辑', - ), - TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).errorColor6, - direction: Axis.vertical, - icon: TDIcons.delete, - label: '删除', - ), - ], - ), - cell: const TDCell( - title: '左滑操作', - note: '辅助信息', - description: '一段很长很长的内容文字', - ), - ); - } - }, - separatorBuilder: (context, index) { - return const SizedBox(height: 24); - }, + + return Column( + // spacing: 16, + children: [ + TDSwipeCell( + groupTag: 'test', + right: TDSwipeCellPanel( + extentRatio: 160 / screenWidth, + children: [ + TDSwipeCellAction( + backgroundColor: TDTheme.of(context).warningNormalColor, + icon: TDIcons.edit, + label: '编辑', + ), + TDSwipeCellAction( + backgroundColor: TDTheme.of(context).errorNormalColor, + icon: TDIcons.delete, + label: '删除', + ), + ], + ), + cell: const TDCell(title: '左滑操作', note: '图标+文字(横向)'), + ), + const SizedBox(height: 16), + TDSwipeCell( + groupTag: 'test', + right: TDSwipeCellPanel( + extentRatio: 120 / screenWidth, + children: [ + TDSwipeCellAction( + backgroundColor: TDTheme.of(context).warningNormalColor, + icon: TDIcons.edit, + ), + TDSwipeCellAction( + backgroundColor: TDTheme.of(context).errorNormalColor, + icon: TDIcons.delete, + ), + ], + ), + cell: const TDCell(title: '左滑操作', note: '仅图标'), + ), + const SizedBox(height: 16), + TDSwipeCell( + groupTag: 'test', + right: TDSwipeCellPanel( + extentRatio: 120 / screenWidth, + children: [ + TDSwipeCellAction( + flex: 60, + backgroundColor: TDTheme.of(context).warningNormalColor, + direction: Axis.vertical, + icon: TDIcons.edit, + label: '编辑', + ), + TDSwipeCellAction( + flex: 60, + backgroundColor: TDTheme.of(context).errorNormalColor, + direction: Axis.vertical, + icon: TDIcons.delete, + label: '删除', + ), + ], + ), + cell: const TDCell( + title: '左滑操作', note: '图标+文字(纵向)', description: '一段很长很长的内容文字'), + ) + ], ); } - @Demo(group: 'swipecell') + @Demo(group: 'SwipeCell') Widget _buildSwiperConfirmCell(BuildContext context) { // 屏幕宽度 var screenWidth = MediaQuery.of(context).size.width; return TDSwipeCell( groupTag: 'test', right: TDSwipeCellPanel( - extentRatio: (60 + 60) / screenWidth, + extentRatio: 120 / screenWidth, children: [ TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).warningColor4, + backgroundColor: TDTheme.of(context).warningNormalColor, label: '编辑', ), TDSwipeCellAction( - flex: 60, - backgroundColor: TDTheme.of(context).errorColor6, + backgroundColor: TDTheme.of(context).errorNormalColor, label: '删除', ), ], confirms: [ TDSwipeCellAction( - backgroundColor: TDTheme.of(context).errorColor6, + backgroundColor: TDTheme.of(context).errorNormalColor, label: '确认删除', confirmIndex: const [1], ), ], ), - cell: const TDCell( - title: '左滑操作', - note: '辅助信息', - ), + cell: const TDCell(title: '左滑操作', note: '二次确认'), ); } } diff --git a/tdesign-component/example/lib/page/td_swiper_page.dart b/tdesign-component/example/lib/page/td_swiper_page.dart index a9a2a3b14..3ffc75047 100644 --- a/tdesign-component/example/lib/page/td_swiper_page.dart +++ b/tdesign-component/example/lib/page/td_swiper_page.dart @@ -14,140 +14,148 @@ class TDSwiperPage extends StatelessWidget { title: tdTitle(context), exampleCodeGroup: 'swiper', children: [ - ExampleModule(title: '组件类型', - children: [ - ExampleItem( - desc: '点状(dots)', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildDotsSwiper, - ), - ); - }), - ExampleItem( - desc: '点条状(dots-bar)', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildDotsBarSwiper, - ), - ); - }), - ExampleItem( - desc: '分式(fraction)', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildFractionSwiper, - ), - ); - }), - ExampleItem( - desc: '切换按钮(controls)', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildControlsSwiper, - ), - ); - }), - ExampleItem( - desc: '卡片式(cards)', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildCardsSwiper, - ), - ); - }), - ExampleItem( - desc: '卡片式(cards)-scale:0.8', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildScaleCardsSwiper, - ), - ); - }), + ExampleModule( + title: '组件类型', + children: [ + ExampleItem( + desc: '点状(dots)', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildDotsSwiper, + ), + ); + }), + ExampleItem( + desc: '点条状(dots-bar)', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildDotsBarSwiper, + ), + ); + }), + ExampleItem( + desc: '分式(fraction)', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildFractionSwiper, + ), + ); + }), + ExampleItem( + desc: '切换按钮(controls)', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildControlsSwiper, + ), + ); + }), + ExampleItem( + desc: '卡片式(cards)', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildCardsSwiper, + ), + ); + }), + ExampleItem( + desc: '卡片式(cards)-scale:0.8', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildScaleCardsSwiper, + ), + ); + }), + ], + ), + ExampleModule(title: '组件样式', children: [ + ExampleItem( + desc: '内部', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildDotsSwiper, + ), + ); + }), + ExampleItem( + desc: '外部', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildOuterDotsSwiper, + ), + ); + }), + ExampleItem( + desc: '右边(竖向)', + ignoreCode: true, + builder: (_) { + return Container( + height: 193, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusLarge)), + child: CodeWrapper( + builder: _buildRightDotsSwiper, + ), + ); + }), + ]) ], - ), - ExampleModule(title: '组件样式', children: [ - ExampleItem( - desc: '内部', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildDotsSwiper, - ), - ); - }), - ExampleItem( - desc: '外部', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildOuterDotsSwiper, - ), - ); - }), - ExampleItem( - desc: '右边(竖向)', - ignoreCode: true, - builder: (_) { - return Container( - height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), - child: CodeWrapper( - builder: _buildRightDotsSwiper, - ), - ); - }), - ]) - ], - test: [ - ExampleItem( desc: '卡片式(cards),只有两张不轮播', ignoreCode: true, @@ -155,22 +163,24 @@ class TDSwiperPage extends StatelessWidget { return Container( height: 193, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusLarge)), child: CodeWrapper( builder: _buildNotLoopCardsSwiper, ), ); }), ExampleItem( - // outer样式不支持竖向布局 + // outer样式不支持竖向布局 desc: '点条状outer样式', ignoreCode: true, builder: (_) { return Container( height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), + margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusLarge)), child: CodeWrapper( builder: _buildOuterDotsBarSwiper, ), @@ -182,9 +192,10 @@ class TDSwiperPage extends StatelessWidget { builder: (_) { return Container( height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), + margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusLarge)), child: CodeWrapper( builder: _buildFractionBarSwiper, ), @@ -196,9 +207,10 @@ class TDSwiperPage extends StatelessWidget { builder: (_) { return Container( height: 193, - margin: const EdgeInsets.only(left: 16,right: 16), + margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusLarge)), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusLarge)), child: CodeWrapper( builder: _buildVerticalDotsBarSwiper, ), @@ -215,10 +227,13 @@ class TDSwiperPage extends StatelessWidget { itemCount: 6, loop: true, pagination: const SwiperPagination( - alignment: Alignment.bottomCenter, - builder: TDSwiperPagination.dots), + alignment: Alignment.bottomCenter, + builder: TDSwiperPagination.dots, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -230,10 +245,13 @@ class TDSwiperPage extends StatelessWidget { itemCount: 6, loop: true, pagination: const SwiperPagination( - alignment: Alignment.bottomCenter, - builder: TDSwiperPagination.dotsBar), + alignment: Alignment.bottomCenter, + builder: TDSwiperPagination.dotsBar, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -244,11 +262,15 @@ class TDSwiperPage extends StatelessWidget { autoplay: true, itemCount: 6, loop: true, + scrollDirection: Axis.vertical, pagination: const SwiperPagination( - alignment: Alignment.bottomCenter, - builder: TDSwiperPagination.fraction), + alignment: Alignment.bottomCenter, + builder: TDSwiperPagination.fraction, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -258,12 +280,15 @@ class TDSwiperPage extends StatelessWidget { return Swiper( // autoplay: true, itemCount: 6, - loop: true, + loop: false, pagination: const SwiperPagination( - alignment: Alignment.center, - builder: TDSwiperPagination.controls), + alignment: Alignment.center, + builder: TDSwiperPagination.controls, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -278,10 +303,13 @@ class TDSwiperPage extends StatelessWidget { loop: true, transformer: TDPageTransformer.margin(), pagination: const SwiperPagination( - alignment: Alignment.center, - builder: TDSwiperPagination.dots), + alignment: Alignment.center, + builder: TDSwiperPagination.dots, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -296,10 +324,13 @@ class TDSwiperPage extends StatelessWidget { loop: true, transformer: TDPageTransformer.scaleAndFade(), pagination: const SwiperPagination( - alignment: Alignment.center, - builder: TDSwiperPagination.dots), + alignment: Alignment.center, + builder: TDSwiperPagination.dots, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -312,10 +343,13 @@ class TDSwiperPage extends StatelessWidget { loop: true, outer: true, pagination: const SwiperPagination( - alignment: Alignment.bottomCenter, - builder: TDSwiperPagination.dots), + alignment: Alignment.bottomCenter, + builder: TDSwiperPagination.dots, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -328,10 +362,13 @@ class TDSwiperPage extends StatelessWidget { loop: true, scrollDirection: Axis.vertical, pagination: const SwiperPagination( - alignment: Alignment.centerRight, - builder: TDSwiperPagination.dots), + alignment: Alignment.centerRight, + builder: TDSwiperPagination.dots, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -346,10 +383,13 @@ class TDSwiperPage extends StatelessWidget { itemCount: 2, loop: false, pagination: const SwiperPagination( - alignment: Alignment.center, - builder: TDSwiperPagination.dots), + alignment: Alignment.center, + builder: TDSwiperPagination.dots, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -362,10 +402,13 @@ class TDSwiperPage extends StatelessWidget { itemCount: 6, loop: true, pagination: const SwiperPagination( - alignment: Alignment.topLeft, - builder: TDSwiperPagination.dotsBar), + alignment: Alignment.topLeft, + builder: TDSwiperPagination.dotsBar, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -377,10 +420,13 @@ class TDSwiperPage extends StatelessWidget { itemCount: 6, loop: true, pagination: const SwiperPagination( - alignment: Alignment.bottomRight, - builder: TDSwiperPagination.fraction), + alignment: Alignment.bottomRight, + builder: TDSwiperPagination.fraction, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } @@ -391,14 +437,16 @@ class TDSwiperPage extends StatelessWidget { autoplay: true, itemCount: 6, loop: true, - scrollDirection:Axis.vertical, + scrollDirection: Axis.vertical, pagination: const SwiperPagination( - alignment: Alignment.bottomRight, - builder: TDSwiperPagination.dotsBar), + alignment: Alignment.bottomRight, + builder: TDSwiperPagination.dotsBar, + ), itemBuilder: (BuildContext context, int index) { - return const TDImage(assetUrl: 'assets/img/image.png',); + return const TDImage( + assetUrl: 'assets/img/image.png', + ); }, ); } } - diff --git a/tdesign-component/example/lib/page/td_switch_page.dart b/tdesign-component/example/lib/page/td_switch_page.dart index 5f95a37e0..dcb6b538b 100644 --- a/tdesign-component/example/lib/page/td_switch_page.dart +++ b/tdesign-component/example/lib/page/td_switch_page.dart @@ -53,256 +53,141 @@ class TDSwitchPageState extends State { return current; } - Widget demoRow( - BuildContext context, - String? title, { - String? desc, - bool on = true, - bool enable = true, - Color? trackOnColor, - Color? trackOffColor, - Color? thumbContentOnColor, - Color? thumbContentOffColor, - TDSwitchSize? size, - TDSwitchType? type, - }) { - final theme = TDTheme.of(context); - Widget current = Row( - children: [ - Expanded( - child: TDText( - title, - textColor: theme.fontGyColor1, - )), - TDText( - desc ?? '', - textColor: theme.grayColor6, - ), - SizedBox( - child: _buildSwitch( - on: on, - enable: enable, - trackOnColor: trackOnColor, - trackOffColor: trackOffColor, - thumbContentOnColor: thumbContentOnColor, - thumbContentOffColor: thumbContentOffColor, - size: size, - type: type), - ) - ], - ); - current = Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: SizedBox( - child: Container( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: current, - ), - color: Colors.white, - ), - height: 56, - ), - ); - return current; - } - - /// 每一项的封装 - @Demo(group: 'switch') - Widget _buildItem(BuildContext context, Widget switchItem, - {String? title, String? desc}) { - final theme = TDTheme.of(context); - Widget current = Row( - children: [ - Expanded( - child: TDText( - title ?? '', - textColor: theme.fontGyColor1, - )), - TDText( - desc ?? '', - textColor: theme.grayColor6, - ), - SizedBox(child: switchItem) - ], - ); - current = Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: SizedBox( - child: Container( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: current, - ), - color: Colors.white, - ), - height: 56, - ), - ); - return Column(mainAxisSize: MainAxisSize.min, children: [current]); - } - @Demo(group: 'switch') Widget _buildSwitchWithBase(BuildContext context) { - return _buildItem( - context, - const TDSwitch(), + return const TDCell( title: '基础开关', + noteWidget: TDSwitch(), ); } @Demo(group: 'switch') Widget _buildSwitchWithText(BuildContext context) { - return _buildItem( - context, - const TDSwitch(isOn: true, type: TDSwitchType.text), + return const TDCell( title: '带文字开关', + noteWidget: TDSwitch( + isOn: true, + type: TDSwitchType.text, + ), ); } @Demo(group: 'switch') Widget _buildSwitchWithIcon(BuildContext context) { - return _buildItem( - context, - const TDSwitch(isOn: true, type: TDSwitchType.icon), + return const TDCell( title: '带图标开关', + noteWidget: TDSwitch( + isOn: true, + type: TDSwitchType.icon, + ), ); } @Demo(group: 'switch') Widget _buildSwitchWithColor(BuildContext context) { - return _buildItem( - context, - const TDSwitch(isOn: true, trackOnColor: Colors.green), + return const TDCell( title: '自定义颜色开关', + noteWidget: TDSwitch( + isOn: true, + trackOnColor: Colors.green, + ), ); } @Demo(group: 'switch') Widget _buildSwitchWithLoadingOff(BuildContext context) { - return _buildItem( - context, - const TDSwitch( + return const TDCell( + title: '加载状态', + noteWidget: TDSwitch( isOn: false, type: TDSwitchType.loading, ), - title: '加载状态', ); } @Demo(group: 'switch') Widget _buildSwitchWithLoadingOn(BuildContext context) { - return _buildItem( - context, - const TDSwitch( + return const TDCell( + title: '加载状态', + noteWidget: TDSwitch( isOn: true, type: TDSwitchType.loading, ), - title: '加载状态', ); } @Demo(group: 'switch') Widget _buildSwitchWithDisableOff(BuildContext context) { - return _buildItem( - context, - const TDSwitch( + return const TDCell( + title: '禁用状态', + noteWidget: TDSwitch( enable: false, isOn: false, ), - title: '禁用状态', ); } @Demo(group: 'switch') Widget _buildSwitchWithDisableOn(BuildContext context) { - return _buildItem( - context, - const TDSwitch( + return const TDCell( + title: '禁用状态', + noteWidget: TDSwitch( enable: false, isOn: true, ), - title: '禁用状态', ); } @Demo(group: 'switch') Widget _buildSwitchWithSizeLarge(BuildContext context) { - return _buildItem( - context, - const TDSwitch( - isOn: true, + return const TDCell( + title: '大尺寸32', + noteWidget: TDSwitch( size: TDSwitchSize.large, + isOn: true, ), - title: '大尺寸32', ); } @Demo(group: 'switch') Widget _buildSwitchWithSizeMed(BuildContext context) { - return _buildItem( - context, - const TDSwitch( - isOn: true, + return const TDCell( + title: '中尺寸28', + noteWidget: TDSwitch( size: TDSwitchSize.medium, + isOn: true, ), - title: '中尺寸28', ); } @Demo(group: 'switch') Widget _buildSwitchWithSizeSmall(BuildContext context) { - return _buildItem( - context, - const TDSwitch( - isOn: true, + return const TDCell( + title: '小尺寸24', + noteWidget: TDSwitch( size: TDSwitchSize.small, + isOn: true, ), - title: '小尺寸24', - ); - } - - @Demo(group: 'switch') - Widget _buildSwitch({ - bool on = true, - bool enable = true, - Color? trackOnColor, - Color? trackOffColor, - Color? thumbContentOnColor, - Color? thumbContentOffColor, - TDSwitchSize? size, - TDSwitchType? type, - }) { - return TDSwitch( - isOn: on, - trackOnColor: trackOnColor, - trackOffColor: trackOffColor, - thumbContentOnColor: thumbContentOnColor, - thumbContentOffColor: thumbContentOffColor, - enable: enable, - size: size, - type: type, ); } @Demo(group: 'switch') Widget _customText(BuildContext context) { - return _buildItem( - context, - const TDSwitch( + return const TDCell( + title: '基础开关', + noteWidget: TDSwitch( type: TDSwitchType.text, openText: '1111', closeText: '—', ), - title: '基础开关', ); } @Demo(group: 'switch') Widget _customTextFont(BuildContext context) { - return _buildItem( - context, - const TDSwitch( + return const TDCell( + title: '基础开关', + noteWidget: TDSwitch( type: TDSwitchType.text, openText: '开', closeText: '关', @@ -311,7 +196,6 @@ class TDSwitchPageState extends State { thumbContentOnFont: TextStyle(fontSize: 18), thumbContentOffFont: TextStyle(fontSize: 12), ), - title: '基础开关', ); } } diff --git a/tdesign-component/example/lib/page/td_table_page.dart b/tdesign-component/example/lib/page/td_table_page.dart index 08a1ba6f9..b5a3e4800 100644 --- a/tdesign-component/example/lib/page/td_table_page.dart +++ b/tdesign-component/example/lib/page/td_table_page.dart @@ -30,21 +30,19 @@ class TDTablePage extends StatelessWidget { } List _getData2() { - var data = []; - for (var i = 0; i < 10; i++) { - if (i == 0) { - data.add({ - 'title1': '横向平铺内容不省略', - 'title2': '横向平铺内容不省略', - 'title3': '横向平铺内容不省略', - }); - } else { - data.add({ - 'title1': '内容', - 'title2': '内容', - 'title3': '内容', - }); + var data = [ + { + 'title1': '横向平铺内容不省略', + 'title2': '横向平铺内容不省略', + 'title3': '横向平铺内容不省略', } + ]; + for (var i = 0; i < 10; i++) { + data.add({ + 'title1': '内容', + 'title2': '内容', + 'title3': '内容', + }); } return data; } @@ -53,7 +51,8 @@ class TDTablePage extends StatelessWidget { Widget build(BuildContext context) { return ExamplePage( title: tdTitle(context), - desc: '表格常用于展示同类结构下的多种数据,易于组织、对比和分析等,并可对数据进行搜索、筛选、排序等操作。一般包括表头、数据行和表尾三部分。', + desc: + '表格常用于展示同类结构下的多种数据,易于组织、对比和分析等,并可对数据进行搜索、筛选、排序等操作。一般包括表头、数据行和表尾三部分。', exampleCodeGroup: 'table', children: [ ExampleModule( @@ -62,7 +61,9 @@ class TDTablePage extends StatelessWidget { ExampleItem(desc: '基础表格', builder: _basicTable), ExampleItem(desc: '可排序表格', builder: _sortableTable), ExampleItem(desc: '带操作或按钮表格', builder: _operationBtnTable), - ExampleItem(builder: _operationIconTable, padding: const EdgeInsets.only(top: 16)), + ExampleItem( + builder: _operationIconTable, + padding: const EdgeInsets.only(top: 16)), ExampleItem(desc: '可固定首列表格', builder: _fixedFirstColTable), ExampleItem(desc: '可固定尾列表格', builder: _fixedEndColTable), ExampleItem(desc: '横向平铺可滚动表格', builder: _horizontalScrollTable), @@ -101,7 +102,8 @@ class TDTablePage extends StatelessWidget { Widget _sortableTable(BuildContext context) { return TDTable( columns: [ - TDTableCol(title: '标题', colKey: 'title1', ellipsis: true, sortable: true), + TDTableCol( + title: '标题', colKey: 'title1', ellipsis: true, sortable: true), TDTableCol(title: '标题', colKey: 'title2', sortable: true), TDTableCol(title: '标题', colKey: 'title3', sortable: true), TDTableCol(title: '标题', colKey: 'title4', sortable: true) @@ -127,18 +129,14 @@ class TDTablePage extends StatelessWidget { TDText( '修改', style: TextStyle( - color: TDTheme.of(context).brandNormalColor, - fontSize: 14, - height: 1, - ), + color: TDTheme.of(context).brandNormalColor, + fontSize: 14), ), TDText( '通过', style: TextStyle( - color: TDTheme.of(context).brandNormalColor, - fontSize: 14, - height: 1, - ), + color: TDTheme.of(context).brandNormalColor, + fontSize: 14), ), ], ); @@ -163,8 +161,10 @@ class TDTablePage extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Icon(TDIcons.upload, color: TDTheme.of(context).brandNormalColor, size: 16), - Icon(TDIcons.delete, color: TDTheme.of(context).brandNormalColor, size: 16), + Icon(TDIcons.upload, + color: TDTheme.of(context).brandNormalColor, size: 16), + Icon(TDIcons.delete, + color: TDTheme.of(context).brandNormalColor, size: 16), ], ); }, @@ -322,9 +322,12 @@ class TDTablePage extends StatelessWidget { Widget _centerTable(BuildContext context) { return TDTable( columns: [ - TDTableCol(title: '标题', colKey: 'title1', align: TDTableColAlign.center), - TDTableCol(title: '标题', colKey: 'title2', align: TDTableColAlign.center), - TDTableCol(title: '标题', colKey: 'title3', align: TDTableColAlign.center), + TDTableCol( + title: '标题', colKey: 'title1', align: TDTableColAlign.center), + TDTableCol( + title: '标题', colKey: 'title2', align: TDTableColAlign.center), + TDTableCol( + title: '标题', colKey: 'title3', align: TDTableColAlign.center), TDTableCol(title: '标题', colKey: 'title4', align: TDTableColAlign.center) ], data: _getData(10), @@ -361,11 +364,15 @@ class TDTablePage extends StatelessWidget { return TDTable( data: _getData(10), columns: [ - TDTableCol(selection: true, checked: (index, row) { - return index == 0; - }, width: 50, selectable: (index, row) { - return index % 2 == 0; - }), + TDTableCol( + selection: true, + checked: (index, row) { + return index == 0; + }, + width: 50, + selectable: (index, row) { + return index % 2 == 0; + }), TDTableCol(title: '标题', colKey: 'title1'), TDTableCol(title: '标题', colKey: 'title2'), TDTableCol(title: '标题', colKey: 'title3'), diff --git a/tdesign-component/example/lib/page/td_tabs_page.dart b/tdesign-component/example/lib/page/td_tabs_page.dart index 5cc901368..5f3335cd2 100644 --- a/tdesign-component/example/lib/page/td_tabs_page.dart +++ b/tdesign-component/example/lib/page/td_tabs_page.dart @@ -11,8 +11,7 @@ class TDTabsPage extends StatefulWidget { State createState() => _TDTabsPageState(); } -class _TDTabsPageState extends State - with TickerProviderStateMixin { +class _TDTabsPageState extends State with TickerProviderStateMixin { TabController? _tabController1; TabController? _tabController2; TabController? _tabController3; @@ -22,12 +21,8 @@ class _TDTabsPageState extends State List _getTabs() { tabs = const [ - TDTab( - text: '选项', - ), - TDTab( - text: '选项', - ), + TDTab(text: '选项'), + TDTab(text: '选项'), TDTab(text: '选项'), TDTab(text: '选项'), TDTab(text: '选项'), @@ -53,9 +48,9 @@ class _TDTabsPageState extends State List _getTabViews() { tabViews = const [ - Center(child: TDText('内容区')), - Center(child: TDText('内容区')), - Center(child: TDText('内容区')), + Center(child: TDText('内容区 1')), + Center(child: TDText('内容区 2')), + Center(child: TDText('内容区 3')), ]; return tabViews; } @@ -86,7 +81,7 @@ class _TDTabsPageState extends State return temp; } - //初始化tab + // 初始化tab void _initTabController() { _tabController1 = TabController(length: 2, vsync: this); _tabController2 = TabController(length: 3, vsync: this); @@ -97,39 +92,41 @@ class _TDTabsPageState extends State @override Widget build(BuildContext context) { return ExamplePage( - title: tdTitle(), - desc: '用于内容分类后的展示切换。', - exampleCodeGroup: 'tabs', - children: [ - ExampleModule( - title: '组件类型', - children: [ - ExampleItem(desc: '均分选项卡', builder: _buildItemWithSplit1), - ExampleItem(builder: _buildItemWithSplit2, padding: const EdgeInsets.only(top: 16)), - ExampleItem(builder: _buildItemWithSplit3, padding: const EdgeInsets.only(top: 16)), - ExampleItem(builder: _buildItemWithSplit4, padding: const EdgeInsets.only(top: 16)), - ExampleItem(desc: '等距选项卡', builder: _buildItemWithSpace), - ExampleItem(desc: '带图标选项卡', builder: _buildItemWithIcon), - ExampleItem(desc: '带微标选项卡', builder: _buildItemWithLogo), - ExampleItem(desc: '带内容区选项卡', builder: _buildItemWithContent), - ], - ), - ExampleModule(title: '组件状态', children: [ - ExampleItem(desc: '选项卡状态', builder: _buildItemWithStatus), - ]), - ExampleModule(title: '组件样式', children: [ - ExampleItem(desc: '选项卡尺寸', builder: _buildItemWithSizeSmall), - ExampleItem(builder: _buildItemWithSizeBig, padding: const EdgeInsets.only(top: 16)), - ExampleItem(desc: '选项卡样式', builder: _buildItemWithOutlineNormal), - ExampleItem(builder: _buildItemWithOutlineCard, padding: const EdgeInsets.only(top: 16)), - ]), - ], - test: [ - ExampleItem(desc: '自定义下标属性', builder: _customIndicatorStyle), - ExampleItem(desc: '自定义下划线样式', builder: _customDividerStyle), - ExampleItem(desc: '不展示下划线-高度为0', builder: _hideBottomDivider), - ExampleItem(desc: 'capsule类型可修改背景色', builder: _capsuleBackgroundColor), - ],); + title: tdTitle(), + desc: '用于内容分类后的展示切换。', + exampleCodeGroup: 'tabs', + padding: const EdgeInsets.only(top: 16), + children: [ + ExampleModule( + title: '组件类型', + children: [ + ExampleItem(desc: '均分选项卡', builder: _buildItemWithSplit1), + ExampleItem(builder: _buildItemWithSplit2), + ExampleItem(builder: _buildItemWithSplit3), + ExampleItem(builder: _buildItemWithSplit4), + ExampleItem(desc: '等距选项卡', builder: _buildItemWithSpace), + ExampleItem(desc: '带图标选项卡', builder: _buildItemWithIcon), + ExampleItem(desc: '带微标选项卡', builder: _buildItemWithLogo), + ExampleItem(desc: '带内容区选项卡', builder: _buildItemWithContent), + ], + ), + ExampleModule(title: '组件状态', children: [ + ExampleItem(desc: '选项卡状态', builder: _buildItemWithStatus), + ]), + ExampleModule(title: '组件样式', children: [ + ExampleItem(desc: '选项卡尺寸', builder: _buildItemWithSizeSmall), + ExampleItem(builder: _buildItemWithSizeBig), + ExampleItem(desc: '选项卡样式', builder: _buildItemWithOutlineNormal), + ExampleItem(builder: _buildItemWithOutlineCard), + ]), + ], + test: [ + ExampleItem(desc: '自定义下标属性', builder: _customIndicatorStyle), + ExampleItem(desc: '自定义下划线样式', builder: _customDividerStyle), + ExampleItem(desc: '不展示下划线-高度为0', builder: _hideBottomDivider), + ExampleItem(desc: 'capsule类型可修改背景色', builder: _capsuleBackgroundColor), + ], + ); } @Demo(group: 'tabs') @@ -137,7 +134,6 @@ class _TDTabsPageState extends State return TDTabBar( tabs: subList(2), controller: _tabController1, - backgroundColor: Colors.white, showIndicator: true, ); } @@ -147,7 +143,6 @@ class _TDTabsPageState extends State return TDTabBar( tabs: subList(3), controller: _tabController2, - backgroundColor: Colors.white, showIndicator: true, ); } @@ -157,7 +152,6 @@ class _TDTabsPageState extends State return TDTabBar( tabs: subList(4), controller: _tabController3, - backgroundColor: Colors.white, showIndicator: true, ); } @@ -167,7 +161,6 @@ class _TDTabsPageState extends State return TDTabBar( tabs: subList(5), controller: _tabController4, - backgroundColor: Colors.white, showIndicator: true, ); } @@ -177,7 +170,6 @@ class _TDTabsPageState extends State return TDTabBar( tabs: subList(16), controller: TabController(length: 16, vsync: this), - backgroundColor: Colors.white, labelPadding: const EdgeInsets.all(10), showIndicator: true, isScrollable: true, @@ -186,34 +178,18 @@ class _TDTabsPageState extends State @Demo(group: 'tabs') Widget _buildItemWithIcon(BuildContext context) { - var tabs = [ - const TDTab( - text: '选项', - icon: Icon( - TDIcons.app, - size: 18, - ), - ), - const TDTab( - text: '选项', - icon: Icon( - TDIcons.app, - size: 18, - ), - ), - const TDTab( - text: '选项', - icon: Icon( - TDIcons.app, - size: 18, - ), - ), - ]; + var tabs = List.generate(3, (index) { + final text = '选项${index + 1}'; + return TDTab( + text: text, + icon: const Icon(TDIcons.app, size: 18), + ); + }); return TDTabBar( - tabs: tabs, - controller: TabController(length: 3, vsync: this), - backgroundColor: Colors.white, - showIndicator: true); + tabs: tabs, + controller: TabController(length: tabs.length, vsync: this), + showIndicator: true, + ); } @Demo(group: 'tabs') @@ -229,25 +205,19 @@ class _TDTabsPageState extends State text: '选项', contentHeight: 42, textMargin: EdgeInsets.only(right: 16, top: 2, bottom: 2), - badge: TDBadge( - TDBadgeType.message, - message: '8', - ), + badge: TDBadge(TDBadgeType.message, message: '8'), ), const TDTab( text: '选项', height: 48, - icon: Icon( - TDIcons.app, - size: 18, - ), + icon: Icon(TDIcons.app, size: 18), ), ]; return TDTabBar( - tabs: tabs, - controller: TabController(length: 3, vsync: this), - backgroundColor: Colors.white, - showIndicator: true); + tabs: tabs, + controller: TabController(length: tabs.length, vsync: this), + showIndicator: true, + ); } @Demo(group: 'tabs') @@ -258,14 +228,14 @@ class _TDTabsPageState extends State child: Column( children: [ TDTabBar( - tabs: subList(3), - controller: tabController, - showIndicator: true, - backgroundColor: Colors.white, - isScrollable: false,), + tabs: subList(3), + controller: tabController, + showIndicator: true, + isScrollable: false, + ), Container( height: 120, - color: Colors.white, + color: TDTheme.of(context).bgColorContainer, child: TDTabBarView( children: _getTabViews(), controller: tabController, @@ -279,120 +249,77 @@ class _TDTabsPageState extends State @Demo(group: 'tabs') Widget _buildItemWithStatus(BuildContext context) { var tabs = [ - const TDTab( - text: '选中', - ), - const TDTab( - text: '默认', - ), - const TDTab( - text: '禁用', - enable: false, - ), + const TDTab(text: '选中'), + const TDTab(text: '默认'), + const TDTab(text: '禁用', enable: false), ]; return TDTabBar( - tabs: tabs, - controller: TabController(length: 3, vsync: this), - backgroundColor: Colors.white, - showIndicator: true); + tabs: tabs, + controller: TabController(length: tabs.length, vsync: this), + showIndicator: true, + ); } @Demo(group: 'tabs') Widget _buildItemWithSizeSmall(BuildContext context) { var tabs = [ - const TDTab( - text: '小尺寸', - ), - const TDTab( - text: '选项', - ), - const TDTab( - text: '选项', - ), - const TDTab( - text: '选项', - ), + const TDTab(text: '小尺寸'), + const TDTab(text: '选项2'), + const TDTab(text: '选项3'), + const TDTab(text: '选项4'), ]; return TDTabBar( - tabs: tabs, - controller: TabController(length: 4, vsync: this), - backgroundColor: Colors.white, - showIndicator: true); + tabs: tabs, + controller: TabController(length: tabs.length, vsync: this), + showIndicator: true, + ); } @Demo(group: 'tabs') Widget _buildItemWithSizeBig(BuildContext context) { var tabs = [ - const TDTab( - text: '大尺寸', - size: TDTabSize.large, - ), - const TDTab( - text: '选项', - size: TDTabSize.large, - ), - const TDTab( - text: '选项', - size: TDTabSize.large, - ), - const TDTab( - text: '选项', - size: TDTabSize.large, - ), + const TDTab(text: '大尺寸', size: TDTabSize.large), + const TDTab(text: '选项2', size: TDTabSize.large), + const TDTab(text: '选项3', size: TDTabSize.large), + const TDTab(text: '选项4', size: TDTabSize.large), ]; return TDTabBar( - tabs: tabs, - controller: TabController(length: 4, vsync: this), - backgroundColor: Colors.white, - showIndicator: true); + tabs: tabs, + controller: TabController(length: tabs.length, vsync: this), + showIndicator: true, + ); } @Demo(group: 'tabs') Widget _buildItemWithOutlineNormal(BuildContext context) { var tabs = [ - const TDTab( - text: '选项', - ), - const TDTab( - text: '选项', - ), - const TDTab( - text: '选项', - ), - const TDTab( - text: '选项', - ), + const TDTab(text: '选项1'), + const TDTab(text: '选项2'), + const TDTab(text: '选项3'), + const TDTab(text: '选项4'), ]; return TDTabBar( - tabs: tabs, - outlineType: TDTabBarOutlineType.capsule, - controller: TabController(length: 4, vsync: this), - backgroundColor: Colors.white, - showIndicator: false); + tabs: tabs, + outlineType: TDTabBarOutlineType.capsule, + controller: TabController(length: tabs.length, vsync: this), + showIndicator: false, + ); } @Demo(group: 'tabs') Widget _buildItemWithOutlineCard(BuildContext context) { var tabs = [ - const TDTab( - text: '选项', - ), - const TDTab( - text: '选项', - ), - const TDTab( - text: '选项', - ), - const TDTab( - text: '选项', - ), + const TDTab(text: '选项1'), + const TDTab(text: '选项2'), + const TDTab(text: '选项3'), + const TDTab(text: '选项4'), ]; return TDTabBar( - tabs: tabs, - outlineType: TDTabBarOutlineType.card, - controller: TabController(length: 4, vsync: this), - backgroundColor: Colors.white, - showIndicator: false); + tabs: tabs, + outlineType: TDTabBarOutlineType.card, + controller: TabController(length: tabs.length, vsync: this), + showIndicator: false, + ); } @Demo(group: 'tabs') @@ -400,7 +327,6 @@ class _TDTabsPageState extends State return TDTabBar( tabs: subList(2), controller: _tabController1, - backgroundColor: Colors.white, showIndicator: true, indicatorColor: Colors.red, indicatorHeight: 20, @@ -414,7 +340,6 @@ class _TDTabsPageState extends State return TDTabBar( tabs: subList(2), controller: _tabController1, - backgroundColor: Colors.white, showIndicator: true, dividerColor: Colors.red, dividerHeight: 5, @@ -426,7 +351,6 @@ class _TDTabsPageState extends State return TDTabBar( tabs: subList(2), controller: _tabController1, - backgroundColor: Colors.white, showIndicator: true, dividerColor: Colors.red, dividerHeight: 0, diff --git a/tdesign-component/example/lib/page/td_tag_page.dart b/tdesign-component/example/lib/page/td_tag_page.dart index a0e00620b..ae8e6f374 100644 --- a/tdesign-component/example/lib/page/td_tag_page.dart +++ b/tdesign-component/example/lib/page/td_tag_page.dart @@ -106,7 +106,8 @@ class TDTagPage extends StatelessWidget { return Container( alignment: Alignment.topLeft, padding: const EdgeInsets.only(left: 16), - child: Wrap(spacing: 8, direction: Axis.vertical, children: [ + child: + Wrap(spacing: 8, direction: Axis.vertical, children: [ // 非浅色填充 Row( children: [ @@ -186,7 +187,8 @@ class TDTagPage extends StatelessWidget { return Container( alignment: Alignment.topLeft, padding: const EdgeInsets.only(left: 16), - child: Wrap(spacing: 8, direction: Axis.vertical, children: [ + child: + Wrap(spacing: 8, direction: Axis.vertical, children: [ // 不带关闭 CodeWrapper(builder: _buildAllSizeTags), // 带关闭 @@ -201,9 +203,9 @@ class TDTagPage extends StatelessWidget { desc: '非浅色填充的各主题展示', ignoreCode: true, builder: (context) { - return Wrap( + return const Wrap( spacing: 8, - children: const [ + children: [ TDTag( '标签文字', ), @@ -230,9 +232,9 @@ class TDTagPage extends StatelessWidget { desc: '浅色填充的各主题展示', ignoreCode: true, builder: (context) { - return Wrap( + return const Wrap( spacing: 8, - children: const [ + children: [ TDTag( '标签文字', isLight: true, @@ -264,9 +266,9 @@ class TDTagPage extends StatelessWidget { desc: '非浅色描边的各主题展示', ignoreCode: true, builder: (context) { - return Wrap( + return const Wrap( spacing: 8, - children: const [ + children: [ TDTag( '标签文字', isOutline: true, @@ -298,9 +300,9 @@ class TDTagPage extends StatelessWidget { desc: '浅色描边的各主题展示', ignoreCode: true, builder: (context) { - return Wrap( + return const Wrap( spacing: 8, - children: const [ + children: [ TDTag( '标签文字', isOutline: true, @@ -337,10 +339,10 @@ class TDTagPage extends StatelessWidget { desc: '各主题关闭图标颜色不会变', ignoreCode: true, builder: (context) { - return Wrap( + return const Wrap( spacing: 8, runSpacing: 8, - children: const [ + children: [ TDTag( '标签文字', isOutline: true, @@ -401,8 +403,8 @@ class TDTagPage extends StatelessWidget { desc: '带图标可关闭的标签', ignoreCode: true, builder: (context) { - return Row( - children: const [ + return const Row( + children: [ SizedBox( width: 16, ), @@ -432,7 +434,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDTag( '加大尺寸', icon: TDIcons.discount, @@ -463,7 +465,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDTag( '加大尺寸', isOutline: true, @@ -505,7 +507,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDSelectTag( 'Tag', theme: TDTagTheme.primary, @@ -549,7 +551,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDSelectTag( 'Tag', theme: TDTagTheme.primary, @@ -599,7 +601,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDSelectTag( 'Tag', theme: TDTagTheme.primary, @@ -649,7 +651,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDSelectTag( 'Tag', theme: TDTagTheme.primary, @@ -712,7 +714,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDTag( 'Tag', theme: TDTagTheme.primary, @@ -744,7 +746,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDTag( 'Tag', theme: TDTagTheme.primary, @@ -780,7 +782,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDTag( 'Tag', theme: TDTagTheme.primary, @@ -816,7 +818,7 @@ class TDTagPage extends StatelessWidget { Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(left: 16, right: 16), - child: Wrap(spacing: 8, runSpacing: 8, children: const [ + child: const Wrap(spacing: 8, runSpacing: 8, children: [ TDTag( 'Tag', theme: TDTagTheme.primary, @@ -941,7 +943,7 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildDarkSelectTags(BuildContext context) { - return Wrap(spacing: 8, children: const [ + return const Wrap(spacing: 8, children: [ TDSelectTag( '未选中态', theme: TDTagTheme.primary, @@ -961,7 +963,7 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildLightSelectTags(BuildContext context) { - return Wrap(spacing: 8, children: const [ + return const Wrap(spacing: 8, children: [ TDSelectTag( '未选中态', theme: TDTagTheme.primary, @@ -984,7 +986,7 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildOutlineSelectTags(BuildContext context) { - return Wrap(spacing: 8, children: const [ + return const Wrap(spacing: 8, children: [ TDSelectTag( '未选中态', theme: TDTagTheme.primary, @@ -1007,7 +1009,7 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildLightOutlineSelectTags(BuildContext context) { - return Wrap(spacing: 8, children: const [ + return const Wrap(spacing: 8, children: [ TDSelectTag( '未选中态', theme: TDTagTheme.primary, @@ -1033,9 +1035,9 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildLightShowTags(BuildContext context) { - return Wrap( + return const Wrap( spacing: 8, - children: const [ + children: [ TDTag('默认', isLight: true), TDTag( '主要', @@ -1063,9 +1065,9 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildDarkShowTags(BuildContext context) { - return Wrap( + return const Wrap( spacing: 8, - children: const [ + children: [ TDTag('默认'), TDTag( '主要', @@ -1089,9 +1091,9 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildOutlineShowTags(BuildContext context) { - return Wrap( + return const Wrap( spacing: 8, - children: const [ + children: [ TDTag('默认', isOutline: true), TDTag( '主要', @@ -1119,9 +1121,9 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildLightOutlineShowTags(BuildContext context) { - return Wrap( + return const Wrap( spacing: 8, - children: const [ + children: [ TDTag('默认', isOutline: true, isLight: true), TDTag( '主要', @@ -1153,7 +1155,7 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildAllSizeTags(BuildContext context) { - return Wrap(spacing: 8, children: const [ + return const Wrap(spacing: 8, children: [ TDTag( '加大尺寸', size: TDTagSize.extraLarge, @@ -1175,7 +1177,7 @@ class TDTagPage extends StatelessWidget { @Demo(group: 'tag') Widget _buildAllSizeCloseTags(BuildContext context) { - return Wrap(spacing: 8, children: const [ + return const Wrap(spacing: 8, children: [ TDTag( '加大尺寸', needCloseIcon: true, diff --git a/tdesign-component/example/lib/page/td_text_page.dart b/tdesign-component/example/lib/page/td_text_page.dart index 881caaf09..df326c2c6 100644 --- a/tdesign-component/example/lib/page/td_text_page.dart +++ b/tdesign-component/example/lib/page/td_text_page.dart @@ -11,9 +11,7 @@ class TDTextPage extends StatelessWidget { @override Widget build(BuildContext context) { - // debugPaintBaselinesEnabled = true; return ExamplePage( - padding: const EdgeInsets.all(8), title: tdTitle(context), exampleCodeGroup: 'text', children: [ @@ -32,25 +30,29 @@ class TDTextPage extends StatelessWidget { ExampleItem( desc: '中文居中:(带有英文可能不居中)', builder: _buildVerticalCenterText), ExampleItem(desc: '自定义内部padding:', builder: _buildCustomPaddingText), + ExampleItem(desc: '删除线:', builder: _buildTextThrough), ]), ], test: [ ExampleItem( desc: '中文居中-系统字体', - builder: (context){ - return Container( - color: TDTheme.of(context).brandFocusColor, - child: Text(exampleTxt), - ); - }), + builder: (context) { + return Container( + color: TDTheme.of(context).brandFocusColor, + child: Text(exampleTxt), + ); + }), ExampleItem( desc: '中文居中-TD字体', - builder: (context){ - return Container( - color: TDTheme.of(context).brandFocusColor, - child: TDText(exampleTxt, forceVerticalCenter: true,), - ); - }), + builder: (context) { + return Container( + color: TDTheme.of(context).brandFocusColor, + child: TDText( + exampleTxt, + forceVerticalCenter: true, + ), + ); + }), ], ); } @@ -151,6 +153,11 @@ class TDTextPage extends StatelessWidget { child: const CustomPaddingText(), ); } + + @Demo(group: 'text') + Widget _buildTextThrough(BuildContext context) { + return TDText(exampleTxt, isTextThrough: true); + } } /// 自定义控件,内部的context可拿到外部TDTextConfiguration的配置信息 diff --git a/tdesign-component/example/lib/page/td_textarea_page.dart b/tdesign-component/example/lib/page/td_textarea_page.dart index 84b8fb60c..b8e82337d 100644 --- a/tdesign-component/example/lib/page/td_textarea_page.dart +++ b/tdesign-component/example/lib/page/td_textarea_page.dart @@ -33,7 +33,6 @@ class _TDTextareaPageState extends State { @override Widget build(BuildContext context) { return ExamplePage( - backgroundColor: const Color(0xFFF0F2F5), title: tdTitle(), desc: '用于多行文本信息输入。', exampleCodeGroup: 'textarea', @@ -97,8 +96,7 @@ class _TDTextareaPageState extends State { hintText: '请输入文字', maxLines: 4, minLines: 4, - onChanged: (value) { - }, + onChanged: (value) {}, ); } @@ -108,8 +106,7 @@ class _TDTextareaPageState extends State { controller: controller[2], hintText: '请输入文字', minLines: 1, - onChanged: (value) { - }, + onChanged: (value) {}, ); } @@ -123,8 +120,7 @@ class _TDTextareaPageState extends State { minLines: 4, maxLength: 500, indicator: true, - onChanged: (value) { - }, + onChanged: (value) {}, ); } @@ -137,9 +133,7 @@ class _TDTextareaPageState extends State { maxLines: 4, minLines: 4, readOnly: true, - onChanged: (value) { - - }, + onChanged: (value) {}, ); } @@ -154,8 +148,7 @@ class _TDTextareaPageState extends State { maxLength: 500, indicator: true, layout: TDTextareaLayout.vertical, - onChanged: (value) { - }, + onChanged: (value) {}, ); } @@ -170,12 +163,14 @@ class _TDTextareaPageState extends State { maxLength: 500, indicator: true, decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusExtraLarge), + color: TDTheme.of(context).bgColorContainer, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusExtraLarge), ), - margin: EdgeInsets.only(right: TDTheme.of(context).spacer16, left: TDTheme.of(context).spacer16), - onChanged: (value) { - }, + margin: EdgeInsets.only( + right: TDTheme.of(context).spacer16, + left: TDTheme.of(context).spacer16), + onChanged: (value) {}, ); } @@ -191,8 +186,7 @@ class _TDTextareaPageState extends State { indicator: true, layout: TDTextareaLayout.vertical, bordered: true, - onChanged: (value) { - }, + onChanged: (value) {}, ); } @@ -207,8 +201,7 @@ class _TDTextareaPageState extends State { maxLength: 500, indicator: true, width: 200, - onChanged: (value) { - }, + onChanged: (value) {}, ); } @@ -221,15 +214,14 @@ class _TDTextareaPageState extends State { labelIcon: Icon( TDIcons.location, size: 20, - color: TDTheme.of(context).fontGyColor1, + color: TDTheme.of(context).textColorPrimary, ), hintText: '请输入文字', maxLines: 4, minLines: 4, maxLength: 500, indicator: true, - onChanged: (value) { - }, + onChanged: (value) {}, ); } @@ -246,8 +238,7 @@ class _TDTextareaPageState extends State { layout: TDTextareaLayout.vertical, required: true, additionInfo: '辅助说明', - onChanged: (value) { - }, + onChanged: (value) {}, ); } @@ -263,8 +254,7 @@ class _TDTextareaPageState extends State { indicator: true, layout: TDTextareaLayout.vertical, size: TDInputSize.small, - onChanged: (value) { - }, + onChanged: (value) {}, ); } } diff --git a/tdesign-component/example/lib/page/td_theme_page.dart b/tdesign-component/example/lib/page/td_theme_page.dart index 082378005..3d9f9ef73 100644 --- a/tdesign-component/example/lib/page/td_theme_page.dart +++ b/tdesign-component/example/lib/page/td_theme_page.dart @@ -49,9 +49,7 @@ class _TDThemeColorsPageState extends State { _initData(); } - void _initData() async{ - - + void _initData() async { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { TDTheme.of(context).colorMap.forEach((key, value) { if (key.startsWith('brand')) { @@ -71,7 +69,7 @@ class _TDThemeColorsPageState extends State { TDTheme.of(context).refMap.forEach((key, value) { var color = TDTheme.of(context).colorMap[key]; - if(color == null){ + if (color == null) { return; } if (key.startsWith('brand')) { @@ -88,9 +86,7 @@ class _TDThemeColorsPageState extends State { grayMap[key] = color; } }); - setState(() { - - }); + setState(() {}); }); } @@ -98,12 +94,12 @@ class _TDThemeColorsPageState extends State { Widget _buildDefaultTheme(BuildContext context) { // 通过TDTheme.of(context).xxx使用公共主题属性 return Container( - margin: EdgeInsets.all(TDTheme.of(context).spacer8), // 间隔 + margin: EdgeInsets.all(TDTheme.of(context).spacer8), + padding: EdgeInsets.all(TDTheme.of(context).spacer8), decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, // 颜色 - borderRadius: - BorderRadius.circular(TDTheme.of(context).radiusDefault), // 圆角 - boxShadow: TDTheme.of(context).shadowsBase, // 阴影 + color: TDTheme.of(context).bgColorSecondaryContainer, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + boxShadow: TDTheme.of(context).shadowsBase, ), child: TDText( '使用外层默认主题', @@ -118,6 +114,7 @@ class _TDThemeColorsPageState extends State { Widget _buildCustomTheme(BuildContext context) { /// 开启多主题 TDTheme.needMultiTheme(true); + /// 此处替换主题 return TDTheme( // 替换fonts和colors,其他主题从父类拷贝 @@ -126,42 +123,8 @@ class _TDThemeColorsPageState extends State { }, colorMap: { 'brandNormalColor': Colors.red }), - // 不能直接在此处使用context,这里虽然被包裹在TGTheme中,但是context未更新,因此阿不到最新数据 + // 不能直接在此处使用context,这里虽然被包裹在TGTheme中,但是context未更新,因此读不到最新数据 child: const TestWidget()); - - // /// 测试控件 -// class TestWidget extends StatelessWidget { -// const TestWidget({Key? key}) : super(key: key); -// -// @override -// Widget build(BuildContext context) { -// return Container( -// alignment: Alignment.center, -// child: Column( -// mainAxisSize: MainAxisSize.min, -// children: [ -// TDText( -// '使用内层赋值主题', -// font: TDTheme.of(context).fontBodyLarge, //明确使用内层主题,必须传context -// textColor: -// TDTheme.of(context).brandNormalColor, // 明确使用内层主题,必须传context -// ), -// TDText( -// '使用内层不赋值主题', -// font: TDTheme.of(context).fontTitleExtraLarge, //明确使用内层主题,必须传context -// textColor: -// TDTheme.of(context).successNormalColor, // 明确使用内层主题,必须传context -// ), -// TDText( -// '使用默认主题', -// font: TDTheme.defaultData().fontBodyLarge, //不传context,使用默认主题,此处是外层的主题 -// textColor: TDTheme.defaultData().brandNormalColor, -// ), -// ], -// ), -// ); -// } -// } } Widget _buildFunctionColor(BuildContext context) { @@ -185,13 +148,13 @@ class _TDThemeColorsPageState extends State { index = index % brandMap.length; var function = functionList[type]; var map = {}; - if(type == 0){ + if (type == 0) { map = brandMap; - } else if(type == 1){ + } else if (type == 1) { map = errorMap; - } else if (type == 2){ + } else if (type == 2) { map = warningMap; - } else if(type == 3){ + } else if (type == 3) { map = successMap; } if (index < 10) { @@ -251,7 +214,7 @@ class _TDThemeColorsPageState extends State { var light = index < 6; if (index == 0) { return Container( - color: TDTheme.of(context).colorMap['whiteColor1'], + color: TDTheme.of(context).bgColorContainer, child: const TDText('whiteColor1'), ); } else { @@ -291,7 +254,7 @@ class TestWidget extends StatelessWidget { TDTheme.of(context).successNormalColor, // 明确使用内层主题,必须传context ), const TDButton( - text: '使用内层赋值主题', + text: '使用内层赋值主题', theme: TDButtonTheme.primary, ), TDText( diff --git a/tdesign-component/example/lib/page/td_time_counter_page.dart b/tdesign-component/example/lib/page/td_time_counter_page.dart index a1272d54a..b54ab13ed 100644 --- a/tdesign-component/example/lib/page/td_time_counter_page.dart +++ b/tdesign-component/example/lib/page/td_time_counter_page.dart @@ -8,302 +8,203 @@ class TDTimeCounterPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - color: TDTheme.of(context).grayColor2, - child: ExamplePage( - title: tdTitle(context), - desc: '用于实时展示计时数值。', - exampleCodeGroup: 'timeCounter', - children: [ - ExampleModule(title: '组件类型', children: [ - ExampleItem( - ignoreCode: true, - desc: '时分秒', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildSimple); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '带毫秒', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildMillisecondSimple); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '正向计时', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildUpSimple); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '带方形底', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildSquareSimple); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '带圆形底', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildRoundSimple); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '带单位', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildUnitSimple); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '无底色带单位', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildCustomUnitSimple); - }, - ), - ]), - ExampleModule(title: '组件尺寸', children: [ - ExampleItem( - ignoreCode: true, - desc: '纯数字', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return Container( - alignment: Alignment.topLeft, - child: Wrap(spacing: 8, direction: Axis.vertical, children: [ - Row( - children: const [ - SizedBox( - width: 80, - child: Text('小'), - ), - CodeWrapper(builder: _buildSmallSize), - ], - ), - Row( - children: const [ - SizedBox( - width: 80, - child: Text('中'), - ), - CodeWrapper(builder: _buildMediumSize), - ], - ), - Row( - children: const [ - SizedBox( - width: 80, - child: Text('大'), - ), - CodeWrapper(builder: _buildLargeSize), - ], - ), - ]), - ); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '带方形底', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return Container( - alignment: Alignment.topLeft, - child: Wrap(spacing: 8, direction: Axis.vertical, children: [ + return ExamplePage( + title: tdTitle(context), + desc: '用于实时展示计时数值。', + exampleCodeGroup: 'timeCounter', + children: [ + const ExampleModule(title: '组件类型', children: [ + ExampleItem(desc: '时分秒', builder: _buildSimple), + ExampleItem(desc: '带毫秒', builder: _buildMillisecondSimple), + ExampleItem(desc: '正向计时', builder: _buildUpSimple), + ExampleItem(desc: '带方形底', builder: _buildSquareSimple), + ExampleItem(desc: '带圆形底', builder: _buildRoundSimple), + ExampleItem(desc: '带单位', builder: _buildUnitSimple), + ExampleItem(desc: '无底色带单位', builder: _buildCustomUnitSimple), + ]), + ExampleModule(title: '组件尺寸', children: [ + ExampleItem( + ignoreCode: true, + desc: '纯数字', + builder: (BuildContext context) { + return const Wrap( + direction: Axis.vertical, + spacing: 16, + children: [ + Row( + // spacing: 40, + children: [ + Text('小'), + SizedBox(width: 40), + CodeWrapper(builder: _buildSmallSize), + ], + ), + Row( + // spacing: 40, + children: [ + Text('中'), + SizedBox(width: 40), + CodeWrapper(builder: _buildMediumSize) + ], + ), + Row( + // spacing: 40, + children: [ + Text('大'), + SizedBox(width: 40), + CodeWrapper(builder: _buildLargeSize), + ], + ), + ], + ); + }, + ), + ExampleItem( + ignoreCode: true, + desc: '带方形底', + builder: (BuildContext context) { + return const Wrap( + direction: Axis.vertical, + spacing: 16, + children: [ Row( - children: const [ - SizedBox( - width: 80, - child: Text('小'), - ), + // spacing: 40, + children: [ + Text('小'), + SizedBox(width: 40), CodeWrapper(builder: _buildSquareSmallSize), ], ), Row( - children: const [ - SizedBox( - width: 80, - child: Text('中'), - ), + // spacing: 40, + children: [ + Text('中'), + SizedBox(width: 40), CodeWrapper(builder: _buildSquareMediumSize), ], ), Row( - children: const [ - SizedBox( - width: 80, - child: Text('大'), - ), + // spacing: 40, + children: [ + Text('大'), + SizedBox(width: 40), CodeWrapper(builder: _buildSquareLargeSize), ], ), - ]), - ); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '带圆形底', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return Container( - alignment: Alignment.topLeft, - child: Wrap(spacing: 8, direction: Axis.vertical, children: [ + ]); + }, + ), + ExampleItem( + ignoreCode: true, + desc: '带圆形底', + builder: (BuildContext context) { + return const Wrap( + direction: Axis.vertical, + spacing: 16, + children: [ Row( - children: const [ - SizedBox( - width: 80, - child: Text('小'), - ), + // spacing: 40, + children: [ + Text('小'), + SizedBox(width: 40), CodeWrapper(builder: _buildRoundSmallSize), ], ), Row( - children: const [ - SizedBox( - width: 80, - child: Text('中'), - ), + // spacing: 40, + children: [ + Text('中'), + SizedBox(width: 40), CodeWrapper(builder: _buildRoundMediumSize), ], ), Row( - children: const [ - SizedBox( - width: 80, - child: Text('大'), - ), + // spacing: 40, + children: [ + Text('大'), + SizedBox(width: 40), CodeWrapper(builder: _buildRoundLargeSize), ], ), - ]), - ); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '带单位', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return Container( - alignment: Alignment.topLeft, - child: Wrap(spacing: 8, direction: Axis.vertical, children: [ + ]); + }, + ), + ExampleItem( + ignoreCode: true, + desc: '带单位', + builder: (BuildContext context) { + return const Wrap( + direction: Axis.vertical, + spacing: 16, + children: [ Row( - children: const [ - SizedBox( - width: 80, - child: Text('小'), - ), + // spacing: 40, + children: [ + Text('小'), + SizedBox(width: 40), CodeWrapper(builder: _buildUnitSmallSize), ], ), Row( - children: const [ - SizedBox( - width: 80, - child: Text('中'), - ), + // spacing: 40, + children: [ + Text('中'), + SizedBox(width: 40), CodeWrapper(builder: _buildUnitMediumSize), ], ), Row( - children: const [ - SizedBox( - width: 80, - child: Text('大'), - ), + // spacing: 40, + children: [ + Text('大'), + SizedBox(width: 40), CodeWrapper(builder: _buildUnitLargeSize), ], ), - ]), - ); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '无底色带单位', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return Container( - alignment: Alignment.topLeft, - child: Wrap(spacing: 8, direction: Axis.vertical, children: [ + ]); + }, + ), + ExampleItem( + ignoreCode: true, + desc: '无底色带单位', + builder: (BuildContext context) { + return const Wrap( + spacing: 8, + direction: Axis.vertical, + children: [ Row( - children: const [ - SizedBox( - width: 80, - child: Text('小'), - ), + // spacing: 40, + children: [ + Text('小'), + SizedBox(width: 40), CodeWrapper(builder: _buildCustomUnitSmallSize), ], ), Row( - children: const [ - SizedBox( - width: 80, - child: Text('中'), - ), + // spacing: 40, + children: [ + Text('中'), + SizedBox(width: 40), CodeWrapper(builder: _buildCustomUnitMediumSize), ], ), Row( - children: const [ - SizedBox( - width: 80, - child: Text('大'), - ), + // spacing: 40, + children: [ + Text('大'), + SizedBox(width: 40), CodeWrapper(builder: _buildCustomUnitLargeSize), ], ), - ]), - ); - }, - ), - ]), - ], - test: [ - ExampleItem( - ignoreCode: true, - desc: '控制倒计时', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildControl); - }, - ), - ExampleItem( - ignoreCode: true, - desc: '自定义显示位数', - center: false, - padding: const EdgeInsets.only(left: 16), - builder: (BuildContext context) { - return const CodeWrapper(builder: _buildCustomNum); + ]); }, ), - ], - ), + ]), + ], + test: const [ + ExampleItem(desc: '控制倒计时', builder: _buildControl), + ExampleItem(desc: '自定义显示位数', builder: _buildCustomNum), + ], ); } } @@ -315,7 +216,10 @@ TDTimeCounter _buildSimple(BuildContext context) { @Demo(group: 'timeCounter') TDTimeCounter _buildMillisecondSimple(BuildContext context) { - return const TDTimeCounter(time: 60 * 60 * 1000, millisecond: true); + return const TDTimeCounter( + time: 60 * 60 * 1000, + millisecond: true, + ); } @Demo(group: 'timeCounter') @@ -329,24 +233,38 @@ TDTimeCounter _buildUpSimple(BuildContext context) { @Demo(group: 'timeCounter') TDTimeCounter _buildSquareSimple(BuildContext context) { - return const TDTimeCounter(time: 60 * 60 * 1000, theme: TDTimeCounterTheme.square); + return const TDTimeCounter( + time: 60 * 60 * 1000, + theme: TDTimeCounterTheme.square, + ); } @Demo(group: 'timeCounter') TDTimeCounter _buildRoundSimple(BuildContext context) { - return const TDTimeCounter(time: 60 * 60 * 1000, theme: TDTimeCounterTheme.round); + return const TDTimeCounter( + time: 60 * 60 * 1000, + theme: TDTimeCounterTheme.round, + ); } @Demo(group: 'timeCounter') TDTimeCounter _buildUnitSimple(BuildContext context) { - return const TDTimeCounter(time: 60 * 60 * 1000, theme: TDTimeCounterTheme.square, splitWithUnit: true); + return const TDTimeCounter( + time: 60 * 60 * 1000, + theme: TDTimeCounterTheme.square, + splitWithUnit: true, + ); } @Demo(group: 'timeCounter') TDTimeCounter _buildCustomUnitSimple(BuildContext context) { var style = TDTimeCounterStyle.generateStyle(context); - style.timeColor = TDTheme.of(context).errorColor6; - return TDTimeCounter(time: 60 * 60 * 1000, splitWithUnit: true, style: style); + style.timeColor = TDTheme.of(context).errorNormalColor; + return TDTimeCounter( + time: 60 * 60 * 1000, + splitWithUnit: true, + style: style, + ); } @Demo(group: 'timeCounter') @@ -459,8 +377,9 @@ TDTimeCounter _buildUnitLargeSize(BuildContext context) { @Demo(group: 'timeCounter') TDTimeCounter _buildCustomUnitSmallSize(BuildContext context) { - var style = TDTimeCounterStyle.generateStyle(context, size: TDTimeCounterSize.small); - style.timeColor = TDTheme.of(context).errorColor6; + var style = + TDTimeCounterStyle.generateStyle(context, size: TDTimeCounterSize.small); + style.timeColor = TDTheme.of(context).errorNormalColor; return TDTimeCounter( time: 60 * 60 * 1000, splitWithUnit: true, @@ -470,8 +389,9 @@ TDTimeCounter _buildCustomUnitSmallSize(BuildContext context) { @Demo(group: 'timeCounter') TDTimeCounter _buildCustomUnitMediumSize(BuildContext context) { - var style = TDTimeCounterStyle.generateStyle(context, size: TDTimeCounterSize.medium); - style.timeColor = TDTheme.of(context).errorColor6; + var style = + TDTimeCounterStyle.generateStyle(context, size: TDTimeCounterSize.medium); + style.timeColor = TDTheme.of(context).errorNormalColor; return TDTimeCounter( time: 60 * 60 * 1000, splitWithUnit: true, @@ -481,8 +401,9 @@ TDTimeCounter _buildCustomUnitMediumSize(BuildContext context) { @Demo(group: 'timeCounter') TDTimeCounter _buildCustomUnitLargeSize(BuildContext context) { - var style = TDTimeCounterStyle.generateStyle(context, size: TDTimeCounterSize.large); - style.timeColor = TDTheme.of(context).errorColor6; + var style = + TDTimeCounterStyle.generateStyle(context, size: TDTimeCounterSize.large); + style.timeColor = TDTheme.of(context).errorNormalColor; return TDTimeCounter( time: 60 * 60 * 1000, splitWithUnit: true, @@ -495,58 +416,44 @@ Widget _buildControl(BuildContext context) { var controller = TDTimeCounterController(); return Wrap( direction: Axis.vertical, + crossAxisAlignment: WrapCrossAlignment.center, spacing: 8, children: [ + TDTimeCounter( + time: 60 * 60 * 1000, + controller: controller, + // autoStart: false, + ), Wrap( spacing: 8, children: [ TDButton( text: '开始', - size: TDButtonSize.extraSmall, theme: TDButtonTheme.primary, - onTap: () { - controller.start(); - }, + onTap: () => controller.start(), ), TDButton( text: '结束', - size: TDButtonSize.extraSmall, theme: TDButtonTheme.primary, - onTap: () { - controller.reset(0); - }, + onTap: () => controller.reset(0), ), TDButton( text: '重置', - size: TDButtonSize.extraSmall, theme: TDButtonTheme.primary, - onTap: () { - controller.reset(); - }, + onTap: () => controller.reset(), ), TDButton( text: '暂停', - size: TDButtonSize.extraSmall, theme: TDButtonTheme.primary, - onTap: () { - controller.pause(); - }, + onTap: () => controller.pause(), ), TDButton( text: '继续', - size: TDButtonSize.extraSmall, theme: TDButtonTheme.primary, - onTap: () { - controller.resume(); - }, + onTap: () => controller.resume(), ), ], - ), - TDTimeCounter( - time: 60 * 60 * 1000, - controller: controller, - // autoStart: false, - ), + ) ], ); } diff --git a/tdesign-component/example/lib/page/td_toast_page.dart b/tdesign-component/example/lib/page/td_toast_page.dart index 2f356f031..a93c36a21 100644 --- a/tdesign-component/example/lib/page/td_toast_page.dart +++ b/tdesign-component/example/lib/page/td_toast_page.dart @@ -5,18 +5,13 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../base/example_widget.dart'; import '../annotation/demo.dart'; -class TDToastPage extends StatefulWidget { - const TDToastPage({Key? key}) : super(key: key); +class TDToastPage extends StatelessWidget { + const TDToastPage({super.key}); - @override - State createState() => _TDToastPageState(); -} - -class _TDToastPageState extends State { @override Widget build(BuildContext context) { return ExamplePage( - title: tdTitle(), + title: tdTitle(context), desc: '用于轻量级反馈或提示,不会打断用户操作。', exampleCodeGroup: 'toast', children: [ @@ -65,14 +60,16 @@ class _TDToastPageState extends State { Widget _textCustomToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showText('自定义纯文字', - context: context, - customWidget: Container( - width: 50, - height: 20, - child: const TDText('自定义纯文字'), - color: TDTheme.of(context).brandClickColor, - )); + TDToast.showText( + '自定义纯文字', + context: context, + customWidget: Container( + width: 50, + height: 20, + child: const TDText('自定义纯文字'), + color: TDTheme.of(context).brandClickColor, + ), + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -100,7 +97,11 @@ class _TDToastPageState extends State { Widget _horizontalIconToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showIconText('带横向图标', icon: TDIcons.check_circle, context: context); + TDToast.showIconText( + '带横向图标', + icon: TDIcons.check_circle, + context: context, + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -114,8 +115,12 @@ class _TDToastPageState extends State { Widget _verticalIconToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showIconText('带竖向图标', - icon: TDIcons.check_circle, direction: IconTextDirection.vertical, context: context); + TDToast.showIconText( + '带竖向图标', + icon: TDIcons.check_circle, + direction: IconTextDirection.vertical, + context: context, + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -143,12 +148,15 @@ class _TDToastPageState extends State { Widget _loadingCustomToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showLoading(context: context, customWidget: Container( - width: 50, - height: 20, - child: const TDText('自定义加载'), - color: TDTheme.of(context).brandColor1, - )); + TDToast.showLoading( + context: context, + customWidget: Container( + width: 50, + height: 20, + child: const TDText('自定义加载'), + color: TDTheme.of(context).brandColor1, + ), + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -202,7 +210,11 @@ class _TDToastPageState extends State { Widget _successVerticalToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showSuccess('成功文案', direction: IconTextDirection.vertical, context: context); + TDToast.showSuccess( + '成功文案', + direction: IconTextDirection.vertical, + context: context, + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -216,7 +228,11 @@ class _TDToastPageState extends State { Widget _warningToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showWarning('警告文案', direction: IconTextDirection.horizontal, context: context); + TDToast.showWarning( + '警告文案', + direction: IconTextDirection.horizontal, + context: context, + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -230,7 +246,11 @@ class _TDToastPageState extends State { Widget _warningVerticalToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showWarning('警告文案', direction: IconTextDirection.vertical, context: context); + TDToast.showWarning( + '警告文案', + direction: IconTextDirection.vertical, + context: context, + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -244,7 +264,11 @@ class _TDToastPageState extends State { Widget _failToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showFail('失败文案', direction: IconTextDirection.horizontal, context: context); + TDToast.showFail( + '失败文案', + direction: IconTextDirection.horizontal, + context: context, + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -258,7 +282,11 @@ class _TDToastPageState extends State { Widget _failVerticalToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showFail('失败文案', direction: IconTextDirection.vertical, context: context); + TDToast.showFail( + '失败文案', + direction: IconTextDirection.vertical, + context: context, + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -272,7 +300,12 @@ class _TDToastPageState extends State { Widget _preventTapToast(BuildContext context) { return TDButton( onTap: () { - TDToast.showText('轻提示文字内容', context: context, preventTap: true, backgroundColor: Colors.black.withOpacity(0.7)); + TDToast.showText( + '轻提示文字内容', + context: context, + preventTap: true, + backgroundColor: Colors.black.withOpacity(0.7), + ); }, size: TDButtonSize.large, type: TDButtonType.outline, @@ -287,10 +320,11 @@ class _TDToastPageState extends State { return TDButton( onTap: () { TDToast.showText( - '最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字', - context: context, - constraints: BoxConstraints(maxWidth: 350.scale), - maxLines: 5); + '最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字最多一行展示十个汉字宽度限制最多不超过三行文字', + context: context, + constraints: BoxConstraints(maxWidth: 350.scale), + maxLines: 5, + ); }, size: TDButtonSize.large, type: TDButtonType.outline, diff --git a/tdesign-component/example/lib/page/td_tree_select_page.dart b/tdesign-component/example/lib/page/td_tree_select_page.dart index 98f1f4c3b..55999da3d 100644 --- a/tdesign-component/example/lib/page/td_tree_select_page.dart +++ b/tdesign-component/example/lib/page/td_tree_select_page.dart @@ -29,7 +29,6 @@ class _TDTreeSelectPageState extends State { title: tdTitle(), desc: '适用于选择树形的数据结构', exampleCodeGroup: 'tree', - backgroundColor: TDTheme.of(context).grayColor2, children: [ ExampleModule( title: '组件类型', @@ -47,7 +46,7 @@ class _TDTreeSelectPageState extends State { ], test: [ ExampleItem(desc: '局部多选', builder: _buildPartMultipleTreeSelect), - ExampleItem(desc: '局部多选', builder: _buildPartMultipleTreeSelect), + ExampleItem(desc: '局部多选', builder: _buildPartMultipleTreeSelect2), ], ); } @@ -100,7 +99,6 @@ class _TDTreeSelectPageState extends State { ); } - @Demo(group: 'tree') Widget _buildThirdTreeSelect(BuildContext context) { var options = []; @@ -115,20 +113,21 @@ class _TDTreeSelectPageState extends State { for (var j = 1; j <= 3; j++) { options[i - 1].children.add(TDSelectOption( - label: '${j == 1 ? '特别长的二级选项特别长的二级选项特别长的二级选项' : '选项$i.$j'}', - value: i * 10 + j, - maxLines: 2, - columnWidth: j == 1 ? 180: null, - children: [], - )); + label: '${j == 1 ? '特别长的二级选项特别长的二级选项特别长的二级选项' : '选项$i.$j'}', + value: i * 10 + j, + maxLines: 2, + columnWidth: j == 1 ? 180 : null, + children: [], + )); for (var k = 1; k <= 3; k++) { options[i - 1].children[j - 1].children.add(TDSelectOption( - label: '${k == 1 ? '非常长的三级选项名称非常长的三级选项名称非常长的三级选项名称' : '选项$i.$j.$k'}', - value: i * 100 + j * 10 + k, - maxLines: 2, - //columnWidth: k == 1 ? 102 : null, - )); + label: + '${k == 1 ? '非常长的三级选项名称非常长的三级选项名称非常长的三级选项名称' : '选项$i.$j.$k'}', + value: i * 100 + j * 10 + k, + maxLines: 2, + //columnWidth: k == 1 ? 102 : null, + )); } } } @@ -187,6 +186,7 @@ class _TDTreeSelectPageState extends State { return TDTreeSelect( options: options, defaultValue: values1, + style: TDTreeSelectStyle.outline, onChange: (val, level) { print('$val, $level'); }, diff --git a/tdesign-component/example/lib/page/td_upload_page.dart b/tdesign-component/example/lib/page/td_upload_page.dart index 83bfa0b03..a84354018 100644 --- a/tdesign-component/example/lib/page/td_upload_page.dart +++ b/tdesign-component/example/lib/page/td_upload_page.dart @@ -14,9 +14,18 @@ class TDUploadPage extends StatefulWidget { class TDUploadState extends State { final List files1 = []; final List files2 = [ - TDUploadFile(key: 1, remotePath: 'https://tdesign.gtimg.com/demo/images/example1.png'), - TDUploadFile(key: 2, remotePath: 'https://tdesign.gtimg.com/demo/images/example2.png'), - TDUploadFile(key: 3, remotePath: 'https://tdesign.gtimg.com/demo/images/example3.png'), + TDUploadFile( + key: 1, + remotePath: 'https://tdesign.gtimg.com/demo/images/example1.png'), + TDUploadFile( + key: 2, + remotePath: 'https://tdesign.gtimg.com/demo/images/example2.png'), + TDUploadFile( + key: 3, + remotePath: 'https://tdesign.gtimg.com/demo/images/example3.png'), + TDUploadFile( + key: 4, + remotePath: 'https://tdesign.gtimg.com/demo/images/example4.png'), ]; final List files3 = [ TDUploadFile( @@ -46,7 +55,8 @@ class TDUploadState extends State { ]; final List files6 = []; - void onValueChanged(List fileList, List value, TDUploadType event) { + void onValueChanged(List fileList, List value, + TDUploadType event) { switch (event) { case TDUploadType.add: setState(() { @@ -61,7 +71,8 @@ class TDUploadState extends State { case TDUploadType.replace: setState(() { final firstReplaceFile = value.first; - final index = fileList.indexWhere((file) => file.key == firstReplaceFile.key); + final index = + fileList.indexWhere((file) => file.key == firstReplaceFile.key); if (index != -1) { fileList[index] = firstReplaceFile; } @@ -83,7 +94,8 @@ class TDUploadState extends State { return ExamplePage( title: tdTitle(), exampleCodeGroup: 'upload', - desc: '用于相册读取或拉起拍照的图片上传功能。${PlatformUtil.isWeb ? "Web端不支持读取本地图片,请前往移动端体验。" : ""}', + desc: + '用于相册读取或拉起拍照的图片上传功能。${PlatformUtil.isWeb ? "Web端不支持读取本地图片,请前往移动端体验。" : ""}', children: [ ExampleModule( title: '组件类型', @@ -103,8 +115,12 @@ class TDUploadState extends State { ), ], test: [ - ExampleItem(ignoreCode: true, desc: '单选快速替换, 大小和图形测试', builder: _uploadSingleWithReplace), - ExampleItem(ignoreCode: true, desc: '上传文件大小限制,10KB', builder: _uploadSizeLimit), + ExampleItem( + ignoreCode: true, + desc: '单选快速替换, 大小和图形测试', + builder: _uploadSingleWithReplace), + ExampleItem( + ignoreCode: true, desc: '上传文件大小限制,10KB', builder: _uploadSizeLimit), ], ); } @@ -112,7 +128,7 @@ class TDUploadState extends State { Widget wrapDemoContainer(String title, {required Widget child}) { return Container( padding: const EdgeInsets.all(16), - decoration: const BoxDecoration(color: Colors.white), + color: TDTheme.of(context).bgColorContainer, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/tdesign-component/example/pubspec.yaml b/tdesign-component/example/pubspec.yaml index 7b7281975..24d51d3a0 100644 --- a/tdesign-component/example/pubspec.yaml +++ b/tdesign-component/example/pubspec.yaml @@ -30,7 +30,7 @@ environment: dependencies: flutter: sdk: flutter - web: ^1.1.1 + web: ^0.3.0 #轮播图组件 flutter_swiper_null_safety: ^1.0.2 @@ -62,6 +62,7 @@ dev_dependencies: dependency_overrides: flutter_plugin_android_lifecycle: 2.0.28 + web: ^1.1.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/tdesign-component/init.sh b/tdesign-component/init.sh index cfab36e8b..b4164fd7d 100644 --- a/tdesign-component/init.sh +++ b/tdesign-component/init.sh @@ -1,13 +1,12 @@ #!/bin/bash # 可以指定自己的Flutter SDK路径 -#FLUTTER_SDK_PATH=~/tools/flutter +# FLUTTER_SDK_PATH=~/tools/flutter -# 设置基础目录(脚本所在目录)` +# 设置基础目录(脚本所在目录) BASE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -# 检查Flutter SDK路径 -# 检查Flutter SDK路径 +# 检查 Flutter SDK 路径 if [[ -n "$FLUTTER_SDK_PATH" ]]; then FLUTTER_CMD="$FLUTTER_SDK_PATH/bin/flutter" echo "使用自定义Flutter路径: $FLUTTER_CMD" diff --git a/tdesign-component/lib/src/components/action_sheet/td_action_sheet.dart b/tdesign-component/lib/src/components/action_sheet/td_action_sheet.dart index e4e331851..a7edbaa17 100644 --- a/tdesign-component/lib/src/components/action_sheet/td_action_sheet.dart +++ b/tdesign-component/lib/src/components/action_sheet/td_action_sheet.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import '../../util/context_extension.dart'; import '../popup/td_popup_route.dart'; import 'td_action_sheet.dart'; import 'td_action_sheet_grid.dart'; @@ -19,7 +20,7 @@ class TDActionSheet { TDActionSheet( this.context, { this.align = TDActionSheetAlign.center, - this.cancelText = '取消', + this.cancelText, this.count = 8, this.rows = 2, this.itemHeight = 96.0, @@ -50,7 +51,7 @@ class TDActionSheet { final TDActionSheetAlign align; /// 取消按钮的文本 - final String cancelText; + final String? cancelText; /// 每页显示的项目数 /// 当[theme]等于[TDActionSheetTheme.grid]且[showPagination]为true时有效 @@ -118,7 +119,7 @@ class TDActionSheet { BuildContext context, { required List items, TDActionSheetAlign align = TDActionSheetAlign.center, - String cancelText = '取消', + String? cancelText, bool showCancel = true, VoidCallback? onCancel, TDActionSheetItemCallback? onSelected, @@ -148,7 +149,7 @@ class TDActionSheet { BuildContext context, { required List items, TDActionSheetAlign align = TDActionSheetAlign.center, - String cancelText = '取消', + String? cancelText, bool showCancel = true, TDActionSheetItemCallback? onSelected, bool showOverlay = true, @@ -192,7 +193,7 @@ class TDActionSheet { BuildContext context, { required List items, TDActionSheetAlign align = TDActionSheetAlign.left, - String cancelText = '取消', + String? cancelText, bool showCancel = true, TDActionSheetItemCallback? onSelected, bool showOverlay = true, @@ -263,7 +264,7 @@ class TDActionSheet { required TDActionSheetTheme theme, required List items, TDActionSheetAlign align = TDActionSheetAlign.center, - String cancelText = '取消', + String? cancelText, bool showCancel = true, TDActionSheetItemCallback? onSelected, bool showOverlay = true, @@ -282,6 +283,9 @@ class TDActionSheet { if (_actionSheetRoute != null) { return; } + + cancelText = cancelText ?? context.resource.cancel; + _actionSheetRoute = TDSlidePopupRoute( slideTransitionFrom: SlideTransitionFrom.bottom, isDismissible: showOverlay ? closeOnOverlayClick : false, diff --git a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_grid.dart b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_grid.dart index b3379e4a2..6dad8abee 100644 --- a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_grid.dart +++ b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_grid.dart @@ -17,7 +17,7 @@ class TDActionSheetGrid extends StatefulWidget { final TDActionSheetAlign align; final int count; final int rows; - final String cancelText; + final String? cancelText; final bool showCancel; final bool showPagination; final bool scrollable; @@ -34,7 +34,7 @@ class TDActionSheetGrid extends StatefulWidget { this.align = TDActionSheetAlign.center, this.count = 8, this.rows = 2, - this.cancelText = '取消', + this.cancelText, this.showCancel = true, this.showPagination = false, this.scrollable = false, @@ -57,18 +57,19 @@ class _TDActionSheetGridState extends State { final borderRadius = Radius.circular(TDTheme.of(context).radiusExtraLarge); return Container( decoration: BoxDecoration( - borderRadius: BorderRadius.only(topLeft: borderRadius, topRight: borderRadius), - color: TDTheme.of(context).whiteColor1, + borderRadius: + BorderRadius.only(topLeft: borderRadius, topRight: borderRadius), + color: TDTheme.of(context).bgColorContainer, ), clipBehavior: Clip.antiAlias, - padding: widget.useSafeArea ? EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom) : EdgeInsets.zero, + padding: widget.useSafeArea + ? EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom) + : EdgeInsets.zero, child: Column( mainAxisSize: MainAxisSize.min, children: [ SizedBox(height: TDTheme.of(context).spacer8), - // 如果有描述,则显示描述 if (widget.description != null) _buildDescription(context), - // 如果显示分页,则显示分页点 if (widget.showPagination) ...[ _buildPaginationGrid(context), _buildPaginationDots(context), @@ -77,8 +78,13 @@ class _TDActionSheetGridState extends State { _buildScrollGrid(context) else _buildGrid(context), - // 如果显示取消按钮,则显示取消按钮 - if (widget.showCancel) buildCancelButton(context, widget.showPagination, widget.cancelText, widget.onCancel), + if (widget.showCancel) + buildCancelButton( + context, + widget.showPagination, + widget.cancelText, + widget.onCancel, + ), ], ), ); @@ -97,7 +103,7 @@ class _TDActionSheetGridState extends State { TDText( widget.description!, font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor3, + textColor: TDTheme.of(context).textColorPlaceholder, ), ], ), @@ -125,7 +131,10 @@ class _TDActionSheetGridState extends State { : null, itemBuilder: (context, pageIndex) { // 获取当前页面的项目 - final pageItems = widget.items.skip(pageIndex * widget.count).take(widget.count).toList(); + final pageItems = widget.items + .skip(pageIndex * widget.count) + .take(widget.count) + .toList(); return _buildGrid(context, items: pageItems, pageIndex: pageIndex); }, ), @@ -133,7 +142,8 @@ class _TDActionSheetGridState extends State { } Widget _buildScrollGrid(BuildContext context) { - final chunks = widget.items.chunk((widget.items.length / widget.rows).ceil()); + final chunks = + widget.items.chunk((widget.items.length / widget.rows).ceil()); final itemCount = chunks[0].length; return _gridWrap( ListView.builder( @@ -195,14 +205,17 @@ class _TDActionSheetGridState extends State { Widget _buildPaginationDots(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: List.generate((widget.items.length / widget.count).ceil(), (index) { + children: + List.generate((widget.items.length / widget.count).ceil(), (index) { return Container( margin: EdgeInsets.symmetric(horizontal: TDTheme.of(context).spacer4), width: 8.0, height: 8.0, decoration: BoxDecoration( shape: BoxShape.circle, - color: currentPage == index ? TDTheme.of(context).brandColor7 : TDTheme.of(context).grayColor4, + color: currentPage == index + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).bgColorSecondaryContainerActive, ), ); }), diff --git a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_group.dart b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_group.dart index 72c0c72ab..5e1e0d34f 100644 --- a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_group.dart +++ b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_group.dart @@ -14,7 +14,7 @@ import 'td_action_sheet_item_widget.dart'; class TDActionSheetGroup extends StatelessWidget { final List items; final TDActionSheetAlign align; - final String cancelText; + final String? cancelText; final bool showCancel; final VoidCallback? onCancel; final TDActionSheetItemCallback? onSelected; @@ -26,7 +26,7 @@ class TDActionSheetGroup extends StatelessWidget { super.key, required this.items, this.align = TDActionSheetAlign.left, - this.cancelText = '取消', + this.cancelText, this.showCancel = true, this.onCancel, this.onSelected, @@ -39,15 +39,19 @@ class TDActionSheetGroup extends StatelessWidget { Widget build(BuildContext context) { final borderRadius = Radius.circular(TDTheme.of(context).radiusExtraLarge); final groupItems = items.groupBy((item) => item.group); - final groupKeys = groupItems.keys.where((k) => k != null && groupItems[k]?.isNotEmpty == true); + final groupKeys = groupItems.keys + .where((k) => k != null && groupItems[k]?.isNotEmpty == true); return Container( decoration: BoxDecoration( - borderRadius: BorderRadius.only(topLeft: borderRadius, topRight: borderRadius), - color: TDTheme.of(context).whiteColor1, + borderRadius: + BorderRadius.only(topLeft: borderRadius, topRight: borderRadius), + color: TDTheme.of(context).bgColorContainer, ), clipBehavior: Clip.antiAlias, - padding: useSafeArea ? EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom) : EdgeInsets.zero, + padding: useSafeArea + ? EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom) + : EdgeInsets.zero, child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -69,7 +73,7 @@ class TDActionSheetGroup extends StatelessWidget { TDText( k!, font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor3, + textColor: TDTheme.of(context).textColorPlaceholder, ), ], ), @@ -98,7 +102,7 @@ class TDActionSheetGroup extends StatelessWidget { color: TDTheme.of(context).fontWhColor1, border: Border( top: BorderSide( - color: TDTheme.of(context).grayColor3, + color: TDTheme.of(context).componentStrokeColor, width: 0.5, ), ), @@ -107,7 +111,8 @@ class TDActionSheetGroup extends StatelessWidget { ], ); }), - if (showCancel) buildCancelButton(context, false, cancelText, onCancel), + if (showCancel) + buildCancelButton(context, false, cancelText, onCancel), ], ), ); diff --git a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_item.dart b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_item.dart index 7e8437d00..d88a24bd6 100644 --- a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_item.dart +++ b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_item.dart @@ -15,7 +15,7 @@ class TDActionSheetItem { this.group, }); - /// 标提 + /// 标题 final String label; /// 标题样式 diff --git a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_item_widget.dart b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_item_widget.dart index 7fe75a170..1c26a2763 100644 --- a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_item_widget.dart +++ b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_item_widget.dart @@ -3,6 +3,7 @@ import '../../theme/td_colors.dart'; import '../../theme/td_fonts.dart'; import '../../theme/td_spacers.dart'; import '../../theme/td_theme.dart'; +import '../../util/context_extension.dart'; import '../badge/td_badge.dart'; import '../text/td_text.dart'; import 'td_action_sheet.dart'; @@ -72,7 +73,7 @@ class TDActionSheetItemWidget extends StatelessWidget { TDText( item!.label, font: TDTheme.of(context).fontBodySmall, - textColor: TDTheme.of(context).fontGyColor1, + textColor: TDTheme.of(context).textColorPrimary, style: item!.textStyle, ), ], @@ -80,9 +81,11 @@ class TDActionSheetItemWidget extends StatelessWidget { ); } - void _setOffsetValue(GlobalKey> offsetKey, ValueNotifier> offsetValue) { + void _setOffsetValue(GlobalKey> offsetKey, + ValueNotifier> offsetValue) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - final renderBox = offsetKey.currentContext?.findRenderObject() as RenderBox; + final renderBox = + offsetKey.currentContext?.findRenderObject() as RenderBox; final size = renderBox.size; final right = -size.width / 2; final top = -size.height / 2; @@ -106,9 +109,17 @@ MainAxisAlignment getMainAxisAlignment(TDActionSheetAlign align) { } } -Widget buildCancelButton(BuildContext context, bool showPagination, String cancelText, VoidCallback? onCancel) { +Widget buildCancelButton( + BuildContext context, + bool showPagination, + String? cancelText, + VoidCallback? onCancel, +) { return Padding( - padding: EdgeInsets.only(top: showPagination ? TDTheme.of(context).spacer16 : TDTheme.of(context).spacer8), + padding: EdgeInsets.only( + top: showPagination + ? TDTheme.of(context).spacer16 + : TDTheme.of(context).spacer8), child: GestureDetector( onTap: () { onCancel?.call(); @@ -116,10 +127,10 @@ Widget buildCancelButton(BuildContext context, bool showPagination, String cance }, child: Container( decoration: BoxDecoration( - color: TDTheme.of(context).fontWhColor1, + color: TDTheme.of(context).bgColorContainer, border: Border( top: BorderSide( - color: TDTheme.of(context).grayColor3, + color: TDTheme.of(context).componentStrokeColor, width: 0.5, ), ), @@ -127,9 +138,9 @@ Widget buildCancelButton(BuildContext context, bool showPagination, String cance height: 48, child: Center( child: TDText( - cancelText, + cancelText ?? context.resource.cancel, font: TDTheme.of(context).fontBodyLarge, - textColor: TDTheme.of(context).fontGyColor1, + textColor: TDTheme.of(context).textColorPrimary, ), ), ), diff --git a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_list.dart b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_list.dart index 2db22af68..44ded5cea 100644 --- a/tdesign-component/lib/src/components/action_sheet/td_action_sheet_list.dart +++ b/tdesign-component/lib/src/components/action_sheet/td_action_sheet_list.dart @@ -4,6 +4,7 @@ import '../../theme/td_fonts.dart'; import '../../theme/td_radius.dart'; import '../../theme/td_spacers.dart'; import '../../theme/td_theme.dart'; +import '../../util/context_extension.dart'; import '../badge/td_badge.dart'; import '../text/td_text.dart'; import 'td_action_sheet.dart'; @@ -12,7 +13,7 @@ import 'td_action_sheet_item_widget.dart'; class TDActionSheetList extends StatelessWidget { final List items; final TDActionSheetAlign align; - final String cancelText; + final String? cancelText; final String? description; final bool showCancel; final VoidCallback? onCancel; @@ -23,7 +24,7 @@ class TDActionSheetList extends StatelessWidget { super.key, required this.items, this.align = TDActionSheetAlign.center, - this.cancelText = '取消', + this.cancelText, this.description, this.showCancel = true, this.onCancel, @@ -36,11 +37,11 @@ class TDActionSheetList extends StatelessWidget { final borderRadius = Radius.circular(TDTheme.of(context).radiusExtraLarge); return Container( decoration: BoxDecoration( - borderRadius: BorderRadius.only(topLeft: borderRadius, topRight: borderRadius), - color: TDTheme.of(context).grayColor1, + borderRadius: + BorderRadius.only(topLeft: borderRadius, topRight: borderRadius), + color: TDTheme.of(context).bgColorPage, ), clipBehavior: Clip.antiAlias, - padding: useSafeArea ? EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom) : EdgeInsets.zero, child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -60,10 +61,10 @@ class TDActionSheetList extends StatelessWidget { vertical: TDTheme.of(context).spacer12, ), decoration: BoxDecoration( - color: TDTheme.of(context).fontWhColor1, + color: TDTheme.of(context).bgColorContainer, border: Border( bottom: BorderSide( - color: TDTheme.of(context).grayColor1, + color: TDTheme.of(context).componentStrokeColor, width: 0.5, ), ), @@ -74,7 +75,7 @@ class TDActionSheetList extends StatelessWidget { TDText( description!, font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor3, + textColor: TDTheme.of(context).textColorSecondary, ), ], ), @@ -84,9 +85,11 @@ class TDActionSheetList extends StatelessWidget { /// 构建选项列表 Widget _buildOptionsList(BuildContext context) { return Container( - color: TDTheme.of(context).fontWhColor1, + color: TDTheme.of(context).bgColorContainer, child: ListView.builder( shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + // 禁用滚动 itemCount: items.length, padding: EdgeInsets.zero, itemBuilder: (context, index) { @@ -100,11 +103,12 @@ class TDActionSheetList extends StatelessWidget { }, child: Container( height: 56, - padding: EdgeInsets.symmetric(horizontal: TDTheme.of(context).spacer16), + padding: EdgeInsets.symmetric( + horizontal: TDTheme.of(context).spacer16), decoration: BoxDecoration( border: Border( bottom: BorderSide( - color: TDTheme.of(context).grayColor1, + color: TDTheme.of(context).componentStrokeColor, width: 0.5, ), ), @@ -116,8 +120,11 @@ class TDActionSheetList extends StatelessWidget { IconTheme( data: IconThemeData( color: item.disabled - ? TDTheme.of(context).fontGyColor4 // 禁用状态下的图标颜色 - : (item.textStyle?.color ?? TDTheme.of(context).fontGyColor1), // 正常状态下的图标颜色 + // 禁用状态下的图标颜色 + ? TDTheme.of(context).textColorDisabled + : (item.textStyle?.color ?? + // 正常状态下的图标颜色 + TDTheme.of(context).textColorPrimary), size: item.textStyle?.fontSize, ), child: SizedBox( @@ -132,10 +139,12 @@ class TDActionSheetList extends StatelessWidget { item.label, font: TDTheme.of(context).fontBodyLarge, textColor: item.disabled - ? TDTheme.of(context).fontGyColor4 // 禁用状态下的文本颜色 - : TDTheme.of(context).fontGyColor1, // 正常状态下的文本颜色 + ? TDTheme.of(context).textColorDisabled // 禁用状态下的文本颜色 + : TDTheme.of(context).textColorPrimary, // 正常状态下的文本颜色 style: item.textStyle, ), + + /// todo 徽标应位于右上角,而不是右边紧挨着,请参考宫格徽标实现 if (item.badge != null) ...[ SizedBox(width: TDTheme.of(context).spacer8), item.badge!, @@ -151,27 +160,32 @@ class TDActionSheetList extends StatelessWidget { /// 构建取消按钮 Widget _buildCancelButton(BuildContext context) { - return Column( - children: [ - SizedBox(height: TDTheme.of(context).spacer8), - GestureDetector( - onTap: () { - onCancel?.call(); - Navigator.maybePop(context); - }, - child: Container( - color: TDTheme.of(context).fontWhColor1, - height: 48, - child: Center( - child: TDText( - cancelText, - font: TDTheme.of(context).fontBodyLarge, - textColor: TDTheme.of(context).fontGyColor1, + return GestureDetector( + onTap: () { + onCancel?.call(); + Navigator.maybePop(context); + }, + child: Column( + children: [ + Container( + color: TDTheme.of(context).bgColorContainer, + height: 48, + margin: EdgeInsets.only(top: TDTheme.of(context).spacer8), + child: Center( + child: TDText( + cancelText ?? context.resource.cancel, + font: TDTheme.of(context).fontBodyLarge, + textColor: TDTheme.of(context).textColorPrimary, + ), ), ), - ), - ), - ], - ); + useSafeArea + ? Container( + color: TDTheme.of(context).bgColorContainer, + height: MediaQuery.of(context).padding.bottom, + ) + : const SizedBox.shrink(), + ], + )); } } diff --git a/tdesign-component/lib/src/components/avatar/td_avatar.dart b/tdesign-component/lib/src/components/avatar/td_avatar.dart index 5997f7008..5a61b0137 100644 --- a/tdesign-component/lib/src/components/avatar/td_avatar.dart +++ b/tdesign-component/lib/src/components/avatar/td_avatar.dart @@ -3,18 +3,9 @@ import '../../../tdesign_flutter.dart'; enum TDAvatarSize { large, medium, small } -enum TDAvatarType { - icon, - normal, - customText, - display, - operation -} +enum TDAvatarType { icon, normal, customText, display, operation } -enum TDAvatarShape { - circle, - square -} +enum TDAvatarShape { circle, square } /// 用于头像显示 class TDAvatar extends StatelessWidget { @@ -66,13 +57,13 @@ class TDAvatar extends StatelessWidget { /// 默认图片(本地) final String defaultUrl; - /// 带操作\展示的头像列表 + /// 带操作展示的头像列表 final List? avatarDisplayList; - /// 带操作\展示的头像列表 (本地资源) + /// 带操作展示的头像列表(本地资源) final List? avatarDisplayListAsset; - /// 带操作\展示的头像描边宽度 + /// 带操作展示的头像描边宽度 final double avatarDisplayBorder; /// 带操作头像自定义操作Widget @@ -90,7 +81,6 @@ class TDAvatar extends StatelessWidget { /// 自定义图片对齐方式 final BoxFit? fit; - double _getAvatarWidth() { double width; switch (size) { @@ -161,11 +151,15 @@ class TDAvatar extends StatelessWidget { width: _getAvatarWidth(), height: _getAvatarWidth(), decoration: BoxDecoration( - color: backgroundColor ?? TDTheme.of(context).brandColor2, + color: backgroundColor ?? TDTheme.of(context).brandFocusColor, borderRadius: BorderRadius.circular(_getAvatarRadius(context)), ), child: Center( - child: Icon(icon ?? TDIcons.user, size: _getIconWidth(), color: TDTheme.of(context).brandNormalColor)), + child: Icon( + icon ?? TDIcons.user, + size: _getIconWidth(), + color: TDTheme.of(context).brandNormalColor, + )), ), onTap: onTap, ); @@ -175,13 +169,13 @@ class TDAvatar extends StatelessWidget { width: _getAvatarWidth(), height: _getAvatarWidth(), decoration: BoxDecoration( - color: backgroundColor ?? TDTheme.of(context).brandColor2, + color: backgroundColor ?? TDTheme.of(context).brandFocusColor, borderRadius: BorderRadius.circular(_getAvatarRadius(context)), image: avatarUrl != null ? DecorationImage(image: NetworkImage(avatarUrl!)) : defaultUrl != '' - ? DecorationImage(image: AssetImage(defaultUrl)) - : null), + ? DecorationImage(image: AssetImage(defaultUrl)) + : null), ), onTap: onTap, ); @@ -246,23 +240,24 @@ class TDAvatar extends StatelessWidget { list.add(Positioned( left: left, child: GestureDetector( - onTap: () { - if (onTap != null) { - onTap!(); - } - }, + onTap: onTap, child: Container( child: Center( - child: Icon(TDIcons.user_add, size: _getIconWidth(), color: TDTheme.of(context).brandNormalColor), + child: Icon(TDIcons.user_add, + size: _getIconWidth(), + color: TDTheme.of(context).brandNormalColor), ), width: _getAvatarWidth(), height: _getAvatarWidth(), clipBehavior: Clip.hardEdge, decoration: ShapeDecoration( - color: TDTheme.of(context).brandColor2, + color: TDTheme.of(context).brandFocusColor, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(_getAvatarWidth() - _getDisplayPadding()), - side: BorderSide(color: Colors.white, width: avatarDisplayBorder)), + borderRadius: BorderRadius.circular( + _getAvatarWidth() - _getDisplayPadding()), + side: BorderSide( + color: Colors.transparent, + width: avatarDisplayBorder)), )), ))); } else { @@ -274,9 +269,14 @@ class TDAvatar extends StatelessWidget { clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(_getAvatarWidth() - _getDisplayPadding()), - side: BorderSide(color: Colors.white, width: avatarDisplayBorder)), - image: DecorationImage(image: NetworkImage(avatarDisplayList![i]), fit:fit??BoxFit.cover))))); + borderRadius: BorderRadius.circular( + _getAvatarWidth() - _getDisplayPadding()), + side: BorderSide( + color: TDTheme.of(context).bgColorContainer, + width: avatarDisplayBorder)), + image: DecorationImage( + image: NetworkImage(avatarDisplayList![i]), + fit: fit ?? BoxFit.cover))))); } } } else if (avatarDisplayListAsset != null) { @@ -287,24 +287,25 @@ class TDAvatar extends StatelessWidget { list.add(Positioned( left: left, child: GestureDetector( - onTap: () { - if (onTap != null) { - onTap!(); - } - }, + onTap: onTap, child: Container( child: Center( child: avatarDisplayWidget ?? - Icon(TDIcons.user_add, size: _getIconWidth(), color: TDTheme.of(context).brandNormalColor), + Icon(TDIcons.user_add, + size: _getIconWidth(), + color: TDTheme.of(context).brandNormalColor), ), width: _getAvatarWidth(), height: _getAvatarWidth(), clipBehavior: Clip.hardEdge, decoration: ShapeDecoration( - color: TDTheme.of(context).brandColor2, + color: TDTheme.of(context).brandFocusColor, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(_getAvatarWidth() - _getDisplayPadding()), - side: BorderSide(color: Colors.white, width: avatarDisplayBorder)), + borderRadius: BorderRadius.circular( + _getAvatarWidth() - _getDisplayPadding()), + side: BorderSide( + color: TDTheme.of(context).bgColorContainer, + width: avatarDisplayBorder)), )), ))); } else { @@ -316,9 +317,14 @@ class TDAvatar extends StatelessWidget { clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(_getAvatarWidth() - _getDisplayPadding()), - side: BorderSide(color: Colors.white, width: avatarDisplayBorder)), - image: DecorationImage(image: AssetImage(avatarDisplayListAsset![i]), fit:fit?? BoxFit.fill))))); + borderRadius: BorderRadius.circular( + _getAvatarWidth() - _getDisplayPadding()), + side: BorderSide( + color: TDTheme.of(context).bgColorContainer, + width: avatarDisplayBorder)), + image: DecorationImage( + image: AssetImage(avatarDisplayListAsset![i]), + fit: fit ?? BoxFit.fill))))); } } } @@ -361,10 +367,13 @@ class TDAvatar extends StatelessWidget { height: _getAvatarWidth(), clipBehavior: Clip.hardEdge, decoration: ShapeDecoration( - color: TDTheme.of(context).brandColor2, + color: TDTheme.of(context).brandFocusColor, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(_getAvatarWidth() - _getDisplayPadding()), - side: BorderSide(color: Colors.white, width: avatarDisplayBorder)), + borderRadius: BorderRadius.circular( + _getAvatarWidth() - _getDisplayPadding()), + side: BorderSide( + color: TDTheme.of(context).bgColorContainer, + width: avatarDisplayBorder)), )))); } else { list.add(Positioned( @@ -375,9 +384,14 @@ class TDAvatar extends StatelessWidget { clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(_getAvatarWidth() - _getDisplayPadding()), - side: BorderSide(color: Colors.white, width: avatarDisplayBorder)), - image: DecorationImage(image: NetworkImage(avatarDisplayList![i]), fit:fit??BoxFit.cover))))); + borderRadius: BorderRadius.circular( + _getAvatarWidth() - _getDisplayPadding()), + side: BorderSide( + color: TDTheme.of(context).bgColorContainer, + width: avatarDisplayBorder)), + image: DecorationImage( + image: NetworkImage(avatarDisplayList![i]), + fit: fit ?? BoxFit.cover))))); } } } else if (avatarDisplayListAsset != null) { @@ -402,10 +416,13 @@ class TDAvatar extends StatelessWidget { height: _getAvatarWidth(), clipBehavior: Clip.hardEdge, decoration: ShapeDecoration( - color: TDTheme.of(context).brandColor2, + color: TDTheme.of(context).brandFocusColor, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(_getAvatarWidth() - _getDisplayPadding()), - side: BorderSide(color: Colors.white, width: avatarDisplayBorder)), + borderRadius: BorderRadius.circular( + _getAvatarWidth() - _getDisplayPadding()), + side: BorderSide( + color: TDTheme.of(context).bgColorContainer, + width: avatarDisplayBorder)), )))); } else { list.add(Positioned( @@ -416,9 +433,14 @@ class TDAvatar extends StatelessWidget { clipBehavior: Clip.antiAlias, decoration: ShapeDecoration( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(_getAvatarWidth() - _getDisplayPadding()), - side: BorderSide(color: Colors.white, width: avatarDisplayBorder)), - image: DecorationImage(image: AssetImage(avatarDisplayListAsset![i]), fit:fit??BoxFit.cover))))); + borderRadius: BorderRadius.circular( + _getAvatarWidth() - _getDisplayPadding()), + side: BorderSide( + color: TDTheme.of(context).bgColorContainer, + width: avatarDisplayBorder)), + image: DecorationImage( + image: AssetImage(avatarDisplayListAsset![i]), + fit: fit ?? BoxFit.cover))))); } } } diff --git a/tdesign-component/lib/src/components/backtop/td_backtop.dart b/tdesign-component/lib/src/components/backtop/td_backtop.dart index 875651b7f..8219e989d 100644 --- a/tdesign-component/lib/src/components/backtop/td_backtop.dart +++ b/tdesign-component/lib/src/components/backtop/td_backtop.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; import '../../util/context_extension.dart'; - enum TDBackTopTheme { light, // 明亮主题 dark // 暗黑主题 @@ -44,50 +43,86 @@ class TDBackTop extends StatefulWidget { } class _TDBackTopState extends State { + bool _isAnimating = false; + + late final Color _bgColor; + late final Color _borderColor; + late final Color _fontColor; + + @override + void initState() { + super.initState(); + _initColors(); + } + + void _initColors() { + final theme = TDTheme.of(context); + _bgColor = _getColorByTheme( + lightColor: theme.grayColor1, + darkColor: theme.grayColor13, + ); + _borderColor = _getColorByTheme( + lightColor: theme.grayColor4, + darkColor: theme.grayColor9, + ); + _fontColor = _getColorByTheme( + lightColor: theme.textColorPrimary, + darkColor: theme.textColorAnti, + ); + } + + Color _getColorByTheme({ + required Color lightColor, + required Color darkColor, + }) { + return widget.theme == TDBackTopTheme.light ? lightColor : darkColor; + } + @override Widget build(BuildContext context) { return GestureDetector( - onTap: () { - if (widget.controller != null && widget.controller!.hasClients) { - widget.controller!.animateTo(0, - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn); - } - - if (widget.onClick != null) { - widget.onClick!(); - } - }, + onTap: _handleTap, child: widget.style == TDBackTopStyle.circle ? _buildCircleWidget(context) : _buildHalfCircleWidget(context), ); } - Widget _buildCircleWidget(BuildContext context) { - var color = widget.theme == TDBackTopTheme.dark - ? Colors.white - : const Color.fromRGBO(0, 0, 0, 0.9); + Future _handleTap() async { + /// 防抖处理,防止短时间内重复触发 + if (_isAnimating) { + return; + } + + if (widget.controller != null && widget.controller!.hasClients) { + _isAnimating = true; + await widget.controller!.animateTo( + 0, + duration: const Duration(milliseconds: 500), + curve: Curves.easeIn, + ); + _isAnimating = false; + } + + widget.onClick?.call(); + } + Widget _buildCircleWidget(BuildContext context) { return Container( width: 48, height: 48, - padding: EdgeInsets.symmetric( - vertical: widget.showText ? 6 : 13), + padding: EdgeInsets.symmetric(vertical: widget.showText ? 6 : 13), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(999), - border:Border.all(color: widget.theme== TDBackTopTheme.dark? TDTheme.of(context).grayColor14 :TDTheme.of(context).grayColor4,width: 0.5), - color: widget.theme == TDBackTopTheme.light - ? Colors.white - : TDTheme.of(context).grayColor14), - + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusCircle), + border: Border.all(color: _borderColor, width: 0.5), + color: _bgColor), child: Center( child: Column( children: [ Icon( TDIcons.backtop, size: 20, - color: color, + color: _fontColor, ), Visibility( visible: widget.showText, @@ -96,7 +131,7 @@ class _TDBackTopState extends State { maxLines: 1, overflow: TextOverflow.visible, style: TextStyle( - fontSize: 10, color: color, fontWeight: FontWeight.w600), + fontSize: 10, color: _fontColor, fontWeight: FontWeight.w600), ), ) ], @@ -105,25 +140,18 @@ class _TDBackTopState extends State { } Widget _buildHalfCircleWidget(BuildContext context) { - var color = widget.theme == TDBackTopTheme.dark - ? Colors.white - : const Color.fromRGBO(0, 0, 0, 0.9); - return ConstrainedBox( constraints: const BoxConstraints(minWidth: 38), child: Container( height: 40, padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( - color: widget.theme == TDBackTopTheme.light - ? Colors.white - : TDTheme.of(context).grayColor14, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(999), - bottomLeft: Radius.circular(999) - ), - border:Border.all(color: widget.theme== TDBackTopTheme.dark?Color.fromRGBO(94, 94, 94, 1):Color.fromRGBO(220, 220, 220, 1),width: 0.5) - ), + color: _bgColor, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(TDTheme.of(context).radiusCircle), + bottomLeft: + Radius.circular(TDTheme.of(context).radiusCircle)), + border: Border.all(color: _borderColor, width: 0.5)), child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, @@ -131,7 +159,7 @@ class _TDBackTopState extends State { Icon( TDIcons.backtop, size: 22, - color: color, + color: _fontColor, ), const SizedBox( width: 2, @@ -141,15 +169,16 @@ class _TDBackTopState extends State { child: SizedBox( height: 32, child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ + /// todo 将 “返回”、“顶部” 两个文本拆分开组合,中文语境下可以,但对于其他语言未必可行 TDText( context.resource.back, style: TextStyle( height: 1.2, fontSize: 10, - color: color, + color: _fontColor, fontWeight: FontWeight.w600), ), TDText( @@ -157,7 +186,7 @@ class _TDBackTopState extends State { style: TextStyle( height: 1.2, fontSize: 10, - color: color, + color: _fontColor, fontWeight: FontWeight.w600), ), ], diff --git a/tdesign-component/lib/src/components/badge/td_badge.dart b/tdesign-component/lib/src/components/badge/td_badge.dart index 8ef1cbee0..91c623220 100644 --- a/tdesign-component/lib/src/components/badge/td_badge.dart +++ b/tdesign-component/lib/src/components/badge/td_badge.dart @@ -40,20 +40,21 @@ enum TDBadgeSize { } class TDBadge extends StatefulWidget { - const TDBadge(this.type, - {Key? key, - this.count, - this.maxCount = '99', - this.border = TDBadgeBorder.large, - this.size = TDBadgeSize.small, - this.color, - this.textColor, - this.message, - this.widthLarge = 32, - this.widthSmall = 12, - this.padding, - this.showZero = true}) - : super(key: key); + const TDBadge( + this.type, { + Key? key, + this.count, + this.maxCount = '99', + this.border = TDBadgeBorder.large, + this.size = TDBadgeSize.small, + this.color, + this.textColor, + this.message, + this.widthLarge = 32, + this.widthSmall = 12, + this.padding, + this.showZero = true, + }) : super(key: key); /// 红点数量 final String? count; @@ -132,26 +133,33 @@ class _TDBadgeState extends State { } } - bool isVisible() { - var value = getValue(); - try { - return widget.showZero || double.parse(value) != 0; - } catch (e) { - return true; - } + bool get visible { + final parsedValue = double.tryParse(value); + return widget.showZero || + (parsedValue != null && parsedValue != 0) || + parsedValue == null; } - String getValue() { - return ((widget.message ?? '').isNotEmpty - ? widget.message - : (widget.count ?? '').isNotEmpty - ? widget.count - : context.resource.badgeZero) as String; + String get value { + return widget.message ?? widget.count ?? context.resource.badgeZero; } @override - Widget build(BuildContext context) { + void initState() { + super.initState(); updateBadgeNum(widget.count); + } + + @override + void didUpdateWidget(covariant TDBadge oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.count != widget.count) { + updateBadgeNum(widget.count); + } + } + + @override + Widget build(BuildContext context) { switch (widget.type) { case TDBadgeType.redPoint: return Container( @@ -159,18 +167,19 @@ class _TDBadgeState extends State { height: getBadgeSize() / 2, width: getBadgeSize() / 2, decoration: BoxDecoration( - color: widget.color ?? TDTheme.of(context).errorColor6, + color: widget.color ?? TDTheme.of(context).errorNormalColor, borderRadius: BorderRadius.circular(getBadgeSize() / 4)), ); case TDBadgeType.message: return Visibility( - visible: isVisible(), + visible: visible, child: badgeNum.length == 1 ? Container( height: getBadgeSize(), width: getBadgeSize(), decoration: BoxDecoration( - color: widget.color ?? TDTheme.of(context).errorColor6, + color: + widget.color ?? TDTheme.of(context).errorNormalColor, borderRadius: BorderRadius.circular(getBadgeSize() / 2), ), child: Center( @@ -179,8 +188,8 @@ class _TDBadgeState extends State { forceVerticalCenter: true, font: getBadgeFont(context), fontWeight: FontWeight.w500, - textColor: - widget.textColor ?? TDTheme.of(context).whiteColor1, + textColor: widget.textColor ?? + TDTheme.of(context).textColorAnti, textAlign: TextAlign.center, ), )) @@ -188,7 +197,8 @@ class _TDBadgeState extends State { height: getBadgeSize(), padding: const EdgeInsets.only(left: 5, right: 5), decoration: BoxDecoration( - color: widget.color ?? TDTheme.of(context).errorColor6, + color: + widget.color ?? TDTheme.of(context).errorNormalColor, borderRadius: BorderRadius.circular(getBadgeSize() / 2), ), child: Center( @@ -197,18 +207,18 @@ class _TDBadgeState extends State { forceVerticalCenter: true, font: getBadgeFont(context), fontWeight: FontWeight.w500, - textColor: - widget.textColor ?? TDTheme.of(context).whiteColor1, + textColor: widget.textColor ?? + TDTheme.of(context).textColorAnti, textAlign: TextAlign.center, ), - ), - )); + ), + )); case TDBadgeType.subscript: return ClipPath( clipper: TrapezoidPath(widget.widthLarge, widget.widthSmall), child: Container( alignment: Alignment.topRight, - color: widget.color ?? TDTheme.of(context).errorColor6, + color: widget.color ?? TDTheme.of(context).errorNormalColor, height: 32, width: 32, child: Transform.rotate( @@ -221,7 +231,7 @@ class _TDBadgeState extends State { font: getBadgeFont(context), fontWeight: FontWeight.w500, textColor: - widget.textColor ?? TDTheme.of(context).whiteColor1, + widget.textColor ?? TDTheme.of(context).textColorAnti, textAlign: TextAlign.center, ), )), @@ -229,12 +239,12 @@ class _TDBadgeState extends State { ); case TDBadgeType.bubble: return Visibility( - visible: isVisible(), + visible: visible, child: Container( height: 16, padding: const EdgeInsets.only(left: 4, right: 4), decoration: BoxDecoration( - color: widget.color ?? TDTheme.of(context).errorColor6, + color: widget.color ?? TDTheme.of(context).errorNormalColor, borderRadius: const BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), @@ -248,38 +258,36 @@ class _TDBadgeState extends State { font: getBadgeFont(context), fontWeight: FontWeight.w500, textColor: - widget.textColor ?? TDTheme.of(context).whiteColor1, + widget.textColor ?? TDTheme.of(context).textColorAnti, textAlign: TextAlign.center, ), ), )); case TDBadgeType.square: return Visibility( - visible: isVisible(), + visible: visible, child: IntrinsicWidth( child: Container( - height: getBadgeSize(), - padding: const EdgeInsets.only(left: 5, right: 5), - decoration: BoxDecoration( - color: widget.color ?? TDTheme.of(context).errorColor6, - borderRadius: widget.border == TDBadgeBorder.large - ? BorderRadius.circular(8) - : BorderRadius.circular(2), - ), - child: Center( - child: TDText( - widget.message ?? '$badgeNum', - forceVerticalCenter: true, - font: getBadgeFont(context), - fontWeight: FontWeight.w500, - textColor: - widget.textColor ?? TDTheme.of(context).whiteColor1, - textAlign: TextAlign.center, - ), - ), - ) - ) - ); + height: getBadgeSize(), + padding: const EdgeInsets.only(left: 5, right: 5), + decoration: BoxDecoration( + color: widget.color ?? TDTheme.of(context).errorNormalColor, + borderRadius: widget.border == TDBadgeBorder.large + ? BorderRadius.circular(8) + : BorderRadius.circular(2), + ), + child: Center( + child: TDText( + widget.message ?? '$badgeNum', + forceVerticalCenter: true, + font: getBadgeFont(context), + fontWeight: FontWeight.w500, + textColor: + widget.textColor ?? TDTheme.of(context).textColorAnti, + textAlign: TextAlign.center, + ), + ), + ))); } } } @@ -298,6 +306,7 @@ class TrapezoidPath extends CustomClipper { path.lineTo(widthLarge, widthSmall); path.lineTo(widthLarge, widthLarge); path.lineTo(0, 0); + path.close(); return path; } diff --git a/tdesign-component/lib/src/components/button/td_button.dart b/tdesign-component/lib/src/components/button/td_button.dart index d9861f45e..035e57f7a 100644 --- a/tdesign-component/lib/src/components/button/td_button.dart +++ b/tdesign-component/lib/src/components/button/td_button.dart @@ -18,32 +18,32 @@ typedef TDButtonEvent = void Function(); /// TD常规按钮 class TDButton extends StatefulWidget { - const TDButton( - {Key? key, - this.text, - this.size = TDButtonSize.medium, - this.type = TDButtonType.fill, - this.shape = TDButtonShape.rectangle, - this.theme, - this.child, - this.disabled = false, - this.isBlock = false, - this.style, - this.activeStyle, - this.disableStyle, - this.textStyle, - this.disableTextStyle, - this.width, - this.height, - this.onTap, - this.icon, - this.iconWidget, - this.iconTextSpacing, - this.onLongPress, - this.margin, - this.padding, - this.iconPosition = TDButtonIconPosition.left}) - : super(key: key); + const TDButton({ + Key? key, + this.text, + this.size = TDButtonSize.medium, + this.type = TDButtonType.fill, + this.shape = TDButtonShape.rectangle, + this.theme, + this.child, + this.disabled = false, + this.isBlock = false, + this.style, + this.activeStyle, + this.disableStyle, + this.textStyle, + this.disableTextStyle, + this.width, + this.height, + this.onTap, + this.icon, + this.iconWidget, + this.iconTextSpacing, + this.onLongPress, + this.margin, + this.padding, + this.iconPosition = TDButtonIconPosition.left, + }) : super(key: key); /// 自控件 final Widget? child; @@ -72,13 +72,13 @@ class TDButton extends StatefulWidget { /// 主题 final TDButtonTheme? theme; - /// 自定义样式,有则优先用它,没有则根据type和theme选取.如果设置了style,则activeStyle和disableStyle也应该设置 + /// 自定义样式,有则优先用它,没有则根据 type 和 theme 选取。如果设置了 style,则 activeStyle 和 disableStyle 也应该设置 final TDButtonStyle? style; - /// 自定义点击样式,有则优先用它,没有则根据type和theme选取 + /// 自定义点击样式,有则优先用它,没有则根据 type 和 theme 选取 final TDButtonStyle? activeStyle; - /// 自定义禁用样式,有则优先用它,没有则根据type和theme选取 + /// 自定义禁用样式,有则优先用它,没有则根据 type 和 theme 选取 final TDButtonStyle? disableStyle; /// 自定义可点击状态文本样式 @@ -96,19 +96,19 @@ class TDButton extends StatefulWidget { /// 图标icon final IconData? icon; - /// 自定义图标icon控件 + /// 自定义图标 icon 控件 final Widget? iconWidget; - /// 自定义图标与文本之间距离 + /// 自定义图标与文本之间距离 final double? iconTextSpacing; /// 图标位置 final TDButtonIconPosition? iconPosition; - /// 自定义padding + /// 自定义 padding final EdgeInsetsGeometry? padding; - /// 自定义margin + /// 自定义 margin final EdgeInsetsGeometry? margin; /// 是否为通栏按钮 @@ -130,7 +130,7 @@ class _TDButtonState extends State { TextStyle? _textStyle; double? _iconSize; - _updateParams() async { + _updateParams() { _buttonStatus = widget.disabled ? TDButtonStatus.disable : TDButtonStatus.defaultState; _innerDefaultStyle = widget.style; @@ -221,7 +221,7 @@ class _TDButtonState extends State { Border? _getBorder(BuildContext context) { if (style.frameWidth != null && style.frameWidth != 0) { return Border.all( - color: style.frameColor ?? TDTheme.of(context).grayColor3, + color: style.frameColor ?? TDTheme.of(context).componentStrokeColor, width: style.frameWidth!, ); } @@ -229,7 +229,7 @@ class _TDButtonState extends State { } Widget _getChild() { - var icon = getIcon(); + var icon = _getIcon(); if (widget.text == null && icon == null) { return Container(); } @@ -242,7 +242,7 @@ class _TDButtonState extends State { var text = TDText( widget.text!, font: _getTextFont(), - textColor: style.textColor ?? TDTheme.of(context).fontGyColor1, + textColor: style.textColor ?? TDTheme.of(context).textColorPrimary, style: _textStyle, forceVerticalCenter: true, ); @@ -255,9 +255,7 @@ class _TDButtonState extends State { if (children.length == 2) { children.insert( 1, - SizedBox( - width:widget.iconTextSpacing??8, - ), + SizedBox(width: widget.iconTextSpacing ?? 8), ); } return Row( @@ -267,11 +265,16 @@ class _TDButtonState extends State { ); } - Widget? getIcon() { + Widget? _getIcon() { if (widget.iconWidget != null) { return widget.iconWidget; } if (widget.icon != null) { + return Icon( + widget.icon, + size: _iconSize, + color: style.textColor, + ); return RichText( overflow: TextOverflow.visible, text: TextSpan( @@ -287,6 +290,7 @@ class _TDButtonState extends State { ), ); } + return null; } @@ -361,7 +365,7 @@ class _TDButtonState extends State { if (widget.margin != null) { return widget.margin; } - return widget.isBlock ? const EdgeInsets.only(left: 16, right: 16) : null; + return widget.isBlock ? const EdgeInsets.symmetric(horizontal: 16) : null; } EdgeInsetsGeometry? _getPadding() { diff --git a/tdesign-component/lib/src/components/button/td_button_style.dart b/tdesign-component/lib/src/components/button/td_button_style.dart index 131674b13..454b241fa 100644 --- a/tdesign-component/lib/src/components/button/td_button_style.dart +++ b/tdesign-component/lib/src/components/button/td_button_style.dart @@ -19,17 +19,19 @@ class TDButtonStyle { /// 自定义圆角 BorderRadiusGeometry? radius; - TDButtonStyle({this.backgroundColor, this.frameColor, this.textColor, this.frameWidth, this.radius}); + TDButtonStyle( + {this.backgroundColor, this.frameColor, this.textColor, this.frameWidth, this.radius}); /// 生成不同主题的填充按钮样式 - TDButtonStyle.generateFillStyleByTheme(BuildContext context, TDButtonTheme? theme, TDButtonStatus status) { + TDButtonStyle.generateFillStyleByTheme( + BuildContext context, TDButtonTheme? theme, TDButtonStatus status) { switch (theme) { case TDButtonTheme.primary: - textColor = TDTheme.of(context).fontWhColor1; + textColor = TDTheme.of(context).textColorAnti; backgroundColor = _getBrandColor(context, status); break; case TDButtonTheme.danger: - textColor = TDTheme.of(context).fontWhColor1; + textColor = TDTheme.of(context).textColorAnti; backgroundColor = _getErrorColor(context, status); break; case TDButtonTheme.light: @@ -45,18 +47,21 @@ class TDButtonStyle { } /// 生成不同主题的描边按钮样式 - TDButtonStyle.generateOutlineStyleByTheme(BuildContext context, TDButtonTheme? theme, TDButtonStatus status) { + TDButtonStyle.generateOutlineStyleByTheme( + BuildContext context, TDButtonTheme? theme, TDButtonStatus status) { switch (theme) { case TDButtonTheme.primary: textColor = _getBrandColor(context, status); - backgroundColor = - status == TDButtonStatus.active ? TDTheme.of(context).grayColor3 : TDTheme.of(context).whiteColor1; + backgroundColor = status == TDButtonStatus.active + ? TDTheme.of(context).bgColorContainerActive + : Colors.transparent; frameColor = textColor; break; case TDButtonTheme.danger: textColor = _getErrorColor(context, status); - backgroundColor = - status == TDButtonStatus.active ? TDTheme.of(context).grayColor3 : TDTheme.of(context).whiteColor1; + backgroundColor = status == TDButtonStatus.active + ? TDTheme.of(context).bgColorContainerActive + : Colors.transparent; frameColor = textColor; break; case TDButtonTheme.light: @@ -68,48 +73,52 @@ class TDButtonStyle { default: textColor = _getDefaultTextColor(context, status); backgroundColor = _getOutlineDefaultBgColor(context, status); - frameColor = TDTheme.of(context).grayColor4; + frameColor = TDTheme.of(context).componentBorderColor; } frameWidth = 1; } /// 生成不同主题的文本按钮样式 - TDButtonStyle.generateTextStyleByTheme(BuildContext context, TDButtonTheme? theme, TDButtonStatus status) { + TDButtonStyle.generateTextStyleByTheme( + BuildContext context, TDButtonTheme? theme, TDButtonStatus status) { switch (theme) { case TDButtonTheme.primary: textColor = _getBrandColor(context, status); - backgroundColor = status == TDButtonStatus.active ? TDTheme.of(context).grayColor3 : Colors.transparent; break; case TDButtonTheme.danger: textColor = _getErrorColor(context, status); - backgroundColor = status == TDButtonStatus.active ? TDTheme.of(context).grayColor3 : Colors.transparent; break; case TDButtonTheme.light: textColor = _getBrandColor(context, status); - backgroundColor = status == TDButtonStatus.active ? TDTheme.of(context).grayColor3 : Colors.transparent; break; case TDButtonTheme.defaultTheme: default: textColor = _getDefaultTextColor(context, status); - backgroundColor = status == TDButtonStatus.active ? TDTheme.of(context).grayColor3 : Colors.transparent; } + backgroundColor = status == TDButtonStatus.active + ? TDTheme.of(context).bgColorContainerActive + : Colors.transparent; frameColor = backgroundColor; } /// 生成不同主题的幽灵按钮样式 - TDButtonStyle.generateGhostStyleByTheme(BuildContext context, TDButtonTheme? theme, TDButtonStatus status) { + TDButtonStyle.generateGhostStyleByTheme( + BuildContext context, TDButtonTheme? theme, TDButtonStatus status) { switch (theme) { case TDButtonTheme.primary: - textColor = - status == TDButtonStatus.disable ? TDTheme.of(context).fontWhColor4 : _getBrandColor(context, status); + textColor = status == TDButtonStatus.disable + ? TDTheme.of(context).fontWhColor4 + : _getBrandColor(context, status); break; case TDButtonTheme.danger: - textColor = - status == TDButtonStatus.disable ? TDTheme.of(context).fontWhColor4 : _getErrorColor(context, status); + textColor = status == TDButtonStatus.disable + ? TDTheme.of(context).fontWhColor4 + : _getErrorColor(context, status); break; case TDButtonTheme.light: - textColor = - status == TDButtonStatus.disable ? TDTheme.of(context).fontWhColor4 : _getBrandColor(context, status); + textColor = status == TDButtonStatus.disable + ? TDTheme.of(context).fontWhColor4 + : _getBrandColor(context, status); break; case TDButtonTheme.defaultTheme: default: @@ -164,11 +173,11 @@ class TDButtonStyle { Color _getDefaultBgColor(BuildContext context, TDButtonStatus status) { switch (status) { case TDButtonStatus.defaultState: - return TDTheme.of(context).grayColor3; + return TDTheme.of(context).bgColorComponent; case TDButtonStatus.active: - return TDTheme.of(context).grayColor5; + return TDTheme.of(context).bgColorComponentHover; case TDButtonStatus.disable: - return TDTheme.of(context).grayColor2; + return TDTheme.of(context).bgColorComponentDisabled; } } @@ -176,20 +185,20 @@ class TDButtonStyle { switch (status) { case TDButtonStatus.defaultState: case TDButtonStatus.active: - return TDTheme.of(context).fontGyColor1; + return TDTheme.of(context).textColorPrimary; case TDButtonStatus.disable: - return TDTheme.of(context).fontGyColor4; + return TDTheme.of(context).textColorDisabled; } } Color _getOutlineDefaultBgColor(BuildContext context, TDButtonStatus status) { switch (status) { case TDButtonStatus.defaultState: - return TDTheme.of(context).whiteColor1; + return Colors.transparent; case TDButtonStatus.active: - return TDTheme.of(context).grayColor3; + return TDTheme.of(context).bgColorContainerActive; case TDButtonStatus.disable: - return TDTheme.of(context).grayColor2; + return TDTheme.of(context).bgColorComponentDisabled; } } } diff --git a/tdesign-component/lib/src/components/calendar/td_calendar.dart b/tdesign-component/lib/src/components/calendar/td_calendar.dart index 9c7a8e2ed..0e4269f1a 100644 --- a/tdesign-component/lib/src/components/calendar/td_calendar.dart +++ b/tdesign-component/lib/src/components/calendar/td_calendar.dart @@ -38,6 +38,7 @@ class TDCalendar extends StatefulWidget { this.onCellClick, this.onCellLongPress, this.onHeaderClick, + this.useSafeArea = true, this.useTimePicker = false, this.timePickerModel, this.monthTitleHeight = 22, @@ -55,10 +56,10 @@ class TDCalendar extends StatefulWidget { /// 用于格式化日期的函数,可定义日期前后的显示内容和日期样式 final CalendarFormat? format; - /// 最大可选的日期(fromMillisecondsSinceEpoch),不传则默认半年后 + /// 最大可选的日期(fromMillisecondsSinceEpoch),不传则默认半年后 final int? maxDate; - /// 最小可选的日期(fromMillisecondsSinceEpoch),不传则默认今天 + /// 最小可选的日期(fromMillisecondsSinceEpoch),不传则默认今天 final int? minDate; /// 标题 @@ -67,10 +68,10 @@ class TDCalendar extends StatefulWidget { /// 标题组件 final Widget? titleWidget; - /// 日历的选择类型,single = 单选;multiple = 多选; range = 区间选择 + /// 日历的选择类型,single = 单选;multiple = 多选;range = 区间选择 final CalendarType? type; - /// 当前选择的日期(fromMillisecondsSinceEpoch),不传则默认今天,当 type = single 时数组长度为1 + /// 当前选择的日期(fromMillisecondsSinceEpoch),不传则默认今天,当 type = single 时数组长度为1 final List? value; /// 年月显示格式,`year`表示年,`month`表示月,如`year month`表示年在前、月在后、中间隔一个空格 @@ -92,13 +93,27 @@ class TDCalendar extends StatefulWidget { final void Function(List value)? onChange; /// 点击日期时触发 - final void Function(int value, DateSelectType type, TDate tdate)? onCellClick; + final void Function( + int value, + DateSelectType type, + TDate tdate, + )? onCellClick; /// 长安日期时触发 - final void Function(int value, DateSelectType type, TDate tdate)? onCellLongPress; + final void Function( + int value, + DateSelectType type, + TDate tdate, + )? onCellLongPress; /// 点击周时触发 - final void Function(int index, String week)? onHeaderClick; + final void Function( + int index, + String week, + )? onHeaderClick; + + /// 是否使用安全区域,默认true + final bool? useSafeArea; /// 是否显示时间选择器 final bool? useTimePicker; @@ -110,7 +125,10 @@ class TDCalendar extends StatefulWidget { final double? monthTitleHeight; /// 月标题构建器 - final Widget Function(BuildContext context, DateTime monthDate)? monthTitleBuilder; + final Widget Function( + BuildContext context, + DateTime monthDate, + )? monthTitleBuilder; /// 时间选择器List的视窗高度 final double? pickerHeight; @@ -125,7 +143,11 @@ class TDCalendar extends StatefulWidget { final bool? animateTo; /// 自定义日期单元格组件 - final Widget? Function(BuildContext context, TDate tdate, DateSelectType selectType)? cellWidget; + final Widget? Function( + BuildContext context, + TDate tdate, + DateSelectType selectType, + )? cellWidget; List? get _value => value?.map((e) { final date = DateTime.fromMillisecondsSinceEpoch(e); @@ -248,7 +270,10 @@ class _TDCalendarState extends State { if (inherited?.usePopup == true) inherited?.confirmBtn ?? Padding( - padding: EdgeInsets.symmetric(vertical: TDTheme.of(context).spacer16), + padding: widget.useSafeArea == true + ? EdgeInsets.only(top: TDTheme.of(context).spacer16) + : EdgeInsets.symmetric( + vertical: TDTheme.of(context).spacer16), child: TDButton( theme: TDButtonTheme.primary, text: context.resource.confirm, @@ -257,6 +282,8 @@ class _TDCalendarState extends State { onTap: inherited?.onConfirm, ), ), + if (widget.useSafeArea == true) + SizedBox(height: MediaQuery.of(context).padding.bottom) ], ), ); @@ -268,7 +295,7 @@ class _TDCalendarState extends State { final valueTime = widget._valueTime; return Container( decoration: BoxDecoration( - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, boxShadow: const [ BoxShadow( color: Color.fromRGBO(0, 0, 0, 0.04), @@ -335,9 +362,15 @@ class _TDCalendarState extends State { return dateValue; } final milliseconds = timePickerModelList.map((model) { - final hour = model.useHour ? model.hourFixedExtentScrollController.selectedItem : 0; - final minute = model.useMinute ? model.minuteFixedExtentScrollController.selectedItem : 0; - final second = model.useSecond ? model.secondFixedExtentScrollController.selectedItem : 0; + final hour = model.useHour + ? model.hourFixedExtentScrollController.selectedItem + : 0; + final minute = model.useMinute + ? model.minuteFixedExtentScrollController.selectedItem + : 0; + final second = model.useSecond + ? model.secondFixedExtentScrollController.selectedItem + : 0; return (hour * 60 * 60 + minute * 60 + second) * 1000; }).toList(); if (widget.type == CalendarType.range && dateValue.length == 1) { diff --git a/tdesign-component/lib/src/components/calendar/td_calendar_body.dart b/tdesign-component/lib/src/components/calendar/td_calendar_body.dart index c84eca04c..fe7bd2ae7 100644 --- a/tdesign-component/lib/src/components/calendar/td_calendar_body.dart +++ b/tdesign-component/lib/src/components/calendar/td_calendar_body.dart @@ -32,12 +32,20 @@ class TDCalendarBody extends StatelessWidget { final List? value; final int firstDayOfWeek; final Widget Function( - TDate? date, List dateList, Map> data, int rowIndex, int colIndex) builder; + TDate? date, + List dateList, + Map> data, + int rowIndex, + int colIndex, + ) builder; final double bodyPadding; final String displayFormat; final List monthNames; final TextStyle? monthTitleStyle; - final Widget Function(BuildContext context, DateTime monthDate)? monthTitleBuilder; + final Widget Function( + BuildContext context, + DateTime monthDate, + )? monthTitleBuilder; final double monthTitleHeight; final double verticalGap; final double cellHeight; @@ -56,12 +64,15 @@ class TDCalendarBody extends StatelessWidget { padding: EdgeInsets.all(bodyPadding), controller: scrollController, itemCount: months.length, - itemExtentBuilder: (index, dimensions) => _getMonthHeight(months, index, monthHeight), + itemExtentBuilder: (index, dimensions) => + _getMonthHeight(months, index, monthHeight), itemBuilder: (context, index) { final monthDate = months[index]; final monthYear = monthDate.year.toString() + context.resource.year; final monthMonth = monthNames[monthDate.month - 1]; - final monthDateText = displayFormat.replaceFirst('year', monthYear).replaceFirst('month', monthMonth); + final monthDateText = displayFormat + .replaceFirst('year', monthYear) + .replaceFirst('month', monthMonth); late List monthData; if (data.containsKey(monthDate)) { monthData = data[monthDate]!; @@ -82,28 +93,30 @@ class TDCalendarBody extends StatelessWidget { children: [ SizedBox( height: monthTitleHeight, - child: monthTitleBuilder?.call(context, monthDate) ?? TDText(monthDateText, style: monthTitleStyle), + child: monthTitleBuilder?.call(context, monthDate) ?? + TDText(monthDateText, style: monthTitleStyle), ), ...List.generate( (monthData.length / 7).ceil(), (rowIndex) => [ SizedBox(height: verticalGap), Row( - children: List.generate( - 7, - (colIndex) => [ + children: [ + for (int colIndex = 0; colIndex < 7; colIndex++) ...[ if (colIndex != 0) SizedBox(width: verticalGap / 2), Expanded( child: builder( - monthData[rowIndex * 7 + colIndex], + (rowIndex * 7 + colIndex < monthData.length) + ? monthData[rowIndex * 7 + colIndex] + : null, monthData, data, rowIndex, colIndex, ), ), - ], - ).expand((element) => element).toList(), + ] + ], ), ], ).expand((element) => element).toList(), @@ -114,7 +127,8 @@ class TDCalendarBody extends StatelessWidget { ); } - void _scrollToItem(ScrollController scrollController, List months, Map monthHeight) { + void _scrollToItem(ScrollController scrollController, List months, + Map monthHeight) { if (value == null || value!.isEmpty) { return; } @@ -149,7 +163,9 @@ class TDCalendarBody extends StatelessWidget { } DateTime _getDefDate(int? date, [int? addMonth]) { - final now = date == null ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(date); + final now = date == null + ? DateTime.now() + : DateTime.fromMillisecondsSinceEpoch(date); if (addMonth == null) { return DateTime(now.year, now.month, now.day); } @@ -168,8 +184,10 @@ class TDCalendarBody extends StatelessWidget { } List _getDaysInMonth(DateTime curDate, DateTime min, DateTime max) { - final daysInMonth = List.generate(_getPreOffset(curDate), (index) => null); - final daysInMonthCount = DateTime(curDate.year, curDate.month + 1, 0).day; // 获取下个月的第一天的前一天,即当前月的最后一天 + final daysInMonth = + List.generate(_getPreOffset(curDate), (index) => null); + final daysInMonthCount = DateTime(curDate.year, curDate.month + 1, 0) + .day; // 获取下个月的第一天的前一天,即当前月的最后一天 for (var day = 1; day <= daysInMonthCount; day++) { final date = DateTime(curDate.year, curDate.month, day); var selectType = DateSelectType.empty; @@ -220,7 +238,8 @@ class TDCalendarBody extends StatelessWidget { } /// 获取月份高度,带缓存 - double _getMonthHeight(List months, int index, Map monthHeight) { + double _getMonthHeight( + List months, int index, Map monthHeight) { if (months.getOrNull(index) == null) { return 1; } @@ -232,8 +251,9 @@ class TDCalendarBody extends StatelessWidget { final preOffset = _getPreOffset(item); final daysInMonthCount = DateTime(item.year, item.month + 1, 0).day; final daysInMonth = preOffset + daysInMonthCount; - final height = - monthTitleHeight + (daysInMonth / 7).ceil() * (verticalGap + cellHeight) + (isLast ? 0 : bodyPadding); + final height = monthTitleHeight + + (daysInMonth / 7).ceil() * (verticalGap + cellHeight) + + (isLast ? 0 : bodyPadding); monthHeight[index] = height; return height; } diff --git a/tdesign-component/lib/src/components/calendar/td_calendar_cell.dart b/tdesign-component/lib/src/components/calendar/td_calendar_cell.dart index c05ae9f96..9bdd97216 100644 --- a/tdesign-component/lib/src/components/calendar/td_calendar_cell.dart +++ b/tdesign-component/lib/src/components/calendar/td_calendar_cell.dart @@ -24,8 +24,16 @@ class TDCalendarCell extends StatefulWidget { final TDate? tdate; final CalendarFormat? format; final CalendarType type; - final void Function(int value, DateSelectType type, TDate tdate)? onCellClick; - final void Function(int value, DateSelectType type, TDate tdate)? onCellLongPress; + final void Function( + int value, + DateSelectType type, + TDate tdate, + )? onCellClick; + final void Function( + int value, + DateSelectType type, + TDate tdate, + )? onCellLongPress; final void Function(List value)? onChange; final double height; final Map> data; @@ -33,7 +41,11 @@ class TDCalendarCell extends StatefulWidget { final int rowIndex; final int colIndex; final List dateList; - final Widget? Function(BuildContext context, TDate tdate, DateSelectType selectType)? cellWidget; + final Widget? Function( + BuildContext context, + TDate tdate, + DateSelectType selectType, + )? cellWidget; @override _TDCalendarCellState createState() => _TDCalendarCellState(); @@ -42,6 +54,7 @@ class TDCalendarCell extends StatefulWidget { class _TDCalendarCellState extends State { var isToday = false; var positionOffset = 0; + @override void initState() { super.initState(); @@ -76,41 +89,44 @@ class _TDCalendarCellState extends State { final positionColor = _getColor(cellStyle, decoration); // 新增自定义cell内容判断逻辑 - final content = widget.cellWidget?.call(context, tdate, widget.tdate!._type) ?? - Column( - children: [ - Expanded( - flex: 2, - child: tdate.prefixWidget ?? - TDText( - tdate.prefix ?? '', - style: tdate.prefixStyle ?? cellStyle.cellPrefixStyle, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - Expanded( - flex: 3, - child: Center( - child: TDText( - forceVerticalCenter: true, - widget.tdate!.date.day.toString(), - style: (isToday ? cellStyle.todayStyle : null) ?? tdate.style ?? cellStyle.cellStyle, + final content = + widget.cellWidget?.call(context, tdate, widget.tdate!._type) ?? + Column( + children: [ + Expanded( + flex: 2, + child: tdate.prefixWidget ?? + TDText( + tdate.prefix ?? '', + style: tdate.prefixStyle ?? cellStyle.cellPrefixStyle, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), ), - ), - ), - Expanded( - flex: 2, - child: tdate.suffixWidget ?? - TDText( - tdate.suffix ?? '', - style: tdate.suffixStyle ?? cellStyle.cellSuffixStyle, - maxLines: 1, - overflow: TextOverflow.ellipsis, + Expanded( + flex: 3, + child: Center( + child: TDText( + forceVerticalCenter: true, + widget.tdate!.date.day.toString(), + style: (isToday ? cellStyle.todayStyle : null) ?? + tdate.style ?? + cellStyle.cellStyle, + ), ), - ), - ], - ); + ), + Expanded( + flex: 2, + child: tdate.suffixWidget ?? + TDText( + tdate.suffix ?? '', + style: tdate.suffixStyle ?? cellStyle.cellSuffixStyle, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ); return GestureDetector( behavior: HitTestBehavior.translucent, @@ -153,7 +169,8 @@ class _TDCalendarCellState extends State { } switch (widget.type) { case CalendarType.single: - final date = list.find((item) => item?._type == DateSelectType.selected); + final date = + list.find((item) => item?._type == DateSelectType.selected); date?._setType(DateSelectType.empty); widget.tdate!._setType(DateSelectType.selected); if (date?._milliseconds != curDate) { @@ -161,7 +178,9 @@ class _TDCalendarCellState extends State { } break; case CalendarType.multiple: - final date = list.where((item) => item?._type == DateSelectType.selected).toList(); + final date = list + .where((item) => item?._type == DateSelectType.selected) + .toList(); final value = date.map((item) => item!._milliseconds).toList(); if (date.find((item) => item?._milliseconds == curDate) != null) { widget.tdate!._setType(DateSelectType.empty); @@ -181,7 +200,9 @@ class _TDCalendarCellState extends State { (start != null && end == null && startTimes! >= curDate)) { start?._setType(DateSelectType.empty); end?._setType(DateSelectType.empty); - final centres = list.where((item) => item?._type == DateSelectType.centre).toList(); + final centres = list + .where((item) => item?._type == DateSelectType.centre) + .toList(); centres.forEach((item) => item!._setType(DateSelectType.empty)); widget.tdate!._setType(DateSelectType.start); widget.onChange?.call([curDate]); @@ -189,7 +210,8 @@ class _TDCalendarCellState extends State { start._setType(DateSelectType.start); widget.tdate!._setType(DateSelectType.end); var startIndex = list.indexOf(start) + 1; - while (list[startIndex] == null || list[startIndex]!._milliseconds < curDate) { + while (list[startIndex] == null || + list[startIndex]!._milliseconds < curDate) { list[startIndex]?._setType(DateSelectType.centre); startIndex++; } @@ -233,7 +255,8 @@ class _TDCalendarCellState extends State { bool _isToday() { final today = DateTime.now(); - return widget.tdate?._milliseconds == DateTime(today.year, today.month, today.day).millisecondsSinceEpoch; + return widget.tdate?._milliseconds == + DateTime(today.year, today.month, today.day).millisecondsSinceEpoch; } } @@ -286,7 +309,8 @@ class TDate { /// 是否是当月最后一天 final bool isLastDayOfMonth; - int get _milliseconds => DateTime(date.year, date.month, date.day).millisecondsSinceEpoch; + int get _milliseconds => + DateTime(date.year, date.month, date.day).millisecondsSinceEpoch; DateSelectType get _type => typeNotifier.value; @@ -297,6 +321,7 @@ class TDate { class DateSelectTypeNotifier extends ChangeNotifier { DateSelectType value = DateSelectType.empty; + DateSelectTypeNotifier(DateSelectType selectType) { value = selectType; } diff --git a/tdesign-component/lib/src/components/calendar/td_calendar_header.dart b/tdesign-component/lib/src/components/calendar/td_calendar_header.dart index 589c734c0..2108ca60e 100644 --- a/tdesign-component/lib/src/components/calendar/td_calendar_header.dart +++ b/tdesign-component/lib/src/components/calendar/td_calendar_header.dart @@ -51,12 +51,12 @@ class TDCalendarHeader extends StatelessWidget { Widget build(BuildContext context) { final list = _getWeeks(context); return Container( - padding: EdgeInsets.fromLTRB(padding, 0, padding, 0), + padding: EdgeInsets.symmetric(horizontal: padding), child: Column( children: [ if (title?.isNotEmpty == true || titleWidget != null || closeBtn) Container( - padding: EdgeInsets.fromLTRB(0, padding, 0, padding), + padding: EdgeInsets.symmetric(vertical: padding), child: Row( children: [ if (closeBtn) const SizedBox(width: 24), @@ -85,8 +85,8 @@ class TDCalendarHeader extends StatelessWidget { ), ), Row( - children: List.generate(list.length, (index) { - return [ + children: [ + for (int index = 0; index < list.length; index++) ...[ if (index != 0) SizedBox(width: weekdayGap), Expanded( child: GestureDetector( @@ -104,8 +104,8 @@ class TDCalendarHeader extends StatelessWidget { ), ), ), - ]; - }).expand((element) => element).toList(), + ] + ], ), ], ), diff --git a/tdesign-component/lib/src/components/calendar/td_calendar_style.dart b/tdesign-component/lib/src/components/calendar/td_calendar_style.dart index e2b85327c..ba8b7ce9e 100644 --- a/tdesign-component/lib/src/components/calendar/td_calendar_style.dart +++ b/tdesign-component/lib/src/components/calendar/td_calendar_style.dart @@ -61,7 +61,7 @@ class TDCalendarStyle { /// 生成默认样式 TDCalendarStyle.generateStyle(BuildContext context) { decoration = BoxDecoration( - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, borderRadius: BorderRadius.vertical( top: Radius.circular(TDTheme.of(context).radiusExtraLarge), ), @@ -69,18 +69,18 @@ class TDCalendarStyle { titleStyle = TextStyle( fontSize: TDTheme.of(context).fontTitleLarge?.size, fontWeight: TDTheme.of(context).fontTitleLarge?.fontWeight, - color: TDTheme.of(context).fontGyColor1, + color: TDTheme.of(context).textColorPrimary, ); titleMaxLine = 1; titleCloseColor = titleStyle?.color; weekdayStyle = TextStyle( fontSize: TDTheme.of(context).fontTitleSmall?.size, - color: TDTheme.of(context).fontGyColor2, + color: TDTheme.of(context).textColorSecondary, ); monthTitleStyle = TextStyle( fontSize: TDTheme.of(context).fontMarkMedium?.size, fontWeight: TDTheme.of(context).fontMarkMedium?.fontWeight, - color: TDTheme.of(context).fontGyColor1, + color: TDTheme.of(context).textColorPrimary, ); verticalGap = TDTheme.of(context).spacer8; bodyPadding = TDTheme.of(context).spacer16; @@ -99,55 +99,71 @@ class TDCalendarStyle { height: TDTheme.of(context).fontBodyExtraSmall?.height, fontWeight: FontWeight.w400, ); - centreColor = TDTheme.of(context).brandColor1; + centreColor = TDTheme.of(context).brandLightColor; switch (type) { case DateSelectType.empty: - cellStyle = defStyle.copyWith(color: TDTheme.of(context).fontGyColor1); - todayStyle = defStyle.copyWith(color: TDTheme.of(context).brandColor7); - cellPrefixStyle = prefixStyle.copyWith(color: TDTheme.of(context).errorColor6); - cellSuffixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontGyColor3); + cellStyle = + defStyle.copyWith(color: TDTheme.of(context).textColorPrimary); + todayStyle = defStyle.copyWith(color: TDTheme.of(context).brandNormalColor); + cellPrefixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).errorNormalColor); + cellSuffixStyle = prefixStyle.copyWith( + color: TDTheme.of(context).textColorPlaceholder); cellDecoration = null; break; case DateSelectType.disabled: - cellStyle = defStyle.copyWith(color: TDTheme.of(context).fontGyColor4); - todayStyle = defStyle.copyWith(color: TDTheme.of(context).brandColor3); - cellPrefixStyle = prefixStyle.copyWith(color: TDTheme.of(context).errorColor3); - cellSuffixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontGyColor4); + cellStyle = + defStyle.copyWith(color: TDTheme.of(context).textColorDisabled); + todayStyle = defStyle.copyWith(color: TDTheme.of(context).brandDisabledColor); + cellPrefixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).errorDisabledColor); + cellSuffixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).textColorDisabled); cellDecoration = null; break; case DateSelectType.selected: - cellStyle = defStyle.copyWith(color: TDTheme.of(context).fontWhColor1); - cellPrefixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontWhColor1); - cellSuffixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontWhColor1); + cellStyle = defStyle.copyWith(color: TDTheme.of(context).textColorAnti); + cellPrefixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).textColorAnti); + cellSuffixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).textColorAnti); cellDecoration = BoxDecoration( borderRadius: BorderRadius.circular(radius6), - color: TDTheme.of(context).brandColor7, + color: TDTheme.of(context).brandNormalColor, ); break; case DateSelectType.centre: - cellStyle = defStyle.copyWith(color: TDTheme.of(context).fontGyColor1); - cellPrefixStyle = prefixStyle.copyWith(color: TDTheme.of(context).errorColor6); - cellSuffixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontGyColor3); + cellStyle = + defStyle.copyWith(color: TDTheme.of(context).textColorPrimary); + cellPrefixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).errorNormalColor); + cellSuffixStyle = prefixStyle.copyWith( + color: TDTheme.of(context).textColorPlaceholder); cellDecoration = BoxDecoration( color: centreColor, ); break; case DateSelectType.start: - cellStyle = defStyle.copyWith(color: TDTheme.of(context).fontWhColor1); - cellPrefixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontWhColor1); - cellSuffixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontWhColor1); + cellStyle = defStyle.copyWith(color: TDTheme.of(context).textColorAnti); + cellPrefixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).textColorAnti); + cellSuffixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).textColorAnti); cellDecoration = BoxDecoration( - color: TDTheme.of(context).brandColor7, + color: TDTheme.of(context).brandNormalColor, borderRadius: BorderRadius.horizontal(left: Radius.circular(radius6)), ); break; case DateSelectType.end: - cellStyle = defStyle.copyWith(color: TDTheme.of(context).fontWhColor1); - cellPrefixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontWhColor1); - cellSuffixStyle = prefixStyle.copyWith(color: TDTheme.of(context).fontWhColor1); + cellStyle = defStyle.copyWith(color: TDTheme.of(context).textColorAnti); + cellPrefixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).textColorAnti); + cellSuffixStyle = + prefixStyle.copyWith(color: TDTheme.of(context).textColorAnti); cellDecoration = BoxDecoration( - color: TDTheme.of(context).brandColor7, - borderRadius: BorderRadius.horizontal(right: Radius.circular(radius6)), + color: TDTheme.of(context).brandNormalColor, + borderRadius: + BorderRadius.horizontal(right: Radius.circular(radius6)), ); break; default: diff --git a/tdesign-component/lib/src/components/cascader/td_custom_tab.dart b/tdesign-component/lib/src/components/cascader/td_custom_tab.dart index d6d2b016f..22c348f69 100644 --- a/tdesign-component/lib/src/components/cascader/td_custom_tab.dart +++ b/tdesign-component/lib/src/components/cascader/td_custom_tab.dart @@ -8,7 +8,9 @@ class TDCustomTab extends StatefulWidget { final List tabs; final TapCallback? onTap; final int? initialIndex; - const TDCustomTab({super.key, required this.tabs, this.onTap,this.initialIndex}); + + const TDCustomTab( + {super.key, required this.tabs, this.onTap, this.initialIndex}); @override State createState() => _TDCustomTabState(); @@ -17,20 +19,22 @@ class TDCustomTab extends StatefulWidget { class _TDCustomTabState extends State { ScrollController _scrollController = ScrollController(); int _currentTabIndex = 0; + @override void initState() { // TODO: implement initState super.initState(); - _currentTabIndex=widget.initialIndex??0; + _currentTabIndex = widget.initialIndex ?? 0; } @override void didUpdateWidget(TDCustomTab oldWidget) { super.didUpdateWidget(oldWidget); - if(widget.initialIndex!=oldWidget.initialIndex){ - _currentTabIndex=widget.initialIndex!; + if (widget.initialIndex != oldWidget.initialIndex) { + _currentTabIndex = widget.initialIndex!; } } + @override Widget build(BuildContext context) { return SingleChildScrollView( @@ -40,10 +44,10 @@ class _TDCustomTabState extends State { mainAxisAlignment: MainAxisAlignment.start, children: List.generate(widget.tabs.length, (index) { return GestureDetector( - onTap:(){ + onTap: () { _onChangeTab(index); }, - child: Container( + child: SizedBox( width: 96, height: 52, child: Stack( @@ -53,8 +57,12 @@ class _TDCustomTabState extends State { widget.tabs[index], style: TextStyle( fontSize: 16, - color: _currentTabIndex == index ? TDTheme.of(context).brandNormalColor : Colors.black), - fontWeight: _currentTabIndex == index ?FontWeight.w600:FontWeight.w400, + color: _currentTabIndex == index + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).textColorPrimary), + fontWeight: _currentTabIndex == index + ? FontWeight.w600 + : FontWeight.w400, ), ), if (_currentTabIndex == index) @@ -70,15 +78,14 @@ class _TDCustomTabState extends State { ), ), ], - )) - ); + ))); })), ); } void _onChangeTab(int index) { if (widget.onTap != null) { - widget.onTap!(index); + widget.onTap!(index); } } } diff --git a/tdesign-component/lib/src/components/cascader/td_multi_cascader.dart b/tdesign-component/lib/src/components/cascader/td_multi_cascader.dart index 1cff69e86..ae7172f3d 100644 --- a/tdesign-component/lib/src/components/cascader/td_multi_cascader.dart +++ b/tdesign-component/lib/src/components/cascader/td_multi_cascader.dart @@ -2,7 +2,8 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; import '../../util/context_extension.dart'; -typedef MultiCascaderCallback = void Function(List selected); +typedef MultiCascaderCallback = void Function( + List selected); class TDMultiCascader extends StatefulWidget { /// 选择器标题 @@ -49,6 +50,7 @@ class TDMultiCascader extends StatefulWidget { /// 值发生变更时触发 final MultiCascaderCallback onChange; + const TDMultiCascader( {super.key, this.title, @@ -71,7 +73,8 @@ class TDMultiCascader extends StatefulWidget { State createState() => _TDMultiCascaderState(); } -class _TDMultiCascaderState extends State with TickerProviderStateMixin { +class _TDMultiCascaderState extends State + with TickerProviderStateMixin { List _tabListData = []; /// 当前tab选中的值 @@ -96,34 +99,39 @@ class _TDMultiCascaderState extends State with TickerProviderSt super.initState(); List.generate(widget.data.length, (index) { MultiCascaderListModel item = MultiCascaderListModel( - labelFun: ()=>widget.data[index]['label'], + labelFun: () => widget.data[index]['label'], value: widget.data[index]['value'], segmentValue: widget.data[index]['segmentValue'], level: 0, ); _listData.add(item); - if (widget.data[index]['children'] != null && widget.data[index]['children'].length > 0) { - _buildRecursiveList(1, widget.data[index]['value'], widget.data[index]['children']); + if (widget.data[index]['children'] != null && + widget.data[index]['children'].length > 0) { + _buildRecursiveList( + 1, widget.data[index]['value'], widget.data[index]['children']); } }); if (widget.isLetterSort) { _listDataSegmenter(); } - _initLocation(widget.initialData??''); - _currentTabIndex = _tabListData.length - 1; - _level = _currentTabIndex>0?_currentTabIndex:0; - if(_currentTabIndex>=0){ - _tabListData = _tabListData.reversed.toList(); - _selectTabValue = widget.initialData; - _selectListData = - _listData.where((element) => element.parentValue == _tabListData[_currentTabIndex].parentValue).toList(); - }else{ - _selectListData = _listData.where((element) => element.level == 0).toList(); - _tabListData.add(MultiCascaderListModel( - labelFun: ()=>context.resource.cascadeLabel, - )); - } + _initLocation(widget.initialData ?? ''); + _currentTabIndex = _tabListData.length - 1; + _level = _currentTabIndex > 0 ? _currentTabIndex : 0; + if (_currentTabIndex >= 0) { + _tabListData = _tabListData.reversed.toList(); + _selectTabValue = widget.initialData; + _selectListData = _listData + .where((element) => + element.parentValue == _tabListData[_currentTabIndex].parentValue) + .toList(); + } else { + _selectListData = + _listData.where((element) => element.level == 0).toList(); + _tabListData.add(MultiCascaderListModel( + labelFun: () => context.resource.cascadeLabel, + )); + } } @override @@ -133,15 +141,21 @@ class _TDMultiCascaderState extends State with TickerProviderSt return Container( width: maxWidth, decoration: BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, borderRadius: BorderRadius.only( - topLeft: Radius.circular(widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), - topRight: Radius.circular(widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), + topLeft: Radius.circular( + widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), + topRight: Radius.circular( + widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), ), ), child: Column( mainAxisSize: MainAxisSize.min, - children: [_buildTitle(context), _buildTabThemeBox(context), Expanded(child: _buildContentBox(context))], + children: [ + _buildTitle(context), + _buildTabThemeBox(context), + Expanded(child: _buildContentBox(context)) + ], ), ); } @@ -150,7 +164,7 @@ class _TDMultiCascaderState extends State with TickerProviderSt void didChangeDependencies() { /// 该方法在开始处必须调用父类的方法 super.didChangeDependencies(); - Future.delayed(Duration(seconds: 1), () { + Future.delayed(const Duration(seconds: 1), () { List.generate(_selectListData.length, (index) { if (_selectListData[index].value == _selectTabValue) { _scrollToListIndex(index); @@ -166,7 +180,8 @@ class _TDMultiCascaderState extends State with TickerProviderSt } void _initLocation(String value) { - List list = _listData.where((element) => element.value == value).toList(); + List list = + _listData.where((element) => element.value == value).toList(); if (list.isNotEmpty) { _tabListData.add(list[0]); if (list[0].parentValue != null) { @@ -180,7 +195,9 @@ class _TDMultiCascaderState extends State with TickerProviderSt if (a.segmentValue == null || b.segmentValue == null) { return 0; } else { - return a.segmentValue!.toLowerCase().compareTo(b.segmentValue!.toLowerCase()); + return a.segmentValue! + .toLowerCase() + .compareTo(b.segmentValue!.toLowerCase()); } }); } @@ -188,21 +205,23 @@ class _TDMultiCascaderState extends State with TickerProviderSt void _buildRecursiveList(int depth, String parentValue, List data) { List.generate(data.length, (index) { MultiCascaderListModel item = MultiCascaderListModel( - labelFun: ()=>data[index]['label'], + labelFun: () => data[index]['label'], value: data[index]['value'], parentValue: parentValue, segmentValue: data[index]['segmentValue'], level: depth, ); _listData.add(item); - if (data[index]['children'] != null && data[index]['children'].length > 0) { - _buildRecursiveList(depth + 1, data[index]['value'], data[index]['children']); + if (data[index]['children'] != null && + data[index]['children'].length > 0) { + _buildRecursiveList( + depth + 1, data[index]['value'], data[index]['children']); } }); } Widget _buildTitle(BuildContext context) { - return Container( + return SizedBox( height: 58, child: Stack( children: [ @@ -215,7 +234,7 @@ class _TDMultiCascaderState extends State with TickerProviderSt TextStyle( fontSize: TDTheme.of(context).fontTitleLarge!.size, fontWeight: FontWeight.w700, - color: TDTheme.of(context).fontGyColor1), + color: TDTheme.of(context).textColorPrimary), ), ), Positioned( @@ -223,10 +242,13 @@ class _TDMultiCascaderState extends State with TickerProviderSt top: 0, child: GestureDetector( onTap: () { - if(widget.action != null){ - var result = _tabListData.where((element) => element.label != context.resource.cascadeLabel).toList(); + if (widget.action != null) { + var result = _tabListData + .where((element) => + element.label != context.resource.cascadeLabel) + .toList(); widget.action?.onConfirm(result); - if(result.isNotEmpty){ + if (result.isNotEmpty) { // 返回数据不空,才会自己关闭。如果数据是空的,有业务在回调中自己选择是否关闭 Navigator.of(context).pop(); } @@ -243,7 +265,7 @@ class _TDMultiCascaderState extends State with TickerProviderSt (widget.closeText == null ? Icon( TDIcons.close, - color: TDTheme.of(context).fontGyColor1, + color: TDTheme.of(context).textColorPrimary, ) : TDText( widget.closeText, @@ -251,7 +273,8 @@ class _TDMultiCascaderState extends State with TickerProviderSt fontSize: TDTheme.of(context) .fontTitleMedium! .size, - color: TDTheme.of(context).fontGyColor1), + color: + TDTheme.of(context).textColorPrimary), )), ), ))), @@ -268,8 +291,11 @@ class _TDMultiCascaderState extends State with TickerProviderSt Widget _buildStepBox(BuildContext context) { var maxWidth = MediaQuery.of(context).size.width; return Container( - decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Color.fromRGBO(0, 0, 0, 0.1), width: 0.5))), - padding: EdgeInsets.only(bottom: 11), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: TDTheme.of(context).componentStrokeColor, + width: 0.5))), width: maxWidth, child: ListView( shrinkWrap: true, @@ -279,17 +305,20 @@ class _TDMultiCascaderState extends State with TickerProviderSt onTap: () { _tabListChange(index); }, - child: Container( + child: SizedBox( height: 38, child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Container( + SizedBox( // 圆和线 height: 8, child: LeftLineWidget( - isCircleFill: tabItem.value == null && tabItem.value != _selectTabValue ? false : true, + isCircleFill: tabItem.value == null && + tabItem.value != _selectTabValue + ? false + : true, isShowTopLine: index == 0 ? false : true, ), ), @@ -298,15 +327,19 @@ class _TDMultiCascaderState extends State with TickerProviderSt '${_tabListData[index].label}', style: TextStyle( fontSize: 14, - color: _currentTabIndex == index ? TDTheme.of(context).brandNormalColor : Colors.black), - fontWeight: _currentTabIndex == index ? FontWeight.w600 : FontWeight.w400, + color: _currentTabIndex == index + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).textColorPrimary), + fontWeight: _currentTabIndex == index + ? FontWeight.w600 + : FontWeight.w400, ), ), Padding( padding: const EdgeInsets.only(left: 2, right: 16), child: Icon( TDIcons.chevron_right, - color: TDTheme.of(context).fontGyColor3.withOpacity(0.4), + color: TDTheme.of(context).textColorPrimary, ), ), ], @@ -319,16 +352,18 @@ class _TDMultiCascaderState extends State with TickerProviderSt var maxWidth = MediaQuery.of(context).size.width; return Container( height: 48, - decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Color.fromRGBO(0, 0, 0, 0.1), width: 0.5))), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: TDTheme.of(context).componentStrokeColor, + width: 0.5))), width: maxWidth, child: TDCustomTab( tabs: List.generate(_tabListData.length, (index) { return _tabListData[index].label ?? ''; }), initialIndex: _currentTabIndex, - onTap: (int index) { - _tabListChange(index); - }, + onTap: _tabListChange, ), ); } @@ -337,19 +372,20 @@ class _TDMultiCascaderState extends State with TickerProviderSt var maxWidth = MediaQuery.of(context).size.width; return Container( width: maxWidth, - padding: EdgeInsets.only(left: 16, right: 16), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (widget.subTitles != null) Container( height: 50, - padding: EdgeInsets.only( + padding: const EdgeInsets.only( top: 20, ), child: TDText( widget.subTitles![_level], - style: TextStyle(color: Color.fromRGBO(0, 0, 0, 0.4)), + style: TextStyle( + color: TDTheme.of(context).textColorPlaceholder), font: TDTheme.of(context).fontTitleSmall, ) //, ), @@ -364,24 +400,29 @@ class _TDMultiCascaderState extends State with TickerProviderSt itemCount: _selectListData.length, itemBuilder: (context, index) { MultiCascaderListModel item = _selectListData[index]; - MultiCascaderListModel preItem = index == 0 ? MultiCascaderListModel() : _selectListData[index - 1]; + MultiCascaderListModel preItem = index == 0 + ? MultiCascaderListModel() + : _selectListData[index - 1]; return GestureDetector( onTap: () { int level = 0; - if (item.level ==0 && _currentTabIndex == 0) { + if (item.level == 0 && _currentTabIndex == 0) { _tabListData.clear(); _tabListData.add(MultiCascaderListModel( - labelFun: ()=>context.resource.cascadeLabel, + labelFun: () => context.resource.cascadeLabel, )); } if (item.level != null) { level = item.level!; } - if (widget.subTitles != null && widget.subTitles!.length - 1 > _level) { + if (widget.subTitles != null && + widget.subTitles!.length - 1 > _level) { _level = level + 1; } - List isList = _tabListData.where((element) => element.level == item.level).toList(); + List isList = _tabListData + .where((element) => element.level == item.level) + .toList(); if (isList.isNotEmpty) { _tabListData.removeAt(level); } @@ -394,31 +435,32 @@ class _TDMultiCascaderState extends State with TickerProviderSt }, child: Container( height: 56, - decoration: BoxDecoration(border: Border.all(color: Colors.transparent)), + decoration: BoxDecoration( + border: Border.all(color: Colors.transparent)), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Container( - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - if (item.segmentValue != null) - SizedBox( - width: 32, - child: item.segmentValue != preItem.segmentValue - ? TDText( - '${item.segmentValue}', - font: Font(size: 16, lineHeight: 24), - ) - : null, - ), - TDText( - '${item.label}', - font: Font(size: 16, lineHeight: 24), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (item.segmentValue != null) + SizedBox( + width: 32, + child: item.segmentValue != + preItem.segmentValue + ? TDText( + '${item.segmentValue}', + font: Font( + size: 16, lineHeight: 24), + ) + : null, ), - ], - ), + TDText( + '${item.label}', + font: Font(size: 16, lineHeight: 24), + ), + ], ), if (_selectTabValue == item.value) Icon( @@ -454,32 +496,44 @@ class _TDMultiCascaderState extends State with TickerProviderSt void _getChildrenListData(int level, String value) { //查询层级数据 - var selectLevelData = _listData.where((element) => element.level == (level)&&element.parentValue==value).toList(); + var selectLevelData = _listData + .where((element) => + element.level == (level) && element.parentValue == value) + .toList(); //判断下级是否存在 if (selectLevelData.isNotEmpty) { //获取下级数据 - var childList = selectLevelData.where((element) => element.parentValue == value).toList(); + var childList = selectLevelData + .where((element) => element.parentValue == value) + .toList(); _selectListData = childList; _currentTabIndex += 1; } else { - var result = _tabListData.where((element) => element.label != context.resource.cascadeLabel).toList(); + var result = _tabListData + .where((element) => element.label != context.resource.cascadeLabel) + .toList(); widget.onChange(result); Navigator.of(context).pop(); } } /// 查询列表数据 - void _getFindListData({required int level, String? parentValue, String? value}) { + void _getFindListData( + {required int level, String? parentValue, String? value}) { List list = []; //查询层级数据 - List selectLevelData = _listData.where((element) => element.level == (level)).toList(); + List selectLevelData = + _listData.where((element) => element.level == (level)).toList(); if (selectLevelData.isNotEmpty) { if (level == 0) { list = selectLevelData; } else if (value != null) { - list = selectLevelData.where((element) => element.value == value).toList(); + list = + selectLevelData.where((element) => element.value == value).toList(); } else { - list = selectLevelData.where((element) => element.parentValue == parentValue).toList(); + list = selectLevelData + .where((element) => element.parentValue == parentValue) + .toList(); } _selectListData = list; } @@ -489,9 +543,9 @@ class _TDMultiCascaderState extends State with TickerProviderSt void _scrollToListIndex(int index) async { // 计算列表中特定索引的位置 double scrollTo = index * 56.0; // 每个列表项的高度是56.0 - _scrollListController.animateTo( + await _scrollListController.animateTo( scrollTo, - duration: Duration(milliseconds: 1), + duration: const Duration(milliseconds: 1), curve: Curves.ease, ); } @@ -507,15 +561,22 @@ class LeftLineWidget extends StatelessWidget { /// 是否显示圆圈上方线条 final bool isShowTopLine; - const LeftLineWidget({this.isShowTopLine = false, this.topLineColor, this.isCircleFill = false}); + const LeftLineWidget( + {super.key, + this.isShowTopLine = false, + this.topLineColor, + this.isCircleFill = false}); @override Widget build(BuildContext context) { return Container( - margin: EdgeInsets.symmetric(horizontal: 16), + margin: const EdgeInsets.symmetric(horizontal: 16), width: 16, child: CustomPaint( - painter: LeftLinePainter(isShowTopLine: isShowTopLine, topLineColor: topLineColor ?? TDTheme.of(context).brandNormalColor, isCircleFill: isCircleFill), + painter: LeftLinePainter( + isShowTopLine: isShowTopLine, + topLineColor: topLineColor ?? TDTheme.of(context).brandNormalColor, + isCircleFill: isCircleFill), ), ); } @@ -535,7 +596,10 @@ class LeftLinePainter extends CustomPainter { /// 是否显示圆圈上方线条 final bool isShowTopLine; - const LeftLinePainter({required this.topLineColor, required this.isShowTopLine, required this.isCircleFill}); + const LeftLinePainter( + {required this.topLineColor, + required this.isShowTopLine, + required this.isCircleFill}); @override void paint(Canvas canvas, Size size) { @@ -550,9 +614,11 @@ class LeftLinePainter extends CustomPainter { Paint circlePaint = Paint(); circlePaint.color = topLineColor; circlePaint.strokeWidth = 1; - circlePaint.style = isCircleFill ? PaintingStyle.fill : PaintingStyle.stroke; + circlePaint.style = + isCircleFill ? PaintingStyle.fill : PaintingStyle.stroke; linePain.color = isShowTopLine ? (topLineColor) : Colors.transparent; - canvas.drawLine(Offset(centerX, -size.height), Offset(centerX, -size.height - _topHeight), linePain); + canvas.drawLine(Offset(centerX, -size.height), + Offset(centerX, -size.height - _topHeight), linePain); canvas.drawCircle(Offset(centerX, topHeight), centerX * 0.5, circlePaint); } @@ -564,6 +630,7 @@ class LeftLinePainter extends CustomPainter { class MultiCascaderListModel { String? Function()? labelFun; + String? get label => labelFun?.call(); String? value; @@ -575,5 +642,11 @@ class MultiCascaderListModel { String? segmentValue; int? level; - MultiCascaderListModel({this.labelFun, this.value, this.parentValue, this.level, this.segmentValue}); + + MultiCascaderListModel( + {this.labelFun, + this.value, + this.parentValue, + this.level, + this.segmentValue}); } diff --git a/tdesign-component/lib/src/components/cell/td_cell.dart b/tdesign-component/lib/src/components/cell/td_cell.dart index 008d8ee49..bfa6e8125 100644 --- a/tdesign-component/lib/src/components/cell/td_cell.dart +++ b/tdesign-component/lib/src/components/cell/td_cell.dart @@ -1,13 +1,7 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; -import '../../theme/td_spacers.dart'; -import '../../theme/td_theme.dart'; -import '../icon/td_icons.dart'; -import '../swipe_cell/td_swipe_cell_inherited.dart'; -import '../text/td_text.dart'; import 'td_cell_inherited.dart'; -import 'td_cell_style.dart'; typedef TDCellClick = void Function(TDCell cell); @@ -126,37 +120,45 @@ class TDCell extends StatefulWidget { class _TDCellState extends State { var _status = 'default'; + bool get disabled { + return widget.disabled ?? false; + } + + /// todo 像素溢出问题待优化 + /// @see https://github.com/Tencent/tdesign-flutter/issues/751 @override Widget build(BuildContext context) { - var style = widget.style ?? TDCellInherited.of(context)?.style ?? TDCellStyle.cellStyle(context); - var crossAxisAlignment = _getAlign(); - var color = _status == 'default' ? style.backgroundColor : style.clickBackgroundColor; - var border; - if(widget.showBottomBorder!) { - border = Border(bottom: BorderSide(width: 1, color: style.borderedColor ?? TDTheme.of(context).grayColor3)); - } + final theme = TDTheme.of(context); + final style = widget.style ?? + TDCellInherited.of(context)?.style ?? + TDCellStyle.cellStyle(context); + final crossAxisAlignment = _getAlign(); + final color = _status == 'default' + ? style.backgroundColor + : style.clickBackgroundColor; + final border = (widget.showBottomBorder ?? false) + ? Border( + bottom: BorderSide( + width: 0.5, + color: style.borderedColor ?? theme.componentStrokeColor, + ), + ) + : null; + return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { - if (widget.onClick != null && !(widget.disabled ?? false)) { + if (widget.onClick != null && !disabled) { widget.onClick!(widget); } TDSwipeCellInherited.of(context)?.cellClick(); }, - onLongPress: widget.onLongPress != null ? () { - if (!(widget.disabled ?? false)) { - widget.onLongPress!(widget); - } - } : null, - onTapDown: (details) { - _setStatus('active', 0); - }, - onTapUp: (details) { - _setStatus('default', 100); - }, - onTapCancel: () { - _setStatus('default', 0); - }, + onLongPress: widget.onLongPress != null && !disabled + ? () => widget.onLongPress!(widget) + : null, + onTapDown: (_) => _setStatus('active', 0), + onTapUp: (_) => _setStatus('default', 100), + onTapCancel: () => _setStatus('default', 0), child: Container( height: widget.height, padding: style.padding, @@ -164,26 +166,33 @@ class _TDCellState extends State { child: Row( crossAxisAlignment: crossAxisAlignment, children: [ - ..._getImage(), + ..._buildImage(), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (widget.leftIcon != null || widget.leftIconWidget != null) ...[ - widget.leftIconWidget ?? Icon(widget.leftIcon, size: 24, color: style.leftIconColor), - SizedBox(width: TDTheme.of(context).spacer12), + if (widget.leftIcon != null || + widget.leftIconWidget != null) ...[ + widget.leftIconWidget ?? + Icon(widget.leftIcon, + size: 24, color: style.leftIconColor), + SizedBox(width: theme.spacer12), ], Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, + // spacing: theme.spacer4, children: [ Row( children: [ if (widget.titleWidget != null) Flexible(child: widget.titleWidget!) else if (widget.title?.isNotEmpty == true) - Flexible(child: TDText(widget.title!, style: style.titleStyle)), - if (widget.required ?? false) TDText(' *', style: style.requiredStyle), + Flexible( + child: TDText(widget.title!, + style: style.titleStyle)), + if (widget.required ?? false) + TDText(' *', style: style.requiredStyle), ], ), if ((widget.titleWidget != null || widget.title != null) && @@ -191,8 +200,9 @@ class _TDCellState extends State { SizedBox(height: TDTheme.of(context).spacer4), if (widget.descriptionWidget != null) widget.descriptionWidget! - else if (widget.description?.isNotEmpty == true) - TDText(widget.description!, style: style.descriptionStyle), + else if (widget.description?.isNotEmpty ?? false) + TDText(widget.description!, + style: style.descriptionStyle), ], ), ), @@ -200,18 +210,20 @@ class _TDCellState extends State { ), ), Wrap( - spacing: TDTheme.of(context).spacer4, - crossAxisAlignment: WrapCrossAlignment.center, + spacing: theme.spacer4, + // crossAxisAlignment: WrapCrossAlignment.center, children: [ if (widget.noteWidget != null) widget.noteWidget! - else if (widget.note?.isNotEmpty == true) + else if (widget.note?.isNotEmpty ?? false) TDText(widget.note!, style: style.noteStyle), if (widget.rightIconWidget != null) widget.rightIconWidget! else if (widget.rightIcon != null) Icon(widget.rightIcon, size: 24, color: style.rightIconColor), - if (widget.arrow ?? false) Icon(TDIcons.chevron_right, size: 24, color: style.arrowColor), + if (widget.arrow ?? false) + Icon(TDIcons.chevron_right, + size: 24, color: style.arrowColor), ], ), ], @@ -234,7 +246,7 @@ class _TDCellState extends State { } void _setStatus(String status, int milliseconds) { - if ((widget.disabled ?? false) || !(widget.hover ?? true)) { + if (disabled || !(widget.hover ?? true)) { return; } if (milliseconds == 0) { @@ -250,26 +262,28 @@ class _TDCellState extends State { }); } - List _getImage() { - var imageSize = widget.imageSize ?? 48; - var list = []; + List _buildImage() { + final imageSize = widget.imageSize ?? 48; + final imageWidgets = []; + if (widget.imageWidget != null) { - list.add(widget.imageWidget!); + imageWidgets.add(widget.imageWidget!); } else if (widget.image != null) { - list.add(ClipRRect( - borderRadius: BorderRadius.circular(widget.imageCircle ?? 50), - child: Image( - image: widget.image!, - width: imageSize, - height: imageSize, - fit: BoxFit.cover, - ), - )); + imageWidgets.add(ClipRRect( + borderRadius: BorderRadius.circular(widget.imageCircle ?? 50), + child: Image( + image: widget.image!, + width: imageSize, + height: imageSize, + fit: BoxFit.cover, + ), + )); } - if (list.isEmpty) { - return list; + + if (imageWidgets.isNotEmpty) { + imageWidgets.add(SizedBox(width: TDTheme.of(context).spacer12)); } - list.add(SizedBox(width: TDTheme.of(context).spacer12)); - return list; + + return imageWidgets; } } diff --git a/tdesign-component/lib/src/components/cell/td_cell_group.dart b/tdesign-component/lib/src/components/cell/td_cell_group.dart index 6c216f2f9..af02fd51f 100644 --- a/tdesign-component/lib/src/components/cell/td_cell_group.dart +++ b/tdesign-component/lib/src/components/cell/td_cell_group.dart @@ -4,7 +4,10 @@ import '../../../tdesign_flutter.dart'; import 'td_cell_inherited.dart'; typedef CellBuilder = Widget Function( - BuildContext context, TDCell cell, int index); + BuildContext context, + TDCell cell, + int index, +); enum TDCellGroupTheme { defaultTheme, cardTheme } @@ -69,9 +72,9 @@ class _TDCellGroupState extends State { if (widget.title != null || widget.titleWidget != null) Container( width: double.infinity, - color: style.titleBackgroundColor, padding: style.titlePadding, - child: widget.titleWidget ?? TDText(widget.title!, style: style.groupTitleStyle), + child: widget.titleWidget ?? + TDText(widget.title!, style: style.groupTitleStyle), ), Flexible( child: Container( @@ -84,10 +87,12 @@ class _TDCellGroupState extends State { borderRadius: radius, child: ListView.separated( padding: EdgeInsets.zero, - shrinkWrap: widget.scrollable == false, // 设置为true以避免无限制地增长 + shrinkWrap: widget.scrollable == false, + // 设置为true以避免无限制地增长 physics: widget.scrollable == false ? const NeverScrollableScrollPhysics() - : null, // 禁用ListView的滚动 + : null, + // 禁用ListView的滚动 itemCount: itemCount, itemBuilder: (context, index) { final item = widget.cells[index]; @@ -119,7 +124,8 @@ class _TDCellGroupState extends State { if (!(widget.bordered ?? false)) { return null; } - var color = style.groupBorderedColor ?? TDTheme.of(context).grayColor3; + var color = + style.groupBorderedColor ?? TDTheme.of(context).componentStrokeColor; return Border.all( color: color, width: 1, @@ -143,7 +149,8 @@ class _TDCellGroupState extends State { Expanded( child: Container( height: 0.5, - color: style.borderedColor ?? TDTheme.of(context).grayColor3), + color: style.borderedColor ?? + TDTheme.of(context).componentStrokeColor), ), ], ); diff --git a/tdesign-component/lib/src/components/cell/td_cell_style.dart b/tdesign-component/lib/src/components/cell/td_cell_style.dart index ec43d2d52..f47af0901 100644 --- a/tdesign-component/lib/src/components/cell/td_cell_style.dart +++ b/tdesign-component/lib/src/components/cell/td_cell_style.dart @@ -22,7 +22,7 @@ class TDCellStyle { this.cardBorderRadius, this.cardPadding, this.titlePadding, - this.titleBackgroundColor, + @deprecated this.titleBackgroundColor, }) { if (context != null) { defaultStyle(context!); @@ -89,38 +89,43 @@ class TDCellStyle { } defaultStyle(BuildContext context) { - backgroundColor = Colors.white; - clickBackgroundColor = TDTheme.of(context).grayColor1; - leftIconColor = TDTheme.of(context).brandColor7; - rightIconColor = TDTheme.of(context).brandColor7; + backgroundColor = TDTheme.of(context).bgColorContainer; + clickBackgroundColor = TDTheme.of(context).bgColorContainerHover; + leftIconColor = TDTheme.of(context).brandNormalColor; + rightIconColor = TDTheme.of(context).brandNormalColor; titleStyle = TextStyle( - color: TDTheme.of(context).fontGyColor1, + color: TDTheme.of(context).textColorPrimary, fontSize: TDTheme.of(context).fontBodyLarge?.size ?? 16, height: TDTheme.of(context).fontBodyLarge?.height ?? 24, fontWeight: FontWeight.w400, ); - requiredStyle = titleStyle!.copyWith(color: TDTheme.of(context).errorColor6); + requiredStyle = + titleStyle!.copyWith(color: TDTheme.of(context).errorNormalColor); descriptionStyle = TextStyle( - color: TDTheme.of(context).fontGyColor2, + color: TDTheme.of(context).textColorSecondary, fontSize: TDTheme.of(context).fontBodyMedium?.size ?? 14, height: TDTheme.of(context).fontBodyMedium?.height ?? 22, fontWeight: FontWeight.w400, ); - noteStyle = titleStyle!.copyWith(color: TDTheme.of(context).fontGyColor3); - arrowColor = TDTheme.of(context).fontGyColor3; + noteStyle = + titleStyle!.copyWith(color: TDTheme.of(context).textColorPlaceholder); + arrowColor = TDTheme.of(context).textColorPlaceholder; - groupBorderedColor = TDTheme.of(context).grayColor3; - borderedColor = TDTheme.of(context).grayColor3; + groupBorderedColor = TDTheme.of(context).componentStrokeColor; + borderedColor = TDTheme.of(context).componentStrokeColor; groupTitleStyle = TextStyle( - color: TDTheme.of(context).fontGyColor1, + color: TDTheme.of(context).textColorPrimary, fontSize: TDTheme.of(context).fontTitleLarge?.size ?? 18, height: TDTheme.of(context).fontTitleLarge?.height ?? 26, - fontWeight: TDTheme.of(context).fontTitleLarge?.fontWeight ?? FontWeight.w600, + fontWeight: + TDTheme.of(context).fontTitleLarge?.fontWeight ?? FontWeight.w600, ); padding = EdgeInsets.all(TDTheme.of(context).spacer16); - cardBorderRadius = BorderRadius.all(Radius.circular(TDTheme.of(context).radiusLarge)); - cardPadding = EdgeInsets.only(left: TDTheme.of(context).spacer16, right: TDTheme.of(context).spacer16); + cardBorderRadius = + BorderRadius.all(Radius.circular(TDTheme.of(context).radiusLarge)); + cardPadding = + EdgeInsets.symmetric(horizontal: TDTheme.of(context).spacer16); titlePadding = EdgeInsets.only( left: TDTheme.of(context).spacer16, right: TDTheme.of(context).spacer16, diff --git a/tdesign-component/lib/src/components/checkbox/td_check_box.dart b/tdesign-component/lib/src/components/checkbox/td_check_box.dart index 0db0f2e74..6f95df5f3 100644 --- a/tdesign-component/lib/src/components/checkbox/td_check_box.dart +++ b/tdesign-component/lib/src/components/checkbox/td_check_box.dart @@ -33,7 +33,8 @@ typedef IconBuilder = Widget? Function(BuildContext context, bool checked); /// /// 自定义Content /// -typedef ContentBuilder = Widget Function(BuildContext context, bool checked, String? content); +typedef ContentBuilder = Widget Function( + BuildContext context, bool checked, String? content); typedef OnCheckValueChanged = void Function(bool selected); @@ -154,19 +155,24 @@ class TDCheckbox extends StatefulWidget { /// 自定义组件间距 final EdgeInsetsGeometry? customSpace; + @override State createState() => TDCheckboxState(); /// 默认的checkBox icon - Widget buildDefaultIcon(BuildContext context, TDCheckboxGroupState? groupState, bool isChecked) { + Widget buildDefaultIcon( + BuildContext context, TDCheckboxGroupState? groupState, bool isChecked) { if (cardMode == true) { return Container(); } Widget current; var size = 24.0; - final style = this.style ?? groupState?.widget.style ?? TDCheckboxStyle.circle; + final style = + this.style ?? groupState?.widget.style ?? TDCheckboxStyle.circle; final theme = TDTheme.of(context); - final deSelectedColor = style == TDCheckboxStyle.check ? Colors.transparent : theme.grayColor4; + final deSelectedColor = style == TDCheckboxStyle.check + ? Colors.transparent + : theme.componentBorderColor; current = Icon( style == TDCheckboxStyle.circle ? isChecked @@ -181,7 +187,9 @@ class TDCheckbox extends StatefulWidget { : TDIcons.check, size: size, color: !enable - ? (isChecked ? (disableColor ?? theme.brandDisabledColor) : deSelectedColor) + ? (isChecked + ? (disableColor ?? theme.brandDisabledColor) + : deSelectedColor) : isChecked ? selectColor ?? theme.brandNormalColor : deSelectedColor, @@ -258,14 +266,15 @@ class TDCheckboxState extends State { if (content != null) { final spacing = _spacing(groupState); - var contentDirection = groupState?.widget.contentDirection ?? widget.contentDirection; + var contentDirection = + groupState?.widget.contentDirection ?? widget.contentDirection; switch (contentDirection) { case TDContentDirection.left: current = Stack( alignment: Alignment.bottomCenter, children: [ Padding( - padding:widget.customSpace??_getPadding(widget.size), + padding: widget.customSpace ?? _getPadding(widget.size), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -275,7 +284,8 @@ class TDCheckboxState extends State { children: [ Expanded( child: Padding( - padding: EdgeInsets.only(left: widget.insetSpacing ?? 16), + padding: EdgeInsets.only( + left: widget.insetSpacing ?? 16), child: content, )), SizedBox( @@ -288,15 +298,18 @@ class TDCheckboxState extends State { ], ), Visibility( - visible: widget.subTitle != null && widget.subTitle != '', + visible: + widget.subTitle != null && widget.subTitle != '', child: Padding( - padding: EdgeInsets.only(left: widget.insetSpacing ?? 16, right: 16), + padding: EdgeInsets.only( + left: widget.insetSpacing ?? 16, right: 16), child: TDText(widget.subTitle ?? '', maxLines: widget.subTitleMaxLine, overflow: TextOverflow.ellipsis, textColor: widget.enable - ? (widget.subTitleColor ?? TDTheme.of(context).fontGyColor3) - : TDTheme.of(context).fontGyColor4, + ? (widget.subTitleColor ?? + TDTheme.of(context).textColorPlaceholder) + : TDTheme.of(context).textColorDisabled, font: TDTheme.of(context).fontBodyMedium), ), ) @@ -316,7 +329,7 @@ class TDCheckboxState extends State { alignment: Alignment.bottomCenter, children: [ Padding( - padding:widget.customSpace?? _getPadding(widget.size), + padding: widget.customSpace ?? _getPadding(widget.size), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -325,7 +338,8 @@ class TDCheckboxState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( - padding: EdgeInsets.only(left: widget.checkBoxLeftSpace ?? 16), + padding: EdgeInsets.only( + left: widget.checkBoxLeftSpace ?? 16), child: icon, ), SizedBox( @@ -333,13 +347,15 @@ class TDCheckboxState extends State { ), Expanded( child: Padding( - padding: EdgeInsets.only(right: widget.insetSpacing ?? 16), + padding: EdgeInsets.only( + right: widget.insetSpacing ?? 16), child: content, )), ], ), Visibility( - visible: widget.subTitle != null && widget.subTitle != '', + visible: + widget.subTitle != null && widget.subTitle != '', child: Padding( padding: EdgeInsets.only( top: widget.cardMode ? 4.scale : 0, @@ -349,9 +365,11 @@ class TDCheckboxState extends State { maxLines: widget.subTitleMaxLine, overflow: TextOverflow.ellipsis, textColor: widget.enable - ? (widget.subTitleColor ?? TDTheme.of(context).fontGyColor3) - : TDTheme.of(context).fontGyColor4, - font: widget.subTitleFont ?? TDTheme.of(context).fontBodyMedium), + ? (widget.subTitleColor ?? + TDTheme.of(context).textColorPlaceholder) + : TDTheme.of(context).textColorDisabled, + font: widget.subTitleFont ?? + TDTheme.of(context).fontBodyMedium), ), ) ], @@ -400,13 +418,18 @@ class TDCheckboxState extends State { return Container( clipBehavior: widget.cardMode ? Clip.hardEdge : Clip.none, decoration: BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, border: widget.cardMode ? checked - ? Border.all(width: 1.5, color: widget.selectColor ?? TDTheme.of(context).brandNormalColor) + ? Border.all( + width: 1.5, + color: widget.selectColor ?? + TDTheme.of(context).brandNormalColor) : Border.all(width: 1.5, color: Colors.transparent) : null, - borderRadius: widget.cardMode ? const BorderRadius.all(Radius.circular(6)) : null), + borderRadius: widget.cardMode + ? const BorderRadius.all(Radius.circular(6)) + : null), child: Stack( children: [ current, @@ -461,7 +484,8 @@ class TDCheckboxState extends State { bool checked, ) { final title = widget.title; - final customContent = widget.customContentBuilder ?? groupState?.widget.customContentBuilder; + final customContent = + widget.customContentBuilder ?? groupState?.widget.customContentBuilder; var content = customContent?.call(context, checked, title); if (content == null) { @@ -470,8 +494,8 @@ class TDCheckboxState extends State { maxLines: widget.titleMaxLine ?? groupState?.widget.titleMaxLine, overflow: TextOverflow.ellipsis, textColor: widget.enable - ? (widget.titleColor ?? TDTheme.of(context).fontGyColor1) - : TDTheme.of(context).fontGyColor4, + ? (widget.titleColor ?? TDTheme.of(context).textColorPrimary) + : TDTheme.of(context).textColorDisabled, font: widget.titleFont ?? TDTheme.of(context) .fontBodyLarge); // TODO custom fontSize https://github.com/Tencent/tdesign-flutter/issues/66 @@ -481,8 +505,10 @@ class TDCheckboxState extends State { } /// 构建icon - Widget? _buildCheckboxIcon(BuildContext context, TDCheckboxGroupState? groupState, bool isCheck) { - final iconBuilder = widget.customIconBuilder ?? groupState?.widget.customIconBuilder; + Widget? _buildCheckboxIcon( + BuildContext context, TDCheckboxGroupState? groupState, bool isCheck) { + final iconBuilder = + widget.customIconBuilder ?? groupState?.widget.customIconBuilder; if (iconBuilder != null) { return iconBuilder.call(context, isCheck); } @@ -495,7 +521,11 @@ class RadioCornerIcon extends StatelessWidget { final double radius; final Color? selectColor; - const RadioCornerIcon({Key? key, required this.length, required this.radius, required this.selectColor}) + const RadioCornerIcon( + {Key? key, + required this.length, + required this.radius, + required this.selectColor}) : super(key: key); @override @@ -508,7 +538,9 @@ class RadioCornerIcon extends StatelessWidget { children: [ CustomPaint( painter: RadioCorner( - length: length, radius: radius, fillColor: selectColor ?? TDTheme.of(context).brandNormalColor), + length: length, + radius: radius, + fillColor: selectColor ?? TDTheme.of(context).brandNormalColor), ), const Positioned( top: 3, @@ -529,7 +561,8 @@ class RadioCorner extends CustomPainter { final double radius; final Color fillColor; - RadioCorner({required this.length, required this.radius, required this.fillColor}); + RadioCorner( + {required this.length, required this.radius, required this.fillColor}); @override void paint(Canvas canvas, Size size) { diff --git a/tdesign-component/lib/src/components/collapse/td_collapse.dart b/tdesign-component/lib/src/components/collapse/td_collapse.dart index 2a142c193..5355418f6 100644 --- a/tdesign-component/lib/src/components/collapse/td_collapse.dart +++ b/tdesign-component/lib/src/components/collapse/td_collapse.dart @@ -5,12 +5,10 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; -import 'td_collapse_panel.dart'; import 'td_collapse_salted_key.dart'; import 'td_inset_divider.dart'; import 'td_nonanimated_expand_icon.dart'; - /// 折叠面板的组件样式 enum TDCollapseStyle { /// Block 通栏风格 @@ -137,7 +135,8 @@ class _TDCollapseState extends State { items.add( MaterialSlice( key: TDCollapseSaltedKey(context, index * 2), - color: child.backgroundColor, + color: + child.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Column( // to prevent collapse state change when parent rebuild key: TDCollapseSaltedKey(context, index * 2), @@ -312,7 +311,7 @@ class _TDCollapseState extends State { Text(child.expandIconTextBuilder!(context, _isChildExpanded(index)), textAlign: TextAlign.right, style: TextStyle( - color: Colors.black.withOpacity(0.4), + color: TDTheme.of(context).textColorPlaceholder, )), expandedIcon, ], diff --git a/tdesign-component/lib/src/components/collapse/td_inset_divider.dart b/tdesign-component/lib/src/components/collapse/td_inset_divider.dart index 665cd049e..687c7dfa5 100644 --- a/tdesign-component/lib/src/components/collapse/td_inset_divider.dart +++ b/tdesign-component/lib/src/components/collapse/td_inset_divider.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; - class TDInsetDivider extends StatelessWidget { const TDInsetDivider({Key? key}) : super(key: key); @@ -14,7 +13,7 @@ class TDInsetDivider extends StatelessWidget { return SizedBox( height: 1, child: Divider( - color: TDTheme.of(context).grayColor3, + color: TDTheme.of(context).componentStrokeColor, indent: TDTheme.of(context).spacer16, endIndent: 0.0, height: 1, diff --git a/tdesign-component/lib/src/components/dialog/td_alert_dialog.dart b/tdesign-component/lib/src/components/dialog/td_alert_dialog.dart index 67300ec39..218382fa2 100644 --- a/tdesign-component/lib/src/components/dialog/td_alert_dialog.dart +++ b/tdesign-component/lib/src/components/dialog/td_alert_dialog.dart @@ -20,10 +20,10 @@ class TDAlertDialog extends StatelessWidget { /// [leftBtn]和[rightBtn]不传style参数会应用默认样式,左侧弱按钮,右侧强按钮 const TDAlertDialog({ Key? key, - this.backgroundColor = Colors.white, + this.backgroundColor, this.radius = 12.0, this.title, - this.titleColor = const Color(0xE6000000), + this.titleColor, this.content, this.contentColor, this.titleAlignment, @@ -49,10 +49,10 @@ class TDAlertDialog extends StatelessWidget { const TDAlertDialog.vertical({ Key? key, required List buttons, - this.backgroundColor = Colors.white, + this.backgroundColor, this.radius = 12.0, this.title, - this.titleColor = Colors.black, + this.titleColor, this.titleAlignment, this.contentWidget, this.content, @@ -71,7 +71,7 @@ class TDAlertDialog extends StatelessWidget { super(key: key); /// 背景颜色 - final Color backgroundColor; + final Color? backgroundColor; /// 圆角 final double radius; @@ -80,7 +80,7 @@ class TDAlertDialog extends StatelessWidget { final String? title; /// 标题颜色 - final Color titleColor; + final Color? titleColor; /// 标题对齐模式 final AlignmentGeometry? titleAlignment; @@ -155,15 +155,19 @@ class TDAlertDialog extends StatelessWidget { } Widget _horizontalButtons(BuildContext context) { - if(buttonWidget != null) { + if (buttonWidget != null) { return buttonWidget!; } final left = leftBtn ?? TDDialogButtonOptions( - title: context.resource.cancel, theme: TDButtonTheme.light, action: leftBtnAction); + title: context.resource.cancel, + theme: TDButtonTheme.light, + action: leftBtnAction); final right = rightBtn ?? TDDialogButtonOptions( - title: context.resource.confirm, theme: TDButtonTheme.primary, action: rightBtnAction); + title: context.resource.confirm, + theme: TDButtonTheme.primary, + action: rightBtnAction); return _buttonStyle == TDDialogButtonStyle.text ? HorizontalTextButtons(leftBtn: left, rightBtn: right) : HorizontalNormalButtons( @@ -185,7 +189,7 @@ class TDAlertDialog extends StatelessWidget { buttonTheme: value.theme, buttonType: value.type, onPressed: () { - if(value.action != null){ + if (value.action != null) { value.action!(); } else { Navigator.pop(context); @@ -199,8 +203,7 @@ class TDAlertDialog extends StatelessWidget { }); return Container( - padding: - const EdgeInsets.only(left: 24, right: 24, bottom: 24), + padding: const EdgeInsets.only(left: 24, right: 24, bottom: 24), child: Column( children: widgets, ), diff --git a/tdesign-component/lib/src/components/dialog/td_confirm_dialog.dart b/tdesign-component/lib/src/components/dialog/td_confirm_dialog.dart index 95e996e6e..de0ea26ff 100644 --- a/tdesign-component/lib/src/components/dialog/td_confirm_dialog.dart +++ b/tdesign-component/lib/src/components/dialog/td_confirm_dialog.dart @@ -17,10 +17,10 @@ class TDConfirmDialog extends StatelessWidget { const TDConfirmDialog({ Key? key, this.action, - this.backgroundColor = Colors.white, + this.backgroundColor, this.radius = 12.0, this.title, - this.titleColor = const Color(0xE6000000), + this.titleColor, this.titleAlignment, this.contentWidget, this.content, @@ -40,7 +40,7 @@ class TDConfirmDialog extends StatelessWidget { final String? title; /// 标题颜色 - final Color titleColor; + final Color? titleColor; /// 标题对齐模式 final AlignmentGeometry? titleAlignment; @@ -67,7 +67,7 @@ class TDConfirmDialog extends StatelessWidget { final Function()? action; /// 背景颜色 - final Color backgroundColor; + final Color? backgroundColor; /// 按钮样式 final TDDialogButtonStyle buttonStyle; @@ -146,36 +146,30 @@ class TDConfirmDialog extends StatelessWidget { backgroundColor: backgroundColor, width: width, radius: radius, - body: LayoutBuilder( - builder: (context, constraints) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - // 内容区域添加弹性约束 https://api.flutter.dev/flutter/widgets/Flexible-class.html - Flexible( - // 滚动支持 - child: SingleChildScrollView( - physics: const ClampingScrollPhysics(), - child: TDDialogInfoWidget( - title: title, - titleColor: titleColor, - titleAlignment: titleAlignment, - contentWidget: contentWidget, - content: content, - contentColor: contentColor, - // 当contentMaxHeight未设置时,使用屏幕的60%作为最大高度,并允许滚动 - contentMaxHeight: contentMaxHeight > 0 - ? contentMaxHeight - : constraints.maxHeight * 0.6, - padding: padding, - ), - ), - ), - _buildButton(context), - ] - ); - } - ) - ); + body: LayoutBuilder(builder: (context, constraints) { + return Column(mainAxisSize: MainAxisSize.min, children: [ + // 内容区域添加弹性约束 https://api.flutter.dev/flutter/widgets/Flexible-class.html + Flexible( + // 滚动支持 + child: SingleChildScrollView( + physics: const ClampingScrollPhysics(), + child: TDDialogInfoWidget( + title: title, + titleColor: titleColor, + titleAlignment: titleAlignment, + contentWidget: contentWidget, + content: content, + contentColor: contentColor, + // 当contentMaxHeight未设置时,使用屏幕的60%作为最大高度,并允许滚动 + contentMaxHeight: contentMaxHeight > 0 + ? contentMaxHeight + : constraints.maxHeight * 0.6, + padding: padding, + ), + ), + ), + _buildButton(context), + ]); + })); } } diff --git a/tdesign-component/lib/src/components/dialog/td_dialog_widget.dart b/tdesign-component/lib/src/components/dialog/td_dialog_widget.dart index 0cb74645d..c80a88a3b 100644 --- a/tdesign-component/lib/src/components/dialog/td_dialog_widget.dart +++ b/tdesign-component/lib/src/components/dialog/td_dialog_widget.dart @@ -14,7 +14,7 @@ class TDDialogScaffold extends StatelessWidget { Key? key, required this.body, this.showCloseButton, - this.backgroundColor = Colors.white, + this.backgroundColor, this.width, this.radius = 12.0, }) : super(key: key); @@ -26,7 +26,7 @@ class TDDialogScaffold extends StatelessWidget { final bool? showCloseButton; /// 背景色 - final Color backgroundColor; + final Color? backgroundColor; /// 圆角 final double radius; @@ -37,42 +37,43 @@ class TDDialogScaffold extends StatelessWidget { @override Widget build(BuildContext context) { return Center( - child: Material( - type: MaterialType.transparency, - child: Container( - width: width ?? 311, - decoration: BoxDecoration( - color: backgroundColor, // 底色 - borderRadius: BorderRadius.all(Radius.circular(radius)), - ), - child: Stack( - children: [ - body, - showCloseButton ?? false - ? Positioned( - top: 0, - right: 0, - child: GestureDetector( - onTap: () { - Navigator.pop(context); - }, - child: SizedBox( - width: 38, - height: 38, - child: Center( - child: Icon( - TDIcons.close, - size: 22, - color: TDTheme.of(context).fontGyColor3, + child: Material( + type: MaterialType.transparency, + child: Container( + width: width ?? 311, + decoration: BoxDecoration( + color: + backgroundColor ?? TDTheme.of(context).bgColorContainer, // 底色 + borderRadius: BorderRadius.all(Radius.circular(radius)), + ), + child: Stack( + children: [ + body, + showCloseButton ?? false + ? Positioned( + top: 0, + right: 0, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: SizedBox( + width: 38, + height: 38, + child: Center( + child: Icon( + TDIcons.close, + size: 22, + color: TDTheme.of(context).textColorPlaceholder, + ), ), ), - ), - )) - : Container(height: 0) - ], - ), + )) + : Container(height: 0) + ], ), ), + ), ); } } @@ -82,11 +83,11 @@ class TDDialogTitle extends StatelessWidget { const TDDialogTitle({ Key? key, this.title, - this.titleColor = Colors.black, + this.titleColor, }) : super(key: key); /// 标题颜色 - final Color titleColor; + final Color? titleColor; /// 标题文字 final String? title; @@ -96,9 +97,9 @@ class TDDialogTitle extends StatelessWidget { // 标题和内容不能同时为空 return TDText( title, - textColor: titleColor, + textColor: titleColor ?? TDTheme.of(context).textColorPrimary, fontWeight: FontWeight.w600, - font: Font(size: 16, lineHeight: 24), + font: Font(size: 18, lineHeight: 26), textAlign: TextAlign.center, ); } @@ -109,11 +110,11 @@ class TDDialogContent extends StatelessWidget { const TDDialogContent({ Key? key, this.content, - this.contentColor = const Color(0x99000000), + this.contentColor, }) : super(key: key); /// 标题颜色 - final Color contentColor; + final Color? contentColor; /// 标题文字 final String? content; @@ -123,7 +124,7 @@ class TDDialogContent extends StatelessWidget { // 标题和内容不能同时为空 return TDText( content, - textColor: contentColor, + textColor: contentColor ?? TDTheme.of(context).textColorSecondary, font: Font(size: 16, lineHeight: 24), textAlign: TextAlign.center, ); @@ -135,7 +136,7 @@ class TDDialogInfoWidget extends StatelessWidget { const TDDialogInfoWidget({ Key? key, this.title, - this.titleColor = Colors.black, + this.titleColor, this.titleAlignment, this.contentWidget, this.content, @@ -148,7 +149,7 @@ class TDDialogInfoWidget extends StatelessWidget { final String? title; /// 标题颜色 - final Color titleColor; + final Color? titleColor; /// 标题对齐模式 final AlignmentGeometry? titleAlignment; @@ -180,17 +181,15 @@ class TDDialogInfoWidget extends StatelessWidget { if (title != null) Align( alignment: titleAlignment ?? Alignment.center, - child: TDText( - title, - textColor: titleColor, - fontWeight: FontWeight.w600, - font: Font(size: 18, lineHeight: 26), - textAlign: TextAlign.center, + child: TDDialogTitle( + title: title, + titleColor: titleColor, ), ), if (contentWidget != null || content != null) Container( - padding: EdgeInsets.fromLTRB(0, (title != null && content != null) ? 8.0 : 0, 0, 0), + padding: EdgeInsets.fromLTRB( + 0, (title != null && content != null) ? 8.0 : 0, 0, 0), constraints: contentMaxHeight > 0 ? BoxConstraints( maxHeight: contentMaxHeight, @@ -202,7 +201,8 @@ class TDDialogInfoWidget extends StatelessWidget { scrollDirection: Axis.vertical, child: TDDialogContent( content: content!, - contentColor: contentColor ?? const Color(0x99000000), + contentColor: contentColor ?? + TDTheme.of(context).textColorSecondary, ), ), ), @@ -246,7 +246,7 @@ class HorizontalNormalButtons extends StatelessWidget { height: leftBtn.height, buttonTextFontWeight: leftBtn.fontWeight ?? FontWeight.w600, onPressed: () { - if(leftBtn.action != null){ + if (leftBtn.action != null) { leftBtn.action!(); } else { Navigator.pop(context); @@ -255,6 +255,7 @@ class HorizontalNormalButtons extends StatelessWidget { ), ), const TDDivider( + height: 0.5, width: 12, color: Colors.transparent, ), @@ -269,7 +270,7 @@ class HorizontalNormalButtons extends StatelessWidget { height: rightBtn.height, buttonTextFontWeight: rightBtn.fontWeight ?? FontWeight.w600, onPressed: () { - if(rightBtn.action != null) { + if (rightBtn.action != null) { rightBtn.action!(); } else { Navigator.pop(context); @@ -302,7 +303,7 @@ class HorizontalTextButtons extends StatelessWidget { // 标题和内容不能同时为空 return Column( children: [ - const TDDivider(height: 1), + const TDDivider(height: 0.5), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -318,7 +319,7 @@ class HorizontalTextButtons extends StatelessWidget { height: 56, buttonTextFontWeight: leftBtn.fontWeight, onPressed: () { - if(leftBtn.action != null){ + if (leftBtn.action != null) { leftBtn.action!(); } else { Navigator.pop(context); @@ -327,7 +328,7 @@ class HorizontalTextButtons extends StatelessWidget { ), ), const TDDivider( - width: 1, + width: 0.5, height: 56, ), Expanded( @@ -341,7 +342,7 @@ class HorizontalTextButtons extends StatelessWidget { height: 56, buttonTextFontWeight: rightBtn.fontWeight ?? FontWeight.w600, onPressed: () { - if(rightBtn.action != null){ + if (rightBtn.action != null) { rightBtn.action!(); } else { Navigator.pop(context); @@ -414,7 +415,10 @@ class TDDialogButton extends StatelessWidget { type: buttonType ?? TDButtonType.fill, theme: buttonTheme, text: buttonText, - textStyle: TextStyle(fontWeight: buttonTextFontWeight,color:buttonTextColor,fontSize: buttonTextSize), + textStyle: TextStyle( + fontWeight: buttonTextFontWeight, + color: buttonTextColor, + fontSize: buttonTextSize), width: width, height: height, isBlock: isBlock, diff --git a/tdesign-component/lib/src/components/dialog/td_image_dialog.dart b/tdesign-component/lib/src/components/dialog/td_image_dialog.dart index e1e0c4ba3..bfe0e0920 100644 --- a/tdesign-component/lib/src/components/dialog/td_image_dialog.dart +++ b/tdesign-component/lib/src/components/dialog/td_image_dialog.dart @@ -21,10 +21,10 @@ class TDImageDialog extends StatelessWidget { Key? key, required this.image, this.imagePosition = TDDialogImagePosition.top, - this.backgroundColor = Colors.white, + this.backgroundColor, this.radius = 12.0, this.title, - this.titleColor = const Color(0xE6000000), + this.titleColor, this.titleAlignment, this.contentWidget, this.content, @@ -37,7 +37,7 @@ class TDImageDialog extends StatelessWidget { }) : super(key: key); /// 背景颜色 - final Color backgroundColor; + final Color? backgroundColor; /// 圆角 final double radius; @@ -46,7 +46,7 @@ class TDImageDialog extends StatelessWidget { final String? title; /// 标题颜色 - final Color titleColor; + final Color? titleColor; /// 标题对齐模式 final AlignmentGeometry? titleAlignment; @@ -174,10 +174,14 @@ class TDImageDialog extends StatelessWidget { } final left = leftBtn ?? TDDialogButtonOptions( - title: context.resource.cancel, theme: TDButtonTheme.light, action: null); + title: context.resource.cancel, + theme: TDButtonTheme.light, + action: null); final right = rightBtn ?? TDDialogButtonOptions( - title: context.resource.confirm, theme: TDButtonTheme.primary, action: null); + title: context.resource.confirm, + theme: TDButtonTheme.primary, + action: null); return HorizontalNormalButtons( leftBtn: left, rightBtn: right, diff --git a/tdesign-component/lib/src/components/dialog/td_input_dialog.dart b/tdesign-component/lib/src/components/dialog/td_input_dialog.dart index ef6a1063c..2063fdb38 100644 --- a/tdesign-component/lib/src/components/dialog/td_input_dialog.dart +++ b/tdesign-component/lib/src/components/dialog/td_input_dialog.dart @@ -15,10 +15,10 @@ class TDInputDialog extends StatelessWidget { const TDInputDialog({ Key? key, required this.textEditingController, - this.backgroundColor = Colors.white, + this.backgroundColor, this.radius = 12.0, this.title, - this.titleColor = const Color(0xE6000000), + this.titleColor, this.titleAlignment, this.contentWidget, this.content, @@ -34,7 +34,7 @@ class TDInputDialog extends StatelessWidget { super(key: key); /// 背景颜色 - final Color backgroundColor; + final Color? backgroundColor; /// 圆角 final double radius; @@ -43,7 +43,7 @@ class TDInputDialog extends StatelessWidget { final String? title; /// 标题颜色 - final Color titleColor; + final Color? titleColor; /// 标题对齐模式 final AlignmentGeometry? titleAlignment; @@ -84,15 +84,13 @@ class TDInputDialog extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + padding: + EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: TDDialogScaffold( - showCloseButton: showCloseButton, - backgroundColor: backgroundColor, - radius: radius, - body: Material( - color: backgroundColor, - borderRadius: BorderRadius.all(Radius.circular(radius)), - child: Column(mainAxisSize: MainAxisSize.min, children: [ + showCloseButton: showCloseButton, + backgroundColor: backgroundColor, + radius: radius, + body: Column(mainAxisSize: MainAxisSize.min, children: [ TDDialogInfoWidget( title: title, titleColor: titleColor, @@ -102,32 +100,31 @@ class TDInputDialog extends StatelessWidget { contentColor: contentColor, padding: padding, ), - SizedBox( - child: customInputWidget != null - ? customInputWidget! - : Container( - color: Colors.white, - height: 48, - margin: const EdgeInsets.fromLTRB(24, 16, 24, 24), - child: TextField( - controller: textEditingController, - autofocus: true, - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(16, 0, 16, 0), - border: OutlineInputBorder(borderRadius: BorderRadius.circular(6), borderSide: BorderSide.none), - hintText: hintText, - hintStyle: const TextStyle(color: Color(0x66000000)), - fillColor: const Color(0xFFF3F3F3), - filled: true, - // labelText: '左上角', - ), + customInputWidget != null + ? customInputWidget! + : Container( + margin: const EdgeInsets.fromLTRB(24, 16, 24, 24), + child: TextField( + controller: textEditingController, + autofocus: true, + decoration: InputDecoration( + contentPadding: + const EdgeInsets.symmetric(horizontal: 16), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusDefault), + borderSide: BorderSide.none), + hintText: hintText, + hintStyle: TextStyle( + color: TDTheme.of(context).textColorPlaceholder), + fillColor: TDTheme.of(context).bgColorComponent, + filled: true, + // labelText: '左上角', ), ), - ), + ), _horizontalButtons(context), - ]), - ), - ), + ])), ); } @@ -138,12 +135,16 @@ class TDInputDialog extends StatelessWidget { final left = leftBtn ?? TDDialogButtonOptions( title: context.resource.cancel, - titleColor: const Color(0xE6000000), + titleColor: TDTheme.of(context).textColorPrimary, fontWeight: FontWeight.normal, action: null, height: 56); final right = rightBtn ?? - TDDialogButtonOptions(title: context.resource.confirm, action: null, fontWeight: FontWeight.w600, height: 56); + TDDialogButtonOptions( + title: context.resource.confirm, + action: null, + fontWeight: FontWeight.w600, + height: 56); return HorizontalTextButtons( leftBtn: left, rightBtn: right, diff --git a/tdesign-component/lib/src/components/divider/dashed_widget.dart b/tdesign-component/lib/src/components/divider/dashed_widget.dart index 5f00a59b0..f5e6ba420 100644 --- a/tdesign-component/lib/src/components/divider/dashed_widget.dart +++ b/tdesign-component/lib/src/components/divider/dashed_widget.dart @@ -2,23 +2,27 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import '../../../tdesign_flutter.dart'; + /// 虚线控件 class DashedWidget extends StatelessWidget { const DashedWidget({ Key? key, - this.color = Colors.black, + this.color, this.gap = 2, this.solidLength = 2, this.width, - this.height, + this.height = 0.5, this.direction = Axis.horizontal, - }) : super(key: key); + }) : assert(gap > 0, 'gap 必须大于 0'), + assert(solidLength > 0, 'solidLength 必须大于 0'), + super(key: key); - final Color color; + final Color? color; final double gap; final double solidLength; final double? width; - final double? height; + final double height; final Axis direction; @override @@ -29,32 +33,35 @@ class DashedWidget extends StatelessWidget { height: height, child: CustomPaint( painter: DashedPainter( - color: color, - strokeWidth: height ?? 1, + color: color ?? TDTheme.of(context).componentStrokeColor, + strokeWidth: height, direction: direction), ), ); - } else { - return SizedBox( - width: width, - height: height ?? MediaQuery.of(context).size.height, - child: CustomPaint( - painter: DashedPainter( - color: color, strokeWidth: width ?? 1, direction: direction), - ), - ); } + + return SizedBox( + width: width, + height: height ?? MediaQuery.of(context).size.height, + child: CustomPaint( + painter: DashedPainter( + color: color ?? TDTheme.of(context).componentStrokeColor, + strokeWidth: width ?? 1, + direction: direction), + ), + ); } } /// 绘制虚线自定义控件 class DashedPainter extends CustomPainter { - DashedPainter( - {this.color = Colors.black, - this.strokeWidth = 1, - this.gap = 2, - this.solidLength = 2, - this.direction = Axis.horizontal}); + DashedPainter({ + required this.color, + this.strokeWidth = 1, + this.gap = 2, + this.solidLength = 2, + this.direction = Axis.horizontal, + }); final Color color; final double strokeWidth; @@ -68,67 +75,43 @@ class DashedPainter extends CustomPainter { ..color = color ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth; - var start = const Offset(0, 0); - Offset end; - if (direction == Axis.horizontal) { - end = Offset(size.width, 0); - } else { - // 不能为0,防止除0错误 - end = Offset(0.00001, size.height); - } - var path = getDashedPath(start, end); - canvas.drawPath(path, paint); + _drawDashedLine(canvas, paint, size); } - Path getDashedPath(Offset start, Offset end) { - var size = Size(end.dx - start.dx, end.dy - start.dy); - var path = Path(); - path.moveTo(start.dx, start.dy); - var shouldDraw = true; - var currentOffset = Offset(start.dx, start.dy); - - var radians = atan(size.height / size.width); - - var gapDx = - cos(radians) * gap < 0 ? cos(radians) * gap * -1 : cos(radians) * gap; - - var gapDy = - sin(radians) * gap < 0 ? sin(radians) * gap * -1 : sin(radians) * gap; - - var solidDx = cos(radians) * solidLength < 0 - ? cos(radians) * solidLength * -1 - : cos(radians) * solidLength; - - var solidDy = sin(radians) * solidLength < 0 - ? sin(radians) * solidLength * -1 - : sin(radians) * solidLength; - - double _getDx() { - return shouldDraw ? solidDx : gapDx; - } - - double _getDy() { - return shouldDraw ? solidDy : gapDy; - } - - while (currentOffset.dx <= end.dx && currentOffset.dy <= end.dy) { - shouldDraw - ? path.lineTo( - currentOffset.dx.toDouble(), currentOffset.dy.toDouble()) - : path.moveTo( - currentOffset.dx.toDouble(), currentOffset.dy.toDouble()); - currentOffset = Offset( - currentOffset.dx + _getDx(), - currentOffset.dy + _getDy(), - ); - shouldDraw = !shouldDraw; + void _drawDashedLine(Canvas canvas, Paint paint, Size size) { + final isHorizontal = direction == Axis.horizontal; + final lineLength = isHorizontal ? size.width : size.height; + final fixedCoordinate = (isHorizontal ? size.height : size.width) / 2; + + double currentPosition = 0; + var drawSolid = true; + + while (currentPosition < lineLength) { + final segmentLength = drawSolid ? solidLength : gap; + final nextPosition = min(currentPosition + segmentLength, lineLength); + + if (drawSolid) { + final start = isHorizontal + ? Offset(currentPosition, fixedCoordinate) + : Offset(fixedCoordinate, currentPosition); + final end = isHorizontal + ? Offset(nextPosition, fixedCoordinate) + : Offset(fixedCoordinate, nextPosition); + canvas.drawLine(start, end, paint); + } + + currentPosition = nextPosition; + drawSolid = !drawSolid; } - return path; } @override - bool shouldRepaint(covariant CustomPainter oldDelegate) { - return oldDelegate != this; + bool shouldRepaint(DashedPainter oldDelegate) { + return color != oldDelegate.color || + strokeWidth != oldDelegate.strokeWidth || + gap != oldDelegate.gap || + solidLength != oldDelegate.solidLength || + direction != oldDelegate.direction; } } diff --git a/tdesign-component/lib/src/components/divider/td_divider.dart b/tdesign-component/lib/src/components/divider/td_divider.dart index 60f48dc1e..5bcf81858 100644 --- a/tdesign-component/lib/src/components/divider/td_divider.dart +++ b/tdesign-component/lib/src/components/divider/td_divider.dart @@ -3,11 +3,7 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; import 'dashed_widget.dart'; -enum TextAlignment { - left, - center, - right -} +enum TextAlignment { left, center, right } /// 分割线 /// 对于非flutter原有的控件,则只需满足TDesign规范即可; @@ -18,7 +14,7 @@ class TDDivider extends StatelessWidget { this.color, this.margin, this.width, - this.height, + this.height = 0.5, this.text, this.textStyle, this.widget, @@ -45,7 +41,7 @@ class TDDivider extends StatelessWidget { final double? width; /// 高度,横向线条使用 - final double? height; + final double height; /// 文本字符串,使用默认样式 final String? text; @@ -62,15 +58,14 @@ class TDDivider extends StatelessWidget { /// 是否为虚线 final bool isDashed; - /// 方向,竖直虚线必须传 + /// 方向,竖直虚线必须传 final Axis direction; @override Widget build(BuildContext context) { // 普通直线 if (widget == null && text == null) { - return _buildLine(context, - width: width, height: height, margin: margin, color: color); + return _buildLine(context, width: width, margin: margin); } // 隐藏线条,纯文本分割 @@ -83,102 +78,48 @@ class TDDivider extends StatelessWidget { ); } - // 文本+线条 + // 文本 + 线条 return _buildDivider(context, alignment); } Widget _buildDivider(BuildContext context, TextAlignment alignment) { - switch(alignment) { + final middleWidget = Padding( + padding: gapPadding ?? const EdgeInsets.symmetric(horizontal: 8), + child: _buildMiddleWidget(context)); + + final line = Expanded(child: Center(child: _buildLine(context))); + + final lineWithWidth = _buildLine(context, width: 16); + + List children; + + switch (alignment) { case TextAlignment.left: - return Container( - width: width, - margin: margin, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - _buildLine( - context, - width: 16, - height: height ?? 0.5, - color: color ?? TDTheme.of(context).grayColor3, - ), - Padding( - padding: gapPadding ?? const EdgeInsets.only(left: 8, right: 8), - child: _buildMiddleWidget(context)), - Expanded( - child: Center( - child: _buildLine( - context, - height: height ?? 0.5, - color: color ?? TDTheme.of(context).grayColor3, - ))), - ], - ), - ); + children = [lineWithWidth, middleWidget, line]; + break; case TextAlignment.center: - return Container( - width: width, - margin: margin, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Center( - child: _buildLine( - context, - height: height ?? 0.5, - color: color ?? TDTheme.of(context).grayColor3, - ), - )), - Padding( - padding: gapPadding ?? const EdgeInsets.only(left: 8, right: 8), - child: _buildMiddleWidget(context)), - Expanded( - child: Center( - child: _buildLine( - context, - height: height ?? 0.5, - color: color ?? TDTheme.of(context).grayColor3, - ))), - ], - ), - ); + children = [line, middleWidget, line]; + break; case TextAlignment.right: - return Container( - width: width, - margin: margin, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Center( - child: _buildLine( - context, - height: height ?? 0.5, - color: color ?? TDTheme.of(context).grayColor3, - ), - )), - Padding( - padding: gapPadding ?? const EdgeInsets.only(left: 8, right: 8), - child: _buildMiddleWidget(context)), - _buildLine( - context, - width: 16, - height: height ?? 0.5, - color: color ?? TDTheme.of(context).grayColor3, - ), - ], - ), - ); + children = [line, middleWidget, lineWithWidth]; + break; } + + return Container( + width: width, + margin: margin, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: children, + ), + ); } /// 绘制线条 Container _buildLine(BuildContext context, - {double? width, - double? height, - EdgeInsetsGeometry? margin, - Color? color}) { + {double? width, EdgeInsetsGeometry? margin}) { + final lineColor = color ?? TDTheme.of(context).componentStrokeColor; + if (isDashed) { return Container( width: width, @@ -186,18 +127,18 @@ class TDDivider extends StatelessWidget { child: DashedWidget( width: width, height: height, - color: color ?? TDTheme.of(context).grayColor3, + color: lineColor, direction: direction, ), ); - } else { - return Container( - width: width, - height: height ?? 0.5, - margin: margin, - color: color ?? TDTheme.of(context).grayColor3, - ); } + + return Container( + width: width, + height: height, + margin: margin, + color: lineColor, + ); } /// 构建中间控件 @@ -206,7 +147,7 @@ class TDDivider extends StatelessWidget { TDText( text, font: TDTheme.of(context).fontBodySmall, - textColor: TDTheme.of(context).fontGyColor3, + textColor: TDTheme.of(context).textColorPlaceholder, forceVerticalCenter: true, style: textStyle, ); diff --git a/tdesign-component/lib/src/components/drawer/td_drawer.dart b/tdesign-component/lib/src/components/drawer/td_drawer.dart index 14564c7a4..e736fdaf9 100644 --- a/tdesign-component/lib/src/components/drawer/td_drawer.dart +++ b/tdesign-component/lib/src/components/drawer/td_drawer.dart @@ -104,10 +104,16 @@ class TDDrawer { if (_drawerRoute != null) { return; // 如果抽屉已经显示了,就不要再显示 } + + final overlayEnabled = showOverlay ?? true; + final dismissible = overlayEnabled && (closeOnOverlayClick ?? true); + _drawerRoute = TDSlidePopupRoute( - slideTransitionFrom: placement == TDDrawerPlacement.right ? SlideTransitionFrom.right : SlideTransitionFrom.left, - isDismissible: (showOverlay ?? true) ? (closeOnOverlayClick ?? true) : false, - modalBarrierColor: (showOverlay ?? true) ? null : Colors.transparent, + slideTransitionFrom: placement == TDDrawerPlacement.right + ? SlideTransitionFrom.right + : SlideTransitionFrom.left, + isDismissible: dismissible, + modalBarrierColor: overlayEnabled ? null : Colors.transparent, modalTop: drawerTop, builder: (context) { return TDDrawerWidget( @@ -126,6 +132,7 @@ class TDDrawer { ); }, ); + Navigator.of(context).push(_drawerRoute!).then((_) { // 当抽屉关闭时,将_drawerRoute置为null _deleteRouter(); diff --git a/tdesign-component/lib/src/components/drawer/td_drawer_widget.dart b/tdesign-component/lib/src/components/drawer/td_drawer_widget.dart index fbeff44a6..fa20c85c9 100644 --- a/tdesign-component/lib/src/components/drawer/td_drawer_widget.dart +++ b/tdesign-component/lib/src/components/drawer/td_drawer_widget.dart @@ -11,7 +11,7 @@ import 'td_drawer.dart'; typedef TDDrawerItemClickCallback = void Function(int index, TDDrawerItem item); /// 抽屉内容组件 -/// 可用于Scaffold中的drawer属性 +/// 可用于 Scaffold 中的 drawer 属性 class TDDrawerWidget extends StatelessWidget { const TDDrawerWidget({ super.key, @@ -72,7 +72,7 @@ class TDDrawerWidget extends StatelessWidget { var cellStyle = style; if (cellStyle == null) { cellStyle = TDCellStyle.cellStyle(context); - cellStyle.leftIconColor = TDTheme.of(context).fontGyColor1; + cellStyle.leftIconColor = TDTheme.of(context).brandNormalColor; } var cells = items ?.asMap() @@ -116,14 +116,14 @@ class TDDrawerWidget extends StatelessWidget { ], ); } + return Container( - color: backgroundColor ?? Colors.white, + color: backgroundColor ?? TDTheme.of(context).bgColorContainer, width: width ?? 280, height: double.infinity, child: content, ); } - } /// 抽屉里的列表项 @@ -138,4 +138,4 @@ class TDDrawerItem { /// 完全自定义 final Widget? content; -} \ No newline at end of file +} diff --git a/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_item.dart b/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_item.dart index 1cfe2c017..0904497e8 100644 --- a/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_item.dart +++ b/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_item.dart @@ -12,10 +12,11 @@ import '../tag/td_tag_styles.dart'; import 'td_dropdown_inherited.dart'; import 'td_dropdown_popup.dart'; -typedef TDDropdownItemContentBuilder = Widget Function( - BuildContext context, _TDDropdownItemState itemState, TDDropdownPopup? popupState); +typedef TDDropdownItemContentBuilder = Widget Function(BuildContext context, + _TDDropdownItemState itemState, TDDropdownPopup? popupState); -typedef TDDropdownItemOptionsCallback = void Function(List? options); +typedef TDDropdownItemOptionsCallback = void Function( + List? options); List _getSelected(List? options) { return options?.where((element) => element.selected == true).toList() ?? []; @@ -34,7 +35,6 @@ int _num(List list, int? n) { class TDDropdownItemController { _TDDropdownItemState? _state; - void _bindState(_TDDropdownItemState _tdDropdownMenuState) { _state = _tdDropdownMenuState; } @@ -48,7 +48,6 @@ class TDDropdownItemController { void updateOptions(TDDropdownItemOptionsCallback callback) { _state?.updateOptions(callback); } - } /// 下拉菜单内容 @@ -123,10 +122,13 @@ class TDDropdownItem extends StatefulWidget { static const double operateHeight = 73; - double? get minContentHeight => - multiple == true ? (minHeight != null ? minHeight! + TDDropdownItem.operateHeight : null) : minHeight; - double? get maxContentHeight => - multiple == true ? (maxHeight != null ? maxHeight! + TDDropdownItem.operateHeight : null) : maxHeight; + double? get minContentHeight => multiple == true + ? (minHeight != null ? minHeight! + TDDropdownItem.operateHeight : null) + : minHeight; + + double? get maxContentHeight => multiple == true + ? (maxHeight != null ? maxHeight! + TDDropdownItem.operateHeight : null) + : maxHeight; @override _TDDropdownItemState createState() => _TDDropdownItemState(); @@ -160,7 +162,9 @@ class _TDDropdownItemState extends State { if (widget.builder != null) { return widget.builder!(context, this, popupState); } - return widget.multiple == true || (widget.optionsColumns ?? 1) > 1 ? _getCheckboxList() : _getRadioList(); + return widget.multiple == true || (widget.optionsColumns ?? 1) > 1 + ? _getCheckboxList() + : _getRadioList(); } Widget _getCheckboxList() { @@ -171,32 +175,42 @@ class _TDDropdownItemState extends State { ? widget.maxContentHeight! : directionListenable.value == TDDropdownMenuDirection.auto ? double.infinity - : max(popupState.maxContentHeight - TDDropdownItem.operateHeight, 0); + : max( + popupState.maxContentHeight - TDDropdownItem.operateHeight, 0); return Column( children: [ Container( - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, child: ConstrainedBox( - constraints: BoxConstraints(minHeight: widget.minContentHeight ?? 0.0, maxHeight: maxContentHeight), + constraints: BoxConstraints( + minHeight: widget.minContentHeight ?? 0.0, + maxHeight: maxContentHeight), child: SingleChildScrollView( child: Column( children: List.generate(groupChunk.length, (index) { var entry = groupChunk.entries.elementAt(index); var chunks = entry.value; - var selectIds = _getSelected(widget.options).map((e) => e!.value).toList(); + var selectIds = _getSelected(widget.options) + .map((e) => e!.value) + .toList(); return Column( children: [ groupChunk.length == 1 && entry.key == '__default__' ? const SizedBox.shrink() : Container( width: double.infinity, - padding: EdgeInsets.only(left: paddingNum, top: paddingNum, right: paddingNum), - color: TDTheme.of(context).whiteColor1, - child: TDText(entry.key == '__default__' ? context.resource.other : entry.key), + padding: EdgeInsets.only( + left: paddingNum, + top: paddingNum, + right: paddingNum), + color: TDTheme.of(context).bgColorContainer, + child: TDText(entry.key == '__default__' + ? context.resource.other + : entry.key), ), Container( padding: EdgeInsets.all(paddingNum), - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, child: TDCheckboxGroupContainer( selectIds: isMultiple ? selectIds @@ -208,7 +222,8 @@ class _TDDropdownItemState extends State { children: List.generate(chunks.length, (ri) { var num = _num(chunks[ri], widget.optionsColumns); return Padding( - padding: _getPadding(chunks.length, ri, 'bottom'), + padding: + _getPadding(chunks.length, ri, 'bottom'), child: Row( children: List.generate(num, (ci) { return Expanded( @@ -250,17 +265,21 @@ class _TDDropdownItemState extends State { title: widget.options![index].label, selectColor: widget.options![index].selectedColor, enable: !(widget.options![index].disabled ?? false), + contentDirection: TDContentDirection.left, ), ), ), ); return widget.minContentHeight != null || widget.maxContentHeight != null ? Container( - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, child: ConstrainedBox( constraints: BoxConstraints( - minHeight: widget.minContentHeight ?? 0.0, maxHeight: widget.maxContentHeight ?? double.infinity), - child: widget.maxContentHeight != null ? SingleChildScrollView(child: radios) : radios, + minHeight: widget.minContentHeight ?? 0.0, + maxHeight: widget.maxContentHeight ?? double.infinity), + child: widget.maxContentHeight != null + ? SingleChildScrollView(child: radios) + : radios, ), ) : radios; @@ -285,8 +304,8 @@ class _TDDropdownItemState extends State { color: enable ? checked ? TDTheme.of(context).brandLightColor - : TDTheme.of(context).grayColor1 - : TDTheme.of(context).grayColor2, + : TDTheme.of(context).bgColorSecondaryContainer + : TDTheme.of(context).bgColorSecondaryContainerHover, borderRadius: BorderRadius.all( Radius.circular(TDTheme.of(context).radiusDefault), ), @@ -297,8 +316,8 @@ class _TDDropdownItemState extends State { textColor: enable ? checked ? TDTheme.of(context).brandColor7 - : TDTheme.of(context).fontGyColor1 - : TDTheme.of(context).fontGyColor4, + : TDTheme.of(context).textColorPrimary + : TDTheme.of(context).textColorDisabled, ), ), ), @@ -310,43 +329,48 @@ class _TDDropdownItemState extends State { height: TDDropdownItem.operateHeight, padding: EdgeInsets.all(TDTheme.of(context).spacer16), decoration: BoxDecoration( - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, border: Border( top: BorderSide( - color: TDTheme.of(context).grayColor3, - width: 1, + color: TDTheme.of(context).componentStrokeColor, + width: 0.5, ), bottom: directionListenable.value == TDDropdownMenuDirection.up ? BorderSide( - color: TDTheme.of(context).grayColor3, - width: 1, + color: TDTheme.of(context).componentStrokeColor, + width: 0.5, ) : BorderSide.none, ), ), - child: Row(children: [ - Expanded( - child: TDButton( - text: context.resource.reset, - theme: TDButtonTheme.light, - onTap: () { - reset(); - widget.onReset?.call(); - }, + child: Row( + // spacing: TDTheme.of(context).spacer16, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TDButton( + text: context.resource.reset, + theme: TDButtonTheme.light, + onTap: () { + reset(); + widget.onReset?.call(); + }, + ), ), - ), - SizedBox(width: TDTheme.of(context).spacer16), - Expanded( - child: TDButton( - text: context.resource.confirm, - theme: TDButtonTheme.primary, - onTap: () { - _handleClose(); - widget.onConfirm?.call(_getSelected(widget.options).map((e) => e!.value).toList()); - }, + SizedBox(width: TDTheme.of(context).spacer16), + Expanded( + child: TDButton( + text: context.resource.confirm, + theme: TDButtonTheme.primary, + onTap: () { + _handleClose(); + widget.onConfirm?.call( + _getSelected(widget.options).map((e) => e!.value).toList()); + }, + ), ), - ), - ]), + ], + ), ); } @@ -362,7 +386,9 @@ class _TDDropdownItemState extends State { } Map>> _groupChunkOptions() { - var groupedOptions = widget.options?.groupBy((option) => option.group ?? '__default__') ?? {}; + var groupedOptions = widget.options + ?.groupBy((option) => option.group ?? '__default__') ?? + {}; var groupedChunkOptions = >>{}; var def = groupedOptions.remove('__default__'); if (def != null) { @@ -380,12 +406,15 @@ class _TDDropdownItemState extends State { selected = [selected.last]; } widget.options?.forEach((element) { - element.selected = selected is List ? selected.contains(element.value) : element.value == selected; + element.selected = selected is List + ? selected.contains(element.value) + : element.value == selected; }); if (isRadio) { setState(() {}); } - widget.onChange?.call(_getSelected(widget.options).map((e) => e!.value).toList()); + widget.onChange + ?.call(_getSelected(widget.options).map((e) => e!.value).toList()); if (widget.multiple != true && selected.isNotEmpty) { _handleClose(); } @@ -420,7 +449,7 @@ class TDDropdownItemOption { this.group, this.selected = false, this.selectedColor, - this.disabledColor + this.disabledColor, }); /// 选项值 diff --git a/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_menu.dart b/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_menu.dart index 8583ddc5b..fd81fb4bb 100644 --- a/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_menu.dart +++ b/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_menu.dart @@ -23,10 +23,12 @@ enum TDDropdownMenuDirection { } /// 下拉菜单构建器 -typedef TDDropdownItemBuilder = List Function(BuildContext context); +typedef TDDropdownItemBuilder = List Function( + BuildContext context); /// 自定义标签内容 -typedef LabelBuilder = Widget Function(BuildContext context, String label, bool isOpened, int index); +typedef LabelBuilder = Widget Function( + BuildContext context, String label, bool isOpened, int index); /// 下拉菜单 class TDDropdownMenu extends StatefulWidget { @@ -56,7 +58,7 @@ class TDDropdownMenu extends StatefulWidget { final List? items; /// 是否在点击遮罩层后关闭菜单 - final bool closeOnClickOverlay; + final bool? closeOnClickOverlay; /// 菜单展开方向(down、up、auto) final TDDropdownMenuDirection? direction; @@ -98,7 +100,8 @@ class TDDropdownMenu extends StatefulWidget { _TDDropdownMenuState createState() => _TDDropdownMenuState(); } -class _TDDropdownMenuState extends State with TickerProviderStateMixin { +class _TDDropdownMenuState extends State + with TickerProviderStateMixin { List? _items; List? _iconControllers; late List> _iconAnimations; @@ -122,7 +125,8 @@ class _TDDropdownMenuState extends State with TickerProviderStat @override void didUpdateWidget(TDDropdownMenu oldWidget) { super.didUpdateWidget(oldWidget); - if (widget.builder != oldWidget.builder || widget.items != oldWidget.items) { + if (widget.builder != oldWidget.builder || + widget.items != oldWidget.items) { _init(); } } @@ -159,11 +163,11 @@ class _TDDropdownMenuState extends State with TickerProviderStat width: widget.width ?? double.infinity, decoration: widget.decoration ?? BoxDecoration( - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, border: Border( bottom: BorderSide( - color: TDTheme.of(context).grayColor3, - width: 1, + color: TDTheme.of(context).componentStrokeColor, + width: 0.5, ), ), ), @@ -185,13 +189,23 @@ class _TDDropdownMenuState extends State with TickerProviderStat _iconControllers = List.generate( _items?.length ?? 0, (index) => AnimationController( - duration: Duration(milliseconds: (widget.duration ?? 200).toInt()), + duration: + Duration(milliseconds: (widget.duration ?? 200).toInt()), vsync: this, )); - _iconAnimations = _iconControllers?.map((e) => Tween(begin: 0, end: 0.5).animate(e)).toList() ?? []; + _iconAnimations = _iconControllers + ?.map((e) => Tween(begin: 0, end: 0.5).animate(e)) + .toList() ?? + []; } Widget _tabBarContent(int index) { + final color = _disabled(index) + ? TDTheme.of(context).textColorDisabled + : _isOpened[index] + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).textColorPrimary; + return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () async { @@ -202,46 +216,40 @@ class _TDDropdownMenuState extends State with TickerProviderStat }, child: Row( mainAxisSize: MainAxisSize.min, - mainAxisAlignment: _items![index].tabBarAlign ?? widget.tabBarAlign ?? MainAxisAlignment.center, - children: [Flexible(child: _getText(index)), _getIcon(index)], + mainAxisAlignment: _items![index].tabBarAlign ?? + widget.tabBarAlign ?? + MainAxisAlignment.center, + children: [ + Flexible(child: _getText(index, color)), + _getIcon(index, color) + ], ), ); } - Widget _getText(int index) { + Widget _getText(int index, Color color) { final label = _items![index].getLabel(); if (widget.labelBuilder != null) { return widget.labelBuilder!(context, label, _isOpened[index], index); } - var textColor = _disabled(index) - ? TDTheme.of(context).fontGyColor4 - : _isOpened[index] - ? TDTheme.of(context).brandColor7 - : TDTheme.of(context).fontGyColor1; return TDText( label, font: TDTheme.of(context).fontBodyMedium, - textColor: textColor, + textColor: color, maxLines: 1, overflow: TextOverflow.ellipsis, ); } - Widget _getIcon(int index) { + Widget _getIcon(int index, Color color) { var arrowIcon = _items![index].arrowIcon ?? widget.arrowIcon ?? - (widget.direction == TDDropdownMenuDirection.up ? TDIcons.caret_up_small : TDIcons.caret_down_small); + (widget.direction == TDDropdownMenuDirection.up + ? TDIcons.caret_up_small + : TDIcons.caret_down_small); return RotationTransition( turns: _iconAnimations[index], - child: Icon( - arrowIcon, - size: 24, - color: _disabled(index) - ? TDTheme.of(context).fontGyColor4 - : _isOpened[index] - ? TDTheme.of(context).brandColor7 - : null, - ), + child: Icon(arrowIcon, size: 20, color: color), ); } @@ -258,7 +266,7 @@ class _TDDropdownMenuState extends State with TickerProviderStat } /// 打开菜单 - Future _openMenu(int index) async { + Future _openMenu(int index) async { /// 如果已经打开了,则关闭 if (_isOpened.contains(true)) { await Navigator.maybePop(context); diff --git a/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_popup.dart b/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_popup.dart index 2de9ffb19..ea55ad76b 100644 --- a/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_popup.dart +++ b/tdesign-component/lib/src/components/dropdown_menu/td_dropdown_popup.dart @@ -26,7 +26,7 @@ class TDDropdownPopup { final FutureCallback handleClose; final TDDropdownPopupDirection? direction; final bool? showOverlay; - final bool closeOnClickOverlay; + final bool? closeOnClickOverlay; final Duration? duration; /// _overlay1:下拉方向的 @@ -48,12 +48,15 @@ class TDDropdownPopup { _initContentTop, _initContentBottom; final _closeListenable = ValueNotifier(null); - final _directionListenable = ValueNotifier(TDDropdownPopupDirection.auto); + final _directionListenable = + ValueNotifier(TDDropdownPopupDirection.auto); final _colorAlphaListenable = ValueNotifier(false); Duration get _duration => duration ?? const Duration(milliseconds: 200); - double get maxContentHeight => direction == TDDropdownPopupDirection.down ? _initContentBottom : _initContentTop; + double get maxContentHeight => direction == TDDropdownPopupDirection.down + ? _initContentBottom + : _initContentTop; void _init(TDDropdownPopupDirection d) { final ancestor = Navigator.of(parentContext).context.findRenderObject(); @@ -96,19 +99,24 @@ class TDDropdownPopup { return _directionListenable.value == TDDropdownPopupDirection.auto ? ValueListenableBuilder( valueListenable: _directionListenable, - builder: (context, value, child) => value == TDDropdownPopupDirection.auto - ? child! - : _getPopup(value, updateChild, completer), // 每次重新渲染item,更新高度 - child: _getPopup(TDDropdownPopupDirection.down, updateChild, completer), + builder: (context, value, child) => + value == TDDropdownPopupDirection.auto + ? child! + : _getPopup( + value, updateChild, completer), // 每次重新渲染item,更新高度 + child: _getPopup( + TDDropdownPopupDirection.down, updateChild, completer), ) : _getPopup(_directionListenable.value, updateChild, completer); }, ); - Navigator.push(parentContext, _PopupOverlayRoute(overlayEntry, handleClose)); + Navigator.push( + parentContext, _PopupOverlayRoute(overlayEntry, handleClose)); return completer.future; } - Widget _getPopup(TDDropdownMenuDirection value, TDDropdownItem? updateChild, Completer completer) { + Widget _getPopup(TDDropdownMenuDirection value, TDDropdownItem? updateChild, + Completer completer) { _init(value); final barrier = GestureDetector( behavior: HitTestBehavior.opaque, diff --git a/tdesign-component/lib/src/components/empty/td_empty.dart b/tdesign-component/lib/src/components/empty/td_empty.dart index b24ab3146..ff3c764bb 100644 --- a/tdesign-component/lib/src/components/empty/td_empty.dart +++ b/tdesign-component/lib/src/components/empty/td_empty.dart @@ -7,35 +7,47 @@ typedef TDTapEvent = void Function(); enum TDEmptyType { plain, operation } class TDEmpty extends StatelessWidget { - const TDEmpty( - {this.type = TDEmptyType.plain, - this.image, - this.emptyText, - this.operationText, - this.operationTheme, - this.onTapEvent, - this.emptyTextColor, - this.emptyTextFont, - this.customOperationWidget, - Key? key}) - : super(key: key); + const TDEmpty({ + this.type = TDEmptyType.plain, + this.icon = TDIcons.info_circle_filled, + this.image, + this.emptyText, + this.operationText, + this.operationTheme, + this.onTapEvent, + this.emptyTextColor, + this.emptyTextFont, + this.customOperationWidget, + Key? key, + }) : super(key: key); /// 点击事件 final TDTapEvent? onTapEvent; + + /// 图标 + final IconData? icon; + /// 展示图片 final Widget? image; + /// 描述文字 final String? emptyText; + /// 描述文字颜色 - final Color? emptyTextColor; + final Color? emptyTextColor; + /// 描述文字大小 - final Font? emptyTextFont; + final Font? emptyTextFont; + /// 操作按钮文案 final String? operationText; + /// 操作按钮文案主题色 final TDButtonTheme? operationTheme; + /// 类型,为operation有操作按钮,plain无按钮 final TDEmptyType type; + /// 自定义操作按钮 final Widget? customOperationWidget; @@ -46,32 +58,35 @@ class TDEmpty extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - image ?? Icon( - TDIcons.info_circle_filled, - size: 96, - color: TDTheme.of(context).fontGyColor3, - ), + image ?? + Icon( + icon ?? TDIcons.info_circle_filled, + size: 96, + color: TDTheme.of(context).textColorPlaceholder, + ), Padding(padding: EdgeInsets.only(top: image == null ? 22 : 16)), TDText( emptyText ?? '', fontWeight: FontWeight.w400, - font: emptyTextFont??TDTheme.of(context).fontBodyMedium, - textColor: emptyTextColor??TDTheme.of(context).fontGyColor2.withOpacity(0.6), + font: emptyTextFont ?? TDTheme.of(context).fontBodyMedium, + textColor: + emptyTextColor ?? TDTheme.of(context).textColorPlaceholder, ), (type == TDEmptyType.operation) - ? customOperationWidget ?? Padding( - padding: const EdgeInsets.only(top: 32), - child: TDButton( - text: operationText ?? '', - size: TDButtonSize.large, - theme: operationTheme??TDButtonTheme.primary, - width: 179, - onTap: () { - if (onTapEvent != null) { - onTapEvent!(); - } - }, - )) + ? customOperationWidget ?? + Padding( + padding: const EdgeInsets.only(top: 32), + child: TDButton( + text: operationText ?? '', + size: TDButtonSize.large, + theme: operationTheme ?? TDButtonTheme.primary, + width: 179, + onTap: () { + if (onTapEvent != null) { + onTapEvent!(); + } + }, + )) : Container() ], ), diff --git a/tdesign-component/lib/src/components/fab/td_fab.dart b/tdesign-component/lib/src/components/fab/td_fab.dart index 57143edc0..1e529a880 100644 --- a/tdesign-component/lib/src/components/fab/td_fab.dart +++ b/tdesign-component/lib/src/components/fab/td_fab.dart @@ -1,9 +1,7 @@ - import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; - enum TDFabTheme { primary, defaultTheme, light, danger } enum TDFabShape { @@ -19,15 +17,15 @@ enum TDFabSize { } class TDFab extends StatelessWidget { - const TDFab( - {Key? key, - this.theme = TDFabTheme.defaultTheme, - this.shape = TDFabShape.circle, - this.size = TDFabSize.large, - this.text, - this.onClick, - this.icon}) - : super(key: key); + const TDFab({ + Key? key, + this.theme = TDFabTheme.defaultTheme, + this.shape = TDFabShape.circle, + this.size = TDFabSize.large, + this.text, + this.onClick, + this.icon, + }) : super(key: key); /// 主题 final TDFabTheme theme; @@ -47,7 +45,7 @@ class TDFab extends StatelessWidget { /// 点击事件 final VoidCallback? onClick; - bool get showText => text != null && text != ''; + bool get showText => text?.isNotEmpty ?? false; EdgeInsets getPadding() { switch (size) { @@ -67,10 +65,6 @@ class TDFab extends StatelessWidget { return showText ? const EdgeInsets.symmetric(horizontal: 8, vertical: 3) : const EdgeInsets.all(5); - default: - return showText - ? const EdgeInsets.symmetric(horizontal: 20, vertical: 12) - : const EdgeInsets.all(12); } } @@ -84,8 +78,6 @@ class TDFab extends StatelessWidget { return 32.0; case TDFabSize.extraSmall: return 28.0; - default: - return 48.0; } } @@ -99,8 +91,6 @@ class TDFab extends StatelessWidget { return TDTheme.of(context).brandColor1; case TDFabTheme.danger: return TDTheme.of(context).errorColor6; - default: - return TDTheme.of(context).grayColor3; } } @@ -109,13 +99,11 @@ class TDFab extends StatelessWidget { case TDFabTheme.primary: return Colors.white; case TDFabTheme.defaultTheme: - return TDTheme.of(context).fontGyColor1.withOpacity(0.9); + return TDTheme.of(context).fontGyColor1; case TDFabTheme.light: - return TDTheme.of(context).brandColor7; + return TDTheme.of(context).brandNormalColor; case TDFabTheme.danger: return Colors.white; - default: - return TDTheme.of(context).fontGyColor1.withOpacity(0.9); } } @@ -129,8 +117,6 @@ class TDFab extends StatelessWidget { return 18.0; case TDFabSize.extraSmall: return 18.0; - default: - return 24.0; } } @@ -144,73 +130,61 @@ class TDFab extends StatelessWidget { return 14.0; case TDFabSize.extraSmall: return 14.0; - default: - return 16.0; } } @override Widget build(BuildContext context) { - return GestureDetector( - onTap: () { - if (onClick != null) { - onClick!(); - } - }, - child: InkWell( - child: Container( - padding: getPadding(), - decoration: BoxDecoration( - color: getBackgroundColor(context), - boxShadow: [ - BoxShadow( - offset: const Offset(0, 5), - blurRadius: 2.5, - spreadRadius:-1.5, - color: Colors.black.withOpacity(0.1)), - BoxShadow( - offset: const Offset(0, 8), - blurRadius: 5, - spreadRadius:0.5, - color: Colors.black.withOpacity(0.06)), - BoxShadow( - offset: const Offset(0, 3), - blurRadius: 7, - spreadRadius:1, - color: Colors.black.withOpacity(0.05)) - ], - borderRadius: shape == TDFabShape.circle - ? BorderRadius.circular(24) - : BorderRadius.circular(6)), - height: getMinWidthOrHeight(), - child: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - icon ?? - Icon( - TDIcons.add, - size: getIconSize(), - color: getIconColor(context), - ), - Visibility( - visible: showText, - child: const SizedBox( - width: 4, - )), - Visibility( - visible: showText, - child: TDText( - text ?? '', - style: TextStyle( - height: 1.5, - fontWeight: FontWeight.w600, - fontSize: getFontSize(), - color: getIconColor(context), - leadingDistribution: TextLeadingDistribution.even), - )) + return InkWell( + onTap: onClick, + child: Container( + padding: getPadding(), + decoration: BoxDecoration( + color: getBackgroundColor(context), + boxShadow: [ + BoxShadow( + offset: const Offset(0, 5), + blurRadius: 2.5, + spreadRadius: -1.5, + color: Colors.black.withOpacity(0.1)), + BoxShadow( + offset: const Offset(0, 8), + blurRadius: 5, + spreadRadius: 0.5, + color: Colors.black.withOpacity(0.06)), + BoxShadow( + offset: const Offset(0, 3), + blurRadius: 7, + spreadRadius: 1, + color: Colors.black.withOpacity(0.05)) ], - ), + borderRadius: shape == TDFabShape.circle + ? BorderRadius.circular(TDTheme.of(context).radiusCircle) + : BorderRadius.circular(TDTheme.of(context).radiusDefault)), + height: getMinWidthOrHeight(), + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + icon ?? + Icon( + TDIcons.add, + size: getIconSize(), + color: getIconColor(context), + ), + if (showText) const SizedBox(width: 4), + if (showText) + TDText( + text ?? '', + style: TextStyle( + height: 1.5, + fontWeight: FontWeight.w600, + fontSize: getFontSize(), + color: getIconColor(context), + leadingDistribution: TextLeadingDistribution.even, + ), + ), + ], ), ), ); diff --git a/tdesign-component/lib/src/components/footer/td_footer.dart b/tdesign-component/lib/src/components/footer/td_footer.dart index 33d077bb2..0b6100ef8 100644 --- a/tdesign-component/lib/src/components/footer/td_footer.dart +++ b/tdesign-component/lib/src/components/footer/td_footer.dart @@ -49,38 +49,29 @@ class TDFooter extends StatefulWidget { class _TDFooterState extends State { @override Widget build(BuildContext context) { + var children = []; + switch (widget.type) { case TDFooterType.text: - return Container( - alignment: Alignment.center, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _renderText(), - ], - ), - ); + children = [_renderText()]; + break; case TDFooterType.link: - return Container( - alignment: Alignment.center, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (widget.links.isNotEmpty) _renderLinks() else _renderText(), - ], - ), - ); + children = [ + if (widget.links.isNotEmpty) _renderLinks() else _renderText() + ]; + break; case TDFooterType.brand: - return Container( - alignment: Alignment.center, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (widget.logo != null) _renderLogo() else _renderText(), - ], - ), - ); + children = [if (widget.logo != null) _renderLogo() else _renderText()]; + break; } + + return Container( + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: children, + ), + ); } Widget _renderLogo() { @@ -112,7 +103,8 @@ class _TDFooterState extends State { ? BoxDecoration( border: Border( right: BorderSide( - color: TDTheme.of(context).grayColor3))) + color: + TDTheme.of(context).textColorPlaceholder))) : null, padding: const EdgeInsets.symmetric(horizontal: 6), child: link, @@ -136,7 +128,7 @@ class _TDFooterState extends State { textAlign: TextAlign.center, style: TextStyle( fontSize: 12, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ), ); } diff --git a/tdesign-component/lib/src/components/form/td_form.dart b/tdesign-component/lib/src/components/form/td_form.dart index 63eeeee5d..51768cd2d 100644 --- a/tdesign-component/lib/src/components/form/td_form.dart +++ b/tdesign-component/lib/src/components/form/td_form.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; @@ -94,6 +93,7 @@ class TDForm extends StatefulWidget { /// 表单控制器 final FormController? formController; + @override State createState() => _TDFormState(); } @@ -102,42 +102,46 @@ class _TDFormState extends State { List _formItems = []; Map _formData = {}; bool _isValidate = false; - bool _isReset=false; + bool _isReset = false; + //用于更新表单 - int _upDataCount=1; + int _updateCount = 1; + @override void initState() { super.initState(); _formData = widget.data; if (widget.formController != null) { - widget.formController?.addListener((){ - if(widget.formController?.eventType=='submit'){ - onSubmit(); - }else if(widget.formController?.eventType=='reset'){ - onReset(); - } + widget.formController?.addListener(() { + if (widget.formController?.eventType == 'submit') { + onSubmit(); + } else if (widget.formController?.eventType == 'reset') { + onReset(); + } }); } } - onReset(){ - _upDataCount+=1; + + onReset() { + _updateCount += 1; setState(() { - _formData=widget.formController!.formData; - _isReset=true; + _formData = widget.formController!.formData; + _isReset = true; }); } + onSubmit() { - _upDataCount+=1; - _isReset=false; + _updateCount += 1; + _isReset = false; bool isValidateSuc = true; _formData.forEach((key, value) { - if(isValidateSuc){ + if (isValidateSuc) { isValidateSuc = validate(key, '${value}'); } }); if (!isValidateSuc) { setState(() { - _isValidate =true; + _isValidate = true; }); } widget.onSubmit(_formData, isValidateSuc); @@ -145,7 +149,7 @@ class _TDFormState extends State { ///检验表单数据 bool validate(name, value) { - if(widget.rules[name]!=null){ + if (widget.rules[name] != null) { final result = widget.rules[name]!.check(value); if (result != null) { /// 返回第一个不通过的错误信息 @@ -157,7 +161,9 @@ class _TDFormState extends State { @override Widget build(BuildContext context) { - _formItems = widget.items.expand((item) => [item, SizedBox(height: 1)]).toList(); + _formItems = widget.items + .expand((item) => [item, const SizedBox(height: 1)]) + .toList(); if (widget.btnGroup?.isNotEmpty ?? false) { _formItems.addAll(widget.btnGroup ?? []); } @@ -170,18 +176,18 @@ class _TDFormState extends State { formContentAlign: widget.formContentAlign, formShowErrorMessage: widget.formShowErrorMessage, requiredMark: widget.requiredMark, - updataCount: _upDataCount, + updateCount: _updateCount, onFormDataChange: (value) { ///监听表单数据变化 _formData = value; }, - isReset:_isReset, + isReset: _isReset, onSubmit: onSubmit, child: ListView.builder( itemCount: _formItems.length, itemBuilder: (context, index) => _formItems[index], shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), cacheExtent: 500, ), ); @@ -189,15 +195,17 @@ class _TDFormState extends State { } class FormController with ChangeNotifier { - String eventType=''; - Map formData={}; + String eventType = ''; + Map formData = {}; + submit() { - eventType='submit'; + eventType = 'submit'; notifyListeners(); } - reset(Map data){ - formData=data; - eventType='reset'; + + reset(Map data) { + formData = data; + eventType = 'reset'; notifyListeners(); } } diff --git a/tdesign-component/lib/src/components/form/td_form_inherited.dart b/tdesign-component/lib/src/components/form/td_form_inherited.dart index 28193c887..ec51b840f 100644 --- a/tdesign-component/lib/src/components/form/td_form_inherited.dart +++ b/tdesign-component/lib/src/components/form/td_form_inherited.dart @@ -13,8 +13,9 @@ class TDFormInherited extends InheritedWidget { final TextAlign formContentAlign; final Function onFormDataChange; final bool isReset; - final int updataCount; + final int updateCount; final Function onSubmit; + const TDFormInherited({ super.key, required this.formData, @@ -26,7 +27,7 @@ class TDFormInherited extends InheritedWidget { required this.onFormDataChange, required this.onSubmit, required this.requiredMark, - required this.updataCount, + required this.updateCount, this.labelWidth, this.formShowErrorMessage, required this.isReset, @@ -38,7 +39,7 @@ class TDFormInherited extends InheritedWidget { @override bool updateShouldNotify(TDFormInherited oldWidget) { - return updataCount != oldWidget.updataCount || + return updateCount != oldWidget.updateCount || isReset != oldWidget.isReset || labelWidth != oldWidget.labelWidth || isHorizontal != oldWidget.isHorizontal || diff --git a/tdesign-component/lib/src/components/form/td_form_item.dart b/tdesign-component/lib/src/components/form/td_form_item.dart index 4580d0c11..b203a9be4 100644 --- a/tdesign-component/lib/src/components/form/td_form_item.dart +++ b/tdesign-component/lib/src/components/form/td_form_item.dart @@ -1,14 +1,21 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'td_form_inherited.dart'; import '../../../tdesign_flutter.dart'; /// 表格单元选用组件类型的枚举 -enum TDFormItemType { input, radios, dateTimePicker, cascader, stepper, rate, textarea, upLoadImg } +enum TDFormItemType { + input, + radios, + dateTimePicker, + cascader, + stepper, + rate, + textarea, + upLoadImg +} class TDFormItem extends StatefulWidget { - TDFormItem({ + const TDFormItem({ required this.type, this.child, this.formItemNotifier, @@ -73,7 +80,7 @@ class TDFormItem extends StatefulWidget { final FormItemNotifier? formItemNotifier; /// 选择器 适用于日期选择器等 - String select; + final String select; /// 选择器方法 适用于日期选择器等 final Function? selectFn; @@ -95,9 +102,10 @@ class TDFormItem extends StatefulWidget { ///提示内容 final hintText; - + /// 背景色 final Color? backgroundColor; + @override _TDFormItemState createState() => _TDFormItemState(); } @@ -107,7 +115,7 @@ class _TDFormItemState extends State { void initState() { // TODO: implement initState super.initState(); - if(!(widget.formItemNotifier?.isDisposed ?? true)) { + if (!(widget.formItemNotifier?.isDisposed ?? true)) { widget.formItemNotifier?.addListener(() { updateFormData(widget.formItemNotifier?.formVal); }); @@ -117,7 +125,8 @@ class _TDFormItemState extends State { @override void dispose() { super.dispose(); - if (widget.formItemNotifier != null && !widget.formItemNotifier!.isDisposed) { + if (widget.formItemNotifier != null && + !widget.formItemNotifier!.isDisposed) { widget.formItemNotifier?.dispose(); } } @@ -266,12 +275,18 @@ class _TDFormItemState extends State { child: widget.labelWidget ?? Row( children: [ - TDText(widget.label, font: TDTheme.of(context).fontBodyMedium, textAlign: widget.labelAlign), - if (FormRequiredMark && (widget.requiredMark != null && widget.requiredMark == true)) + TDText(widget.label, + font: TDTheme.of(context).fontBodyMedium, + textAlign: widget.labelAlign), + if (FormRequiredMark && + (widget.requiredMark != null && + widget.requiredMark == true)) Padding( padding: const EdgeInsets.only(left: 4), child: TDText('*', - style: const TextStyle(fontSize: 12), textColor: Colors.red, textAlign: widget.labelAlign), + style: const TextStyle(fontSize: 12), + textColor: Colors.red, + textAlign: widget.labelAlign), ), ], ))); @@ -304,9 +319,8 @@ class _TDFormItemState extends State { case TDFormItemType.input: case TDFormItemType.rate: return Container( - decoration: BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, - ), + color: + widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Padding( padding: const EdgeInsets.all(16), child: Column( @@ -323,14 +337,15 @@ class _TDFormItemState extends State { children: itemColumnContent, ), ), - _buildTipRow(left: 0, top: TDFormItemType.rate == widget.type ? 4 : 0) + _buildTipRow( + left: 0, + top: TDFormItemType.rate == widget.type ? 4 : 0) ], ))); case TDFormItemType.radios: return Container( - decoration: BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, - ), + color: + widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Padding( padding: const EdgeInsets.all(16), child: Column( @@ -355,12 +370,11 @@ class _TDFormItemState extends State { return _buildSelectRow(context); case TDFormItemType.stepper: return Container( - decoration: BoxDecoration( - color: widget.backgroundColor ?? theme.whiteColor1, - ), + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Padding( padding: const EdgeInsets.all(16), - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + child: + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Visibility( visible: FormIsHorizontal, child: Row( @@ -378,9 +392,8 @@ class _TDFormItemState extends State { ); case TDFormItemType.textarea: return Container( - decoration: BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, - ), + color: + widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Padding( padding: const EdgeInsets.all(16), child: Column( @@ -388,10 +401,14 @@ class _TDFormItemState extends State { children: [ Visibility( visible: FormIsHorizontal, - child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Visibility(visible: widget.label != null ? true : false, child: labelContent), - Expanded(child: widget.child ?? SizedBox()), - ]), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Visibility( + visible: widget.label != null ? true : false, + child: labelContent), + Expanded(child: widget.child ?? SizedBox()), + ]), replacement: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -401,7 +418,8 @@ class _TDFormItemState extends State { width: LabelWidth, child: widget.labelWidget ?? TDText(widget.label, - font: TDTheme.of(context).fontBodyMedium, textAlign: widget.labelAlign), + font: TDTheme.of(context).fontBodyMedium, + textAlign: widget.labelAlign), ), ), widget.child ?? SizedBox() @@ -413,14 +431,16 @@ class _TDFormItemState extends State { ))); case TDFormItemType.upLoadImg: return Container( - decoration: BoxDecoration(color: widget.backgroundColor ?? theme.whiteColor1), + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Padding( padding: const EdgeInsets.all(16), child: Column( children: [ Visibility( visible: FormIsHorizontal, - child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: itemRowContent), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: itemRowContent), replacement: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -430,7 +450,8 @@ class _TDFormItemState extends State { width: LabelWidth, child: widget.labelWidget ?? TDText(widget.label, - font: TDTheme.of(context).fontBodyMedium, textAlign: widget.labelAlign), + font: TDTheme.of(context).fontBodyMedium, + textAlign: widget.labelAlign), )), widget.child ?? SizedBox() ], @@ -448,27 +469,34 @@ class _TDFormItemState extends State { width: LabelWidth, child: widget.labelWidget ?? Padding( - padding: EdgeInsets.only(left: 2), + padding: const EdgeInsets.only(left: 2), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - TDText(widget.label ?? '', font: TDTheme.of(context).fontBodyMedium, textAlign: widget.labelAlign), - if (FormRequiredMark && (widget.requiredMark != null && widget.requiredMark == true)) + TDText(widget.label ?? '', + font: TDTheme.of(context).fontBodyMedium, + textAlign: widget.labelAlign), + if (FormRequiredMark && + (widget.requiredMark != null && + widget.requiredMark == true)) Padding( padding: const EdgeInsets.only(left: 4), child: TDText('*', - style: const TextStyle(fontSize: 12), textColor: Colors.red, textAlign: widget.labelAlign), + style: const TextStyle(fontSize: 12), + textColor: Colors.red, + textAlign: widget.labelAlign), ), ], ), ), ); Widget selectText = TDText( - textAlign: FormContentAlign, widget.select != '' ? widget.select : widget.hintText, + textAlign: FormContentAlign, font: TDTheme.of(context).fontBodyLarge, - textColor: - widget.select != '' ? TDTheme.of(context).fontGyColor1 : TDTheme.of(context).fontGyColor3.withOpacity(0.4), + textColor: widget.select != '' + ? TDTheme.of(context).textColorPrimary + : TDTheme.of(context).textColorPlaceholder, maxLines: 1, overflow: TextOverflow.ellipsis, ); @@ -482,7 +510,7 @@ class _TDFormItemState extends State { padding: const EdgeInsets.only(left: 2), child: Icon( TDIcons.chevron_right, - color: TDTheme.of(context).fontGyColor3.withOpacity(0.4), + color: TDTheme.of(context).textColorPlaceholder, ), ), ], @@ -496,7 +524,7 @@ class _TDFormItemState extends State { } }, child: Container( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -531,7 +559,7 @@ class _TDFormItemState extends State { padding: const EdgeInsets.only(left: 2), child: Icon( TDIcons.chevron_right, - color: TDTheme.of(context).fontGyColor3.withOpacity(0.4), + color: TDTheme.of(context).textColorPlaceholder, ), ), ], @@ -552,31 +580,38 @@ class _TDFormItemState extends State { if (widget.help != null && (errorMessage == null || errorMessage == '')) Row( children: [ - if (widget.label != null && FormIsHorizontal) SizedBox(width: LabelWidth), + if (widget.label != null && FormIsHorizontal) + SizedBox(width: LabelWidth), Expanded( child: Padding( - padding: EdgeInsets.only(left: left, right: right, top: top), + padding: + EdgeInsets.only(left: left, right: right, top: top), child: TDText( widget.help, font: TDTheme.of(context).fontBodySmall, textAlign: widget.tipAlign ?? TextAlign.left, - textColor: const Color.fromRGBO(0, 0, 0, 0.4), + textColor: TDTheme.of(context).textColorPlaceholder, )), ) ], ), - if (ShowErrorMessage != null && ShowErrorMessage! && errorMessage != null && errorMessage != '') + if (ShowErrorMessage != null && + ShowErrorMessage! && + errorMessage != null && + errorMessage != '') Row( children: [ - if (widget.label != null && FormIsHorizontal) SizedBox(width: LabelWidth), + if (widget.label != null && FormIsHorizontal) + SizedBox(width: LabelWidth), Expanded( child: Padding( - padding: EdgeInsets.only(left: left, right: right, top: top), + padding: + EdgeInsets.only(left: left, right: right, top: top), child: TDText( errorMessage, font: TDTheme.of(context).fontBodySmall, textAlign: widget.tipAlign ?? TextAlign.left, - textColor: Color.fromRGBO(213, 73, 65, 1), + textColor: TDTheme.of(context).errorNormalColor, ))) ], ), @@ -586,10 +621,11 @@ class _TDFormItemState extends State { } class FormItemNotifier with ChangeNotifier { - bool isDisposed = false; String _formVal = ''; + String get formVal => _formVal; + upDataForm(val) { _formVal = val; notifyListeners(); diff --git a/tdesign-component/lib/src/components/image/image_widget.dart b/tdesign-component/lib/src/components/image/image_widget.dart index 5a15ef9c5..6d1f64c18 100644 --- a/tdesign-component/lib/src/components/image/image_widget.dart +++ b/tdesign-component/lib/src/components/image/image_widget.dart @@ -1,6 +1,6 @@ +import 'dart:io'; import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; -import 'dart:io'; ///封装图片加载控件,增加图片加载失败时加载默认图片 class ImageWidget extends StatefulWidget { @@ -123,8 +123,8 @@ class ImageWidget extends StatefulWidget { this.assetUrl, this.cacheHeight, this.imageFile}) - : image = ResizeImage.resizeIfNeeded( - cacheWidth, cacheHeight, NetworkImage(src ?? '', scale: scale, headers: headers)), + : image = ResizeImage.resizeIfNeeded(cacheWidth, cacheHeight, + NetworkImage(src ?? '', scale: scale, headers: headers)), assert(cacheWidth == null || cacheWidth > 0), assert(cacheHeight == null || cacheHeight > 0), super(key: key); @@ -161,7 +161,8 @@ class ImageWidget extends StatefulWidget { cacheWidth, cacheHeight, scale != null - ? ExactAssetImage(assetUrl ?? '', bundle: bundle, scale: scale, package: package) + ? ExactAssetImage(assetUrl ?? '', + bundle: bundle, scale: scale, package: package) : AssetImage(assetUrl ?? '', bundle: bundle, package: package), ), loadingBuilder = null, @@ -196,16 +197,13 @@ class ImageWidget extends StatefulWidget { this.errorWidget, this.loadingWidget, this.src, - }) : image = ResizeImage.resizeIfNeeded(cacheWidth, cacheHeight, FileImage(imageFile!, scale: scale)), + }) : image = ResizeImage.resizeIfNeeded( + cacheWidth, cacheHeight, FileImage(imageFile!, scale: scale)), loadingBuilder = null, - assert(alignment != null), - assert(repeat != null), - assert(filterQuality != null), - assert(matchTextDirection != null), assert(cacheWidth == null || cacheWidth > 0), assert(cacheHeight == null || cacheHeight > 0), - assert(isAntiAlias != null), super(key: key); + @override State createState() { return _StateImageWidget(); @@ -333,32 +331,43 @@ class _StateImageWidget extends State { @override Widget build(BuildContext context) { - if (error == false && loading == true) { + final alignment = widget.alignment; + final color = widget.color ?? TDTheme.of(context).bgColorContainerHover; + + // 优先处理 loading 状态 + if (loading) { return Container( - alignment: widget.alignment, - color: widget.color ?? TDTheme.of(context).grayColor2, - child: widget.loadingWidget ?? - Icon( - TDIcons.ellipsis, - size: 22, - color: TDTheme.of(context).fontGyColor3, - )); + alignment: alignment, + color: color, + child: widget.loadingWidget ?? + Icon( + TDIcons.ellipsis, + size: 22, + color: TDTheme.of(context).textColorPlaceholder, + ), + ); } - if (error == true && loading == false) { + + // 其次处理 error 状态 + if (error) { return Container( - alignment: widget.alignment, - color: widget.color ?? TDTheme.of(context).grayColor2, + alignment: alignment, + color: color, child: widget.errorWidget ?? Icon( TDIcons.close, size: 22, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ), ); } - if (loading == false && error == false) { + + // 默认显示图片 + if (!loading && !error) { return _image; } + + // 特殊状态组合兜底(理论上不会走到这里) return Container(); } diff --git a/tdesign-component/lib/src/components/image/td_image.dart b/tdesign-component/lib/src/components/image/td_image.dart index 9eaa14f4b..7d73262ff 100644 --- a/tdesign-component/lib/src/components/image/td_image.dart +++ b/tdesign-component/lib/src/components/image/td_image.dart @@ -1,8 +1,9 @@ +import 'dart:io'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; + import '../../../tdesign_flutter.dart'; -import '../../util/string_util.dart'; -import 'dart:io'; enum TDImageType { /// 裁剪 @@ -126,6 +127,7 @@ class TDImage extends StatefulWidget { } class _TDImageState extends State { + /// @todo 重复代码,需简化 @override Widget build(BuildContext context) { switch (widget.type) { @@ -279,7 +281,9 @@ class _TDImageState extends State { return widget.imageFile == null ? (widget.assetUrl == null ? ConstrainedBox( - constraints: BoxConstraints(maxHeight: widget.height ?? 72, maxWidth: widget.width ?? 72), + constraints: BoxConstraints( + maxHeight: widget.height ?? 72, + maxWidth: widget.width ?? 72), child: ImageWidget.network( widget.imgUrl, height: widget.height ?? 72, @@ -307,7 +311,9 @@ class _TDImageState extends State { ), ) : ConstrainedBox( - constraints: BoxConstraints(maxHeight: widget.height ?? 72, maxWidth: widget.width ?? 72), + constraints: BoxConstraints( + maxHeight: widget.height ?? 72, + maxWidth: widget.width ?? 72), child: ImageWidget.asset( widget.assetUrl!, width: widget.width ?? 72, @@ -432,7 +438,9 @@ class _TDImageState extends State { height: widget.height ?? 72, width: widget.width ?? 72, clipBehavior: Clip.hardEdge, - decoration: BoxDecoration(borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault)), + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)), child: widget.imageFile == null ? (widget.assetUrl == null ? ImageWidget.network( diff --git a/tdesign-component/lib/src/components/image_viewer/td_image_viewer_widget.dart b/tdesign-component/lib/src/components/image_viewer/td_image_viewer_widget.dart index 38b9f3ce8..33d3a5565 100644 --- a/tdesign-component/lib/src/components/image_viewer/td_image_viewer_widget.dart +++ b/tdesign-component/lib/src/components/image_viewer/td_image_viewer_widget.dart @@ -128,13 +128,14 @@ class _TDImageViewerWidgetState extends State { @override void initState() { super.initState(); - if(widget.images.isEmpty) { + if (widget.images.isEmpty) { throw FlutterError('images must not be empty'); } - if((widget.defaultIndex ?? 0) > widget.images.length - 1) { + if ((widget.defaultIndex ?? 0) > widget.images.length - 1) { throw FlutterError('defaultIndex must be less than images.length'); } - if(widget.labels != null && widget.images.length != widget.labels!.length) { + if (widget.labels != null && + widget.images.length != widget.labels!.length) { throw FlutterError('labels.length must be equals images.length'); } _index = (widget.defaultIndex ?? 0) + 1; @@ -172,6 +173,7 @@ class _TDImageViewerWidgetState extends State { loadingWidget: Container( width: size.width, height: size.height, + // todo color: TDTheme.of(context).fontGyColor1, child: Center( child: TDLoading( @@ -197,38 +199,42 @@ class _TDImageViewerWidgetState extends State { } Widget _getPageTitle() { - if(widget.labels != null) { + if (widget.labels != null) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Visibility( visible: (widget.labels![_index - 1]) != '', - child: Text(widget.labels![_index - 1], + child: Text( + widget.labels![_index - 1], textAlign: TextAlign.center, - style: widget.labelStyle ?? TextStyle(color: TDTheme.of(context).whiteColor1), + style: widget.labelStyle ?? + TextStyle(color: TDTheme.of(context).textColorAnti), ), ), Visibility( visible: widget.showIndex ?? false, - child: Text('$_index / ${widget.images.length}', + child: Text( + '$_index / ${widget.images.length}', textAlign: TextAlign.center, - style: widget.indexStyle ?? TextStyle(color: TDTheme.of(context).brandClickColor, fontSize: 10), + style: widget.indexStyle ?? + TextStyle( + color: TDTheme.of(context).brandClickColor, fontSize: 10), ), ) ], ); } return Text( - (widget.showIndex ?? false) - ? '$_index / ${widget.images.length}' - : '', + (widget.showIndex ?? false) ? '$_index / ${widget.images.length}' : '', textAlign: TextAlign.center, - style: widget.indexStyle ?? TextStyle(color: TDTheme.of(context).whiteColor1), + style: widget.indexStyle ?? + TextStyle(color: TDTheme.of(context).textColorAnti), ); } Widget _getLeft() { - if(widget.leftItemBuilder != null) { + if (widget.leftItemBuilder != null) { return widget.leftItemBuilder!(context, _index - 1); } return GestureDetector( @@ -241,33 +247,34 @@ class _TDImageViewerWidgetState extends State { }, child: Icon( TDIcons.close, - color: widget.iconColor ?? TDTheme.of(context).whiteColor1, + color: widget.iconColor ?? TDTheme.of(context).textColorAnti, ), ); } Widget _getRight() { - if(widget.rightItemBuilder != null) { + if (widget.rightItemBuilder != null) { return widget.rightItemBuilder!(context, _index - 1); } return Visibility( visible: widget.deleteBtn ?? false, child: GestureDetector( onTap: () { - if(widget.images.length == 1 && !(widget.ignoreDeleteError ?? false)) { + if (widget.images.length == 1 && + !(widget.ignoreDeleteError ?? false)) { throw FlutterError('images must not be empty'); } widget.images.removeAt(_index - 1); widget.onDelete?.call(_index - 1); setState(() { - if(_index > 1) { + if (_index > 1) { _index--; } }); }, child: Icon( TDIcons.delete, - color: widget.iconColor ?? TDTheme.of(context).whiteColor1, + color: widget.iconColor ?? TDTheme.of(context).textColorAnti, ), ), ); @@ -275,7 +282,7 @@ class _TDImageViewerWidgetState extends State { @override Widget build(BuildContext context) { - var media = MediaQuery.of(context); + var media = MediaQuery.of(context); var safeAreaHeight = media.padding.top; return Stack( children: [ @@ -285,6 +292,7 @@ class _TDImageViewerWidgetState extends State { left: 0, right: 0, child: Container( + // todo color: widget.bgColor ?? TDTheme.of(context).fontGyColor1, ), ), @@ -319,7 +327,8 @@ class _TDImageViewerWidgetState extends State { ), SafeArea( child: Container( - color: widget.navBarBgColor ?? const Color(0x66000000), + color: widget.navBarBgColor ?? + TDTheme.of(context).textColorPlaceholder, height: 44, padding: const EdgeInsets.symmetric(horizontal: 12), child: Row( diff --git a/tdesign-component/lib/src/components/indexes/td_indexes.dart b/tdesign-component/lib/src/components/indexes/td_indexes.dart index bd5b32e25..44c1f37b9 100644 --- a/tdesign-component/lib/src/components/indexes/td_indexes.dart +++ b/tdesign-component/lib/src/components/indexes/td_indexes.dart @@ -30,7 +30,7 @@ class TDIndexes extends StatefulWidget { /// 索引字符列表。不传默认 A-Z final List? indexList; - /// 索引列表最大高度(父容器高度的百分比,默认0.8) + /// 索引列表最大高度(父容器高度的百分比,默认 0.8) final double? indexListMaxHeight; /// 锚点是否吸顶 @@ -58,10 +58,12 @@ class TDIndexes extends StatefulWidget { final Widget? Function(BuildContext context, String index) builderContent; /// 锚点自定义构建 - final Widget? Function(BuildContext context, String index, bool isPinnedToTop)? builderAnchor; + final Widget? Function( + BuildContext context, String index, bool isPinnedToTop)? builderAnchor; /// 索引文本自定义构建,包括索引激活左侧提示 - final Widget Function(BuildContext context, String index, bool isActive)? builderIndex; + final Widget Function(BuildContext context, String index, bool isActive)? + builderIndex; @override _TDIndexesState createState() => _TDIndexesState(); @@ -75,10 +77,16 @@ class _TDIndexesState extends State { final _contentKeys = {}; var _isAnimating = false; + /// A-Z 字母字符列表 + static final List _defaultAZList = List.generate( + 26, + (index) => String.fromCharCode(65 + index), + ); + @override void initState() { super.initState(); - _indexList = widget.indexList ?? _azList(); + _indexList = widget.indexList ?? _defaultAZList; _activeIndex = ValueNotifier(_indexList.getOrNull(0) ?? ''); _scrollController = widget.scrollController ?? ScrollController(); } @@ -87,7 +95,7 @@ class _TDIndexesState extends State { void didUpdateWidget(TDIndexes oldWidget) { super.didUpdateWidget(oldWidget); if (widget.indexList != oldWidget.indexList) { - _indexList = widget.indexList ?? _azList(); + _indexList = widget.indexList ?? _defaultAZList; _activeIndex = ValueNotifier(_indexList.getOrNull(0) ?? ''); } if (widget.scrollController != oldWidget.scrollController) { @@ -105,7 +113,7 @@ class _TDIndexesState extends State { @override Widget build(BuildContext context) { return Container( - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, child: Stack( children: [ CustomScrollView( @@ -138,7 +146,9 @@ class _TDIndexesState extends State { final isPinnedOffset = capsuleTheme && _activeIndex.value == e; return SliverStickyHeader.builder( sticky: widget.sticky ?? true, - pinnedOffset: isPinnedOffset ? TDTheme.of(context).spacer8 + stickyOffset : stickyOffset, + pinnedOffset: isPinnedOffset + ? TDTheme.of(context).spacer8 + stickyOffset + : stickyOffset, builder: (context, state) { _anchorKeys[e] = context; if (state.isPinned && _activeIndex.value != e && !_isAnimating) { @@ -160,7 +170,9 @@ class _TDIndexesState extends State { builder: (context) { _contentKeys[e] = context; return Padding( - padding: isPinnedOffset ? EdgeInsets.only(top: TDTheme.of(context).spacer8) : EdgeInsets.zero, + padding: isPinnedOffset + ? EdgeInsets.only(top: TDTheme.of(context).spacer8) + : EdgeInsets.zero, child: widget.builderContent(context, e), ); }, @@ -170,14 +182,6 @@ class _TDIndexesState extends State { }).toList(); } - List _azList() { - final azList = []; - for (var i = 65; i <= 90; i++) { - azList.add(String.fromCharCode(i)); - } - return azList; - } - void _scrollToTarget(String newIndex, String oldIndex) { _isAnimating = true; @@ -185,12 +189,14 @@ class _TDIndexesState extends State { final isUp = _indexList.indexOf(newIndex) > _indexList.indexOf(oldIndex); if (isUp) { var index = oldIndex; - final contentRenderBox = _contentKeys[index]?.findRenderObject() as RenderBox?; + final contentRenderBox = + _contentKeys[index]?.findRenderObject() as RenderBox?; if (contentRenderBox != null) { final contentHeight = contentRenderBox.size.height; final maxScrollExtent = _scrollController.position.maxScrollExtent; - final targetOffset = - contentRenderBox.localToGlobal(Offset(0, contentHeight), ancestor: context.findRenderObject()); + final targetOffset = contentRenderBox.localToGlobal( + Offset(0, contentHeight), + ancestor: context.findRenderObject()); final scrollOffset = targetOffset.dy + _scrollController.offset; _scrollController.jumpTo(min(maxScrollExtent, scrollOffset)); } diff --git a/tdesign-component/lib/src/components/indexes/td_indexes_anchor.dart b/tdesign-component/lib/src/components/indexes/td_indexes_anchor.dart index 8e80163c7..65e7bcbea 100644 --- a/tdesign-component/lib/src/components/indexes/td_indexes_anchor.dart +++ b/tdesign-component/lib/src/components/indexes/td_indexes_anchor.dart @@ -26,7 +26,8 @@ class TDIndexesAnchor extends StatelessWidget { final ValueNotifier activeIndex; /// 索引锚点构建 - final Widget? Function(BuildContext context, String index, bool isPinnedToTop)? builderAnchor; + final Widget? Function( + BuildContext context, String index, bool isPinnedToTop)? builderAnchor; @override Widget build(BuildContext context) { @@ -37,23 +38,39 @@ class TDIndexesAnchor extends StatelessWidget { final customAnchor = builderAnchor?.call(context, text, isPinned); return customAnchor ?? Container( - padding: - EdgeInsets.symmetric(vertical: TDTheme.of(context).spacer4, horizontal: TDTheme.of(context).spacer16), - margin: capsuleTheme ? EdgeInsets.symmetric(horizontal: TDTheme.of(context).spacer8) : null, + padding: EdgeInsets.symmetric( + vertical: TDTheme.of(context).spacer4, + horizontal: TDTheme.of(context).spacer16), + margin: capsuleTheme + ? EdgeInsets.symmetric( + horizontal: TDTheme.of(context).spacer8) + : null, decoration: BoxDecoration( - color: isPinned ? TDTheme.of(context).whiteColor1 : TDTheme.of(context).grayColor1, - borderRadius: capsuleTheme ? BorderRadius.circular(TDTheme.of(context).radiusCircle) : null, + color: isPinned + ? TDTheme.of(context).bgColorContainer + : TDTheme.of(context).bgColorSecondaryContainer, + borderRadius: capsuleTheme + ? BorderRadius.circular(TDTheme.of(context).radiusCircle) + : null, border: isPinned ? capsuleTheme - ? Border.all(color: TDTheme.of(context).grayColor1) - : Border(bottom: BorderSide(color: TDTheme.of(context).grayColor1)) + ? Border.all( + color: TDTheme.of(context).componentStrokeColor) + : Border( + bottom: BorderSide( + color: TDTheme.of(context).componentStrokeColor, + width: 0.5)) : null, ), child: TDText( text, forceVerticalCenter: true, - font: isPinned ? TDTheme.of(context).fontMarkMedium : TDTheme.of(context).fontTitleSmall, - textColor: isPinned ? TDTheme.of(context).brandColor7 : TDTheme.of(context).fontGyColor1, + font: isPinned + ? TDTheme.of(context).fontMarkMedium + : TDTheme.of(context).fontTitleSmall, + textColor: isPinned + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).textColorPrimary, ), ); }, diff --git a/tdesign-component/lib/src/components/indexes/td_indexes_list.dart b/tdesign-component/lib/src/components/indexes/td_indexes_list.dart index eeca75acc..7f6b27385 100644 --- a/tdesign-component/lib/src/components/indexes/td_indexes_list.dart +++ b/tdesign-component/lib/src/components/indexes/td_indexes_list.dart @@ -33,7 +33,8 @@ class TDIndexesList extends StatefulWidget { final void Function(String newIndex, String oldIndex) onSelect; /// 索引文本自定义构建,包括索引激活左侧提示 - final Widget Function(BuildContext context, String index, bool isActive)? builderIndex; + final Widget Function(BuildContext context, String index, bool isActive)? + builderIndex; @override State createState() => _TDIndexesListState(); @@ -48,14 +49,19 @@ class _TDIndexesListState extends State { @override void initState() { super.initState(); - _containerKeys = widget.indexList.asMap().map((index, e) => MapEntry(e, GlobalKey())); + _initContainerKeys(); + } + + void _initContainerKeys() { + _containerKeys = + widget.indexList.asMap().map((index, e) => MapEntry(e, GlobalKey())); } @override void didUpdateWidget(TDIndexesList oldWidget) { super.didUpdateWidget(oldWidget); if (widget.indexList != oldWidget.indexList) { - _containerKeys = widget.indexList.asMap().map((index, e) => MapEntry(e, GlobalKey())); + _initContainerKeys(); } } @@ -96,52 +102,64 @@ class _TDIndexesListState extends State { (e) { final isActive = value == e; if (widget.builderIndex != null) { - return Container(key: _containerKeys[e], child: widget.builderIndex!(context, e, isActive),); + return Container( + key: _containerKeys[e], + child: widget.builderIndex!(context, e, isActive), + ); } return Stack( clipBehavior: Clip.none, children: [ if (_showTip && value == e) Positioned( - top: -TDTheme.of(context).spacer48 / 2 + _indexSize / 2, + top: -TDTheme.of(context).spacer48 / 2 + + _indexSize / 2, left: -TDTheme.of(context).spacer48, child: Container( height: TDTheme.of(context).spacer48, width: TDTheme.of(context).spacer48, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusCircle), - color: TDTheme.of(context).brandColor1, + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusCircle), + color: TDTheme.of(context).brandLightColor, ), child: Center( child: TDText( e, forceVerticalCenter: true, - font: TDTheme.of(context).fontTitleExtraLarge, - textColor: TDTheme.of(context).brandColor7, + font: TDTheme.of(context) + .fontTitleExtraLarge, + textColor: + TDTheme.of(context).brandNormalColor, ), ), ), ), Container( key: _containerKeys[e], - padding: EdgeInsets.only(left: TDTheme.of(context).spacer8), - color: Colors.transparent, + padding: EdgeInsets.only( + left: TDTheme.of(context).spacer8), child: Container( width: _indexSize, height: _indexSize, decoration: isActive ? BoxDecoration( - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusCircle), - color: TDTheme.of(context).brandColor7, + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusCircle), + color: TDTheme.of(context) + .brandNormalColor, ) : null, child: Center( child: TDText( e, forceVerticalCenter: true, - font: isActive ? TDTheme.of(context).fontMarkSmall : TDTheme.of(context).fontLinkSmall, - textColor: - isActive ? TDTheme.of(context).fontWhColor1 : TDTheme.of(context).fontGyColor1, + font: isActive + ? TDTheme.of(context).fontMarkSmall + : TDTheme.of(context).fontLinkSmall, + textColor: isActive + ? TDTheme.of(context).textColorAnti + : TDTheme.of(context).textColorPrimary, ), ), ), @@ -172,10 +190,12 @@ class _TDIndexesListState extends State { String? _fingerInsideContainer(Offset globalPosition) { for (var entry in _containerKeys.entries) { - final renderBox = entry.value.currentContext?.findRenderObject() as RenderBox?; + final renderBox = + entry.value.currentContext?.findRenderObject() as RenderBox?; if (renderBox != null) { final localPosition = renderBox.globalToLocal(globalPosition); - final isIn = renderBox.hitTest(BoxHitTestResult(), position: localPosition); + final isIn = + renderBox.hitTest(BoxHitTestResult(), position: localPosition); if (isIn) { return entry.key; } diff --git a/tdesign-component/lib/src/components/input/td_input.dart b/tdesign-component/lib/src/components/input/td_input.dart index bfb88f9ed..ec4ed5418 100644 --- a/tdesign-component/lib/src/components/input/td_input.dart +++ b/tdesign-component/lib/src/components/input/td_input.dart @@ -4,7 +4,14 @@ import 'package:flutter/services.dart'; import '../../../tdesign_flutter.dart'; import '../dialog/td_dialog_widget.dart'; -enum TDInputType { normal, twoLine, longText, special, normalMaxTwoLine, cardStyle } +enum TDInputType { + normal, + twoLine, + longText, + special, + normalMaxTwoLine, + cardStyle +} enum TDInputSize { small, large } @@ -240,7 +247,7 @@ class TDInput extends StatelessWidget { final iconWidth = leftIcon != null ? 24 + iconSpace : 0; final labelWidth = _measureTextWidth(leftLabel, leftLabelStyle, context); final requiredWidth = (required ?? false) ? 14 : 0; - return iconWidth + labelWidth + requiredWidth + (leftContentSpace??4); + return iconWidth + labelWidth + requiredWidth + (leftContentSpace ?? 4); } /// 计算文本渲染宽度 @@ -248,9 +255,12 @@ class TDInput extends StatelessWidget { /// style: 文本样式(继承主题字体尺寸) /// 排版控制:letterSpacing=0消除字间距,height=1.0避免行高影响 /// 默认最大行数排版为1行 - double _measureTextWidth(String? text, TextStyle? style, BuildContext context) { - if (text == null || text.isEmpty) return 0; - final effectiveStyle = (style ?? TextStyle()).copyWith( + double _measureTextWidth( + String? text, TextStyle? style, BuildContext context) { + if (text == null || text.isEmpty) { + return 0; + } + final effectiveStyle = (style ?? const TextStyle()).copyWith( fontSize: TDTheme.of(context).fontBodyLarge?.size, letterSpacing: 0, height: 1.0, @@ -302,16 +312,21 @@ class TDInput extends StatelessWidget { Widget buildNormalInput(BuildContext context) { var cardStyleDecoration = _getCardStylePreDecoration(context); - var hasLeftWidget = leftLabel != null || leftIcon != null || (required ?? false); + var hasLeftWidget = + leftLabel != null || leftIcon != null || (required ?? false); return Stack( alignment: Alignment.bottomCenter, children: [ Container( alignment: Alignment.centerLeft, - color: (cardStyleDecoration != null || decoration != null) ? null : backgroundColor, + color: (cardStyleDecoration != null || decoration != null) + ? null + : (backgroundColor ?? TDTheme.of(context).bgColorContainer), decoration: cardStyleDecoration ?? decoration, child: Row( - crossAxisAlignment: additionInfo != '' ? CrossAxisAlignment.start : CrossAxisAlignment.center, + crossAxisAlignment: additionInfo != '' + ? CrossAxisAlignment.start + : CrossAxisAlignment.center, children: [ Visibility( visible: hasLeftWidget, @@ -334,16 +349,20 @@ class TDInput extends StatelessWidget { Visibility( visible: leftLabel != null, child: Container( - constraints: BoxConstraints(maxWidth: _leftLabelWidth), + constraints: + BoxConstraints(maxWidth: _leftLabelWidth), padding: EdgeInsets.only( - left: leftIcon != null ? (spacer.iconLabelSpace ?? 4) : 0, + left: leftIcon != null + ? (spacer.iconLabelSpace ?? 4) + : 0, top: getInputPadding(), bottom: getInputPadding()), child: TDText( leftLabel, maxLines: 1, overflow: TextOverflow.visible, - style: leftLabelStyle ?? const TextStyle(letterSpacing: 0), + style: leftLabelStyle ?? + const TextStyle(letterSpacing: 0), font: TDTheme.of(context).fontBodyLarge, fontWeight: FontWeight.w400, ), @@ -360,7 +379,8 @@ class TDInput extends StatelessWidget { child: TDText( '*', maxLines: 1, - style: TextStyle(color: TDTheme.of(context).errorColor6), + style: TextStyle( + color: TDTheme.of(context).errorColor6), font: TDTheme.of(context).fontBodyLarge, fontWeight: FontWeight.w400, ), @@ -375,7 +395,9 @@ class TDInput extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ TDInputView( - textStyle: textStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor1), + textStyle: textStyle ?? + TextStyle( + color: TDTheme.of(context).textColorPrimary), readOnly: readOnly, autofocus: autofocus, obscureText: obscureText, @@ -392,15 +414,20 @@ class TDInput extends StatelessWidget { focusNode: focusNode, isCollapsed: true, textAlign: contentAlignment, - hintTextStyle: hintTextStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor3), + hintTextStyle: hintTextStyle ?? + TextStyle( + color: TDTheme.of(context).textColorPlaceholder), cursorColor: cursorColor, textInputBackgroundColor: textInputBackgroundColor, controller: controller, contentPadding: contentPadding ?? EdgeInsets.only( left: spacer.labelInputSpace ?? 16, - right: spacer.inputRightSpace != null ? spacer.inputRightSpace! / 2 : 16, - bottom: additionInfo != '' ? 4 : getInputPadding(), + right: spacer.inputRightSpace != null + ? spacer.inputRightSpace! / 2 + : 16, + bottom: + additionInfo != '' ? 4 : getInputPadding(), top: getInputPadding()), inputAction: inputAction, ), @@ -414,8 +441,11 @@ class TDInput extends StatelessWidget { child: TDText( additionInfo, font: TDTheme.of(context).fontBodySmall, - textAlign: contentAlignment != TextAlign.center ? contentAlignment : TextAlign.start, - textColor: additionInfoColor ?? TDTheme.of(context).fontGyColor3, + textAlign: contentAlignment != TextAlign.center + ? contentAlignment + : TextAlign.start, + textColor: additionInfoColor ?? + TDTheme.of(context).textColorPlaceholder, ), ), visible: additionInfo != '', @@ -426,22 +456,31 @@ class TDInput extends StatelessWidget { Visibility( visible: rightWidget != null, child: Container( - margin: EdgeInsets.only(top: getInputPadding(), bottom: getInputPadding(), right: 16), + margin: EdgeInsets.only( + top: getInputPadding(), + bottom: getInputPadding(), + right: 16), child: rightWidget, ), ), Visibility( - visible: controller != null && controller!.text.isNotEmpty && needClear && rightWidget == null, + visible: controller != null && + controller!.text.isNotEmpty && + needClear && + rightWidget == null, child: GestureDetector( child: Container( margin: EdgeInsets.only( - left: spacer.inputRightSpace != null ? spacer.inputRightSpace! / 2 : 8, + left: spacer.inputRightSpace != null + ? spacer.inputRightSpace! / 2 + : 8, right: spacer.rightSpace ?? 16, top: additionInfo != '' ? getInputPadding() : 0), child: Icon( size: clearIconSize, TDIcons.close_circle_filled, - color: clearBtnColor ?? TDTheme.of(context).fontGyColor3, + color: clearBtnColor ?? + TDTheme.of(context).textColorPlaceholder, ), ), onTap: onClearTap ?? @@ -454,7 +493,9 @@ class TDInput extends StatelessWidget { onTap: onBtnTap, child: Container( margin: EdgeInsets.only( - left: spacer.inputRightSpace != null ? spacer.inputRightSpace! / 2 : 8, + left: spacer.inputRightSpace != null + ? spacer.inputRightSpace! / 2 + : 8, right: spacer.rightSpace ?? 16, top: additionInfo != '' ? getInputPadding() : 0), child: rightBtn, @@ -484,24 +525,33 @@ class TDInput extends StatelessWidget { switch (cardStyle) { case TDCardStyle.topText: cardStyleDecoration = BoxDecoration( - color: Colors.white, - border: Border.all(color: TDTheme.of(context).grayColor4), - borderRadius: BorderRadius.circular(6)); + color: TDTheme.of(context).bgColorContainer, + border: + Border.all(color: TDTheme.of(context).componentStrokeColor), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)); break; case TDCardStyle.topTextWithBlueBorder: cardStyleDecoration = BoxDecoration( - color: Colors.white, - border: Border.all(color: TDTheme.of(context).brandNormalColor, width: 1.5), - borderRadius: BorderRadius.circular(6)); + color: TDTheme.of(context).bgColorContainer, + border: Border.all( + color: TDTheme.of(context).brandNormalColor, width: 1.5), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)); break; case TDCardStyle.errorStyle: cardStyleDecoration = BoxDecoration( - color: Colors.white, - border: Border.all(color: TDTheme.of(context).errorColor6, width: 1.5), - borderRadius: BorderRadius.circular(6)); + color: TDTheme.of(context).bgColorContainer, + border: Border.all( + color: TDTheme.of(context).errorColor6, width: 1.5), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)); break; default: - cardStyleDecoration = BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(6)); + cardStyleDecoration = BoxDecoration( + color: TDTheme.of(context).bgColorContainer, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)); break; } } @@ -511,7 +561,9 @@ class TDInput extends StatelessWidget { Widget buildTwoLineInput(BuildContext context) { return Container( alignment: Alignment.centerLeft, - color: decoration != null ? null : backgroundColor, + color: decoration != null + ? null + : (backgroundColor ?? TDTheme.of(context).bgColorContainer), decoration: decoration, child: Stack( alignment: Alignment.bottomCenter, @@ -526,14 +578,18 @@ class TDInput extends StatelessWidget { Visibility( visible: leftLabel != null, child: Container( - constraints: BoxConstraints(maxWidth: _leftLabelWidth + (leftLabelSpace ?? 12)), - padding: EdgeInsets.only(left: leftLabelSpace ?? 12.0, top: 10.0), + constraints: BoxConstraints( + maxWidth: + _leftLabelWidth + (leftLabelSpace ?? 12)), + padding: EdgeInsets.only( + left: leftLabelSpace ?? 12.0, top: 10.0), child: Column( children: [ TDText( leftLabel, maxLines: 2, - style: leftLabelStyle ?? const TextStyle(letterSpacing: 0), + style: leftLabelStyle ?? + const TextStyle(letterSpacing: 0), font: TDTheme.of(context).fontBodyLarge, fontWeight: FontWeight.w400, ), @@ -552,7 +608,8 @@ class TDInput extends StatelessWidget { child: TDText( '*', maxLines: 1, - style: TextStyle(color: TDTheme.of(context).errorColor6), + style: TextStyle( + color: TDTheme.of(context).errorColor6), font: TDTheme.of(context).fontBodyLarge, fontWeight: FontWeight.w400, ), @@ -573,7 +630,9 @@ class TDInput extends StatelessWidget { Expanded( flex: 1, child: TDInputView( - textStyle: textStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor1), + textStyle: textStyle ?? + TextStyle( + color: TDTheme.of(context).textColorPrimary), readOnly: readOnly, autofocus: autofocus, obscureText: obscureText, @@ -588,30 +647,40 @@ class TDInput extends StatelessWidget { isCollapsed: true, maxLines: maxLines, focusNode: focusNode, - hintTextStyle: hintTextStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor3), + hintTextStyle: hintTextStyle ?? + TextStyle( + color: + TDTheme.of(context).textColorPlaceholder), cursorColor: cursorColor, textInputBackgroundColor: textInputBackgroundColor, controller: controller, contentPadding: contentPadding ?? EdgeInsets.only( left: spacer.labelInputSpace ?? 16, - right: spacer.inputRightSpace != null ? spacer.inputRightSpace! / 2 : 8, + right: spacer.inputRightSpace != null + ? spacer.inputRightSpace! / 2 + : 8, ), inputAction: inputAction, ), ), Visibility( - visible: controller != null && controller!.text.isNotEmpty && needClear, + visible: controller != null && + controller!.text.isNotEmpty && + needClear, child: GestureDetector( child: Container( margin: EdgeInsets.only( - left: spacer.inputRightSpace != null ? spacer.inputRightSpace! / 2 : 8, + left: spacer.inputRightSpace != null + ? spacer.inputRightSpace! / 2 + : 8, right: spacer.rightSpace ?? 16, ), child: Icon( size: clearIconSize, TDIcons.close_circle_filled, - color: clearBtnColor ?? TDTheme.of(context).fontGyColor3, + color: clearBtnColor ?? + TDTheme.of(context).textColorPlaceholder, ), ), onTap: onClearTap, @@ -622,7 +691,9 @@ class TDInput extends StatelessWidget { onTap: onBtnTap, child: Container( margin: EdgeInsets.only( - left: spacer.inputRightSpace != null ? spacer.inputRightSpace! / 2 : 8, + left: spacer.inputRightSpace != null + ? spacer.inputRightSpace! / 2 + : 8, right: spacer.rightSpace ?? 16, ), child: rightBtn, @@ -649,7 +720,9 @@ class TDInput extends StatelessWidget { Widget buildLongTextInput(BuildContext context) { return Container( alignment: Alignment.centerLeft, - color: decoration != null ? null : backgroundColor, + color: decoration != null + ? null + : (backgroundColor ?? TDTheme.of(context).bgColorContainer), decoration: decoration, height: leftLabel != null ? 197 : 148, child: Column( @@ -661,7 +734,10 @@ class TDInput extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: EdgeInsets.only(left: 16, top: getInputPadding(), bottom: getInputPadding()), + padding: EdgeInsets.only( + left: 16, + top: getInputPadding(), + bottom: getInputPadding()), child: TDText( leftLabel, maxLines: 2, @@ -679,7 +755,8 @@ class TDInput extends StatelessWidget { Expanded( flex: 1, child: TDInputView( - textStyle: textStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor1), + textStyle: textStyle ?? + TextStyle(color: TDTheme.of(context).textColorPrimary), readOnly: readOnly, autofocus: autofocus, obscureText: obscureText, @@ -689,15 +766,19 @@ class TDInput extends StatelessWidget { inputType: inputType, textAlign: textAlign, onChanged: onChanged, - inputFormatters: inputFormatters ?? [LengthLimitingTextInputFormatter(maxLength)], + inputFormatters: inputFormatters ?? + [LengthLimitingTextInputFormatter(maxLength)], inputDecoration: inputDecoration, maxLines: maxLines, focusNode: focusNode, - hintTextStyle: hintTextStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor3), + hintTextStyle: hintTextStyle ?? + TextStyle(color: TDTheme.of(context).textColorPlaceholder), cursorColor: cursorColor, textInputBackgroundColor: textInputBackgroundColor, controller: controller, - contentPadding: contentPadding ?? const EdgeInsets.only(left: 16, right: 16, top: 12, bottom: 12), + contentPadding: contentPadding ?? + const EdgeInsets.only( + left: 16, right: 16, top: 12, bottom: 12), inputAction: inputAction, ), ), @@ -707,7 +788,7 @@ class TDInput extends StatelessWidget { child: TDText( '${controller?.text.length}/${maxLength}', font: TDTheme.of(context).fontBodySmall, - textColor: TDTheme.of(context).fontGyColor3, + textColor: TDTheme.of(context).textColorPlaceholder, ), ), ], @@ -721,7 +802,9 @@ class TDInput extends StatelessWidget { children: [ Container( alignment: Alignment.centerLeft, - color: decoration != null ? null : backgroundColor, + color: decoration != null + ? null + : (backgroundColor ?? TDTheme.of(context).bgColorContainer), decoration: decoration, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -729,8 +812,10 @@ class TDInput extends StatelessWidget { Visibility( visible: leftLabel != null, child: Padding( - padding: - EdgeInsets.only(left: leftLabelSpace ?? 16, top: getInputPadding(), bottom: getInputPadding()), + padding: EdgeInsets.only( + left: leftLabelSpace ?? 16, + top: getInputPadding(), + bottom: getInputPadding()), child: leftInfoWidth != null ? SizedBox( width: _leftLabelWidth, @@ -758,7 +843,8 @@ class TDInput extends StatelessWidget { child: Padding( padding: EdgeInsets.only(left: spacer.labelInputSpace!), child: TDInputView( - textStyle: textStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor1), + textStyle: textStyle ?? + TextStyle(color: TDTheme.of(context).textColorPrimary), readOnly: readOnly, autofocus: autofocus, obscureText: obscureText, @@ -772,14 +858,18 @@ class TDInput extends StatelessWidget { maxLines: maxLines, focusNode: focusNode, isCollapsed: true, - hintTextStyle: hintTextStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor3), + hintTextStyle: hintTextStyle ?? + TextStyle( + color: TDTheme.of(context).textColorPlaceholder), cursorColor: cursorColor, textInputBackgroundColor: textInputBackgroundColor, controller: controller, textAlign: textAlign, contentPadding: contentPadding ?? EdgeInsets.only( - right: spacer.inputRightSpace!, bottom: getInputPadding(), top: getInputPadding()), + right: spacer.inputRightSpace!, + bottom: getInputPadding(), + top: getInputPadding()), inputAction: inputAction, ), ), @@ -787,7 +877,10 @@ class TDInput extends StatelessWidget { Visibility( visible: rightWidget != null, child: Container( - margin: EdgeInsets.only(top: getInputPadding(), bottom: getInputPadding(), right: spacer.rightSpace!), + margin: EdgeInsets.only( + top: getInputPadding(), + bottom: getInputPadding(), + right: spacer.rightSpace!), child: rightWidget, ), ), @@ -878,7 +971,8 @@ class Chinese2Formatter extends TextInputFormatter { final _regExp = r'^[\u4E00-\u9FA5A-Za-z0-9_]+$'; @override - TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, TextEditingValue newValue) { var newValueLength = newValue.text.length; var count = 0; if (newValueLength == 0) { @@ -895,11 +989,13 @@ class Chinese2Formatter extends TextInputFormatter { return newValue.copyWith( text: text, composing: TextRange.empty, - selection: TextSelection.fromPosition(TextPosition(offset: i, affinity: TextAffinity.downstream))); + selection: TextSelection.fromPosition( + TextPosition(offset: i, affinity: TextAffinity.downstream))); } } } - if (newValueLength > 0 && RegExp(_regExp).firstMatch(newValue.text) != null) { + if (newValueLength > 0 && + RegExp(_regExp).firstMatch(newValue.text) != null) { if (newValueLength + count <= maxLength) { return newValue; } diff --git a/tdesign-component/lib/src/components/link/td_link.dart b/tdesign-component/lib/src/components/link/td_link.dart index 7f967fb26..4ec8659bc 100644 --- a/tdesign-component/lib/src/components/link/td_link.dart +++ b/tdesign-component/lib/src/components/link/td_link.dart @@ -96,27 +96,33 @@ class TDLink extends StatelessWidget { @override Widget build(BuildContext context) { if (type == TDLinkType.withPrefixIcon) { - return Row(children: [ - prefixIcon == null ? _getDefaultIcon(context) : prefixIcon!, - SizedBox( - width: _getLeftGapSize(context), - ), - _buildLink(context), - ]); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + prefixIcon == null ? _getDefaultIcon(context) : prefixIcon!, + SizedBox( + width: _getLeftGapSize(context), + ), + _buildLink(context), + ], + ); } else if (type == TDLinkType.withSuffixIcon) { - return Row(children: [ - _buildLink(context), - SizedBox( - width: _getRightGapSize(context), - ), - suffixIcon == null ? _getDefaultIcon(context) : suffixIcon!, - ]); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildLink(context), + SizedBox( + width: _getRightGapSize(context), + ), + suffixIcon == null ? _getDefaultIcon(context) : suffixIcon!, + ], + ); } return _buildLink(context); } - /// 提取成方法,允许业务定义自己的TDLinkConfiguration + /// 提取成方法,允许业务定义自己的 TDLinkConfiguration TDLinkConfiguration? getConfiguration(BuildContext context) { return context.dependOnInheritedWidgetOfExactType(); } @@ -125,49 +131,33 @@ class TDLink extends StatelessWidget { if (color != null) { return color!; } - // to refactor: use map instead of multi level switch - switch (state) { - case TDLinkState.normal: - switch (style) { - case TDLinkStyle.primary: - return TDTheme.of(context).brandNormalColor; - case TDLinkStyle.danger: - return TDTheme.of(context).errorColor6; - case TDLinkStyle.warning: - return TDTheme.of(context).warningColor5; - case TDLinkStyle.success: - return TDTheme.of(context).successColor5; - case TDLinkStyle.defaultStyle: - return TDTheme.of(context).fontGyColor1; - } - - case TDLinkState.active: - switch (style) { - case TDLinkStyle.primary: - return TDTheme.of(context).brandClickColor; - case TDLinkStyle.danger: - return TDTheme.of(context).errorColor7; - case TDLinkStyle.warning: - return TDTheme.of(context).warningColor6; - case TDLinkStyle.success: - return TDTheme.of(context).successColor6; - case TDLinkStyle.defaultStyle: - return TDTheme.of(context).brandClickColor; - } - case TDLinkState.disabled: - switch (style) { - case TDLinkStyle.primary: - return TDTheme.of(context).brandDisabledColor; - case TDLinkStyle.danger: - return TDTheme.of(context).errorDisabledColor; - case TDLinkStyle.warning: - return TDTheme.of(context).warningDisabledColor; - case TDLinkStyle.success: - return TDTheme.of(context).successDisabledColor; - case TDLinkStyle.defaultStyle: - return TDTheme.of(context).fontGyColor4; - } - } + + final theme = TDTheme.of(context); + final colorMap = >{ + TDLinkState.normal: { + TDLinkStyle.primary: theme.brandNormalColor, + TDLinkStyle.danger: theme.errorNormalColor, + TDLinkStyle.warning: theme.warningNormalColor, + TDLinkStyle.success: theme.successNormalColor, + TDLinkStyle.defaultStyle: theme.textColorPrimary, + }, + TDLinkState.active: { + TDLinkStyle.primary: theme.brandClickColor, + TDLinkStyle.danger: theme.errorClickColor, + TDLinkStyle.warning: theme.warningClickColor, + TDLinkStyle.success: theme.successClickColor, + TDLinkStyle.defaultStyle: theme.brandClickColor, + }, + TDLinkState.disabled: { + TDLinkStyle.primary: theme.brandDisabledColor, + TDLinkStyle.danger: theme.errorDisabledColor, + TDLinkStyle.warning: theme.warningDisabledColor, + TDLinkStyle.success: theme.successDisabledColor, + TDLinkStyle.defaultStyle: theme.textColorDisabled, + }, + }; + + return colorMap[state]?[style] ?? theme.textColorPrimary; } Widget _getDefaultIcon(BuildContext context) { @@ -242,7 +232,7 @@ class TDLink extends StatelessWidget { } switch (size) { case TDLinkSize.large: - return 14.64; + return 8; case TDLinkSize.small: return 6.05; case TDLinkSize.medium: @@ -256,7 +246,7 @@ class TDLink extends StatelessWidget { } switch (size) { case TDLinkSize.large: - return 15.37; + return 8; case TDLinkSize.small: return 6.63; case TDLinkSize.medium: diff --git a/tdesign-component/lib/src/components/loading/td_activity_indicator.dart b/tdesign-component/lib/src/components/loading/td_activity_indicator.dart index ac2356f1b..34ef3d342 100644 --- a/tdesign-component/lib/src/components/loading/td_activity_indicator.dart +++ b/tdesign-component/lib/src/components/loading/td_activity_indicator.dart @@ -6,6 +6,8 @@ import '../../../tdesign_flutter.dart'; const double _kDefaultIndicatorRadius = 10.0; +/// todo 建议使用 CupertinoActivityIndicator +/// /// An iOS-style activity indicator that spins clockwise. /// /// {@youtube 560 315 https://www.youtube.com/watch?v=AENVH-ZqKDQ} @@ -97,7 +99,7 @@ class _TDCupertinoActivityIndicatorState child: CustomPaint( painter: _CupertinoActivityIndicatorPainter( position: _controller, - activeColor: widget.activeColor ?? const Color(0xB4807E7E), + activeColor: widget.activeColor ?? TDTheme.of(context).textColorPlaceholder, radius: widget.radius, progress: widget.progress, ), diff --git a/tdesign-component/lib/src/components/loading/td_loading.dart b/tdesign-component/lib/src/components/loading/td_loading.dart index 5c8c5c098..659607ffc 100644 --- a/tdesign-component/lib/src/components/loading/td_loading.dart +++ b/tdesign-component/lib/src/components/loading/td_loading.dart @@ -12,15 +12,25 @@ import 'td_point_indicator.dart'; /// Loading 尺寸 enum TDLoadingSize { + /// 小尺寸 small, + + /// 中尺寸 medium, + + /// 大尺寸 large, } -/// Loading的图标 +/// Loading图标 enum TDLoadingIcon { + /// 圆形 circle, + + /// 点状 point, + + /// 菊花状 activity, } @@ -34,26 +44,34 @@ class TDLoading extends StatelessWidget { this.text, this.refreshWidget, this.customIcon, - this.textColor = Colors.black, + this.textColor, this.duration = 2000, }) : super(key: key); /// 尺寸 final TDLoadingSize size; + /// 图标,支持圆形、点状、菊花状 final TDLoadingIcon? icon; + /// 图标颜色 final Color? iconColor; + /// 文案 final String? text; + /// 失败刷新组件 final Widget? refreshWidget; + /// 文案颜色 - final Color textColor; + final Color? textColor; + /// 文案和图标相对方向 final Axis axis; + /// 自定义图标,优先级高于icon final Widget? customIcon; + /// 一次刷新的时间,控制动画速度 final int duration; @@ -62,13 +80,13 @@ class TDLoading extends StatelessWidget { @override Widget build(BuildContext context) { return Wrap( - children: [_contentWidget()], + children: [_contentWidget(context)], ); } - Widget _contentWidget() { + Widget _contentWidget(BuildContext context) { if (icon == null) { - return textWidget(); + return textWidget(context); } else { Widget? indicator; if (customIcon != null) { @@ -104,27 +122,20 @@ class TDLoading extends StatelessWidget { if (text == null) { return indicator; - } else if (axis == Axis.vertical) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - indicator, - SizedBox( - height: _getPaddingWidth(), - ), - textWidget(), - ]); - } else { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - indicator, - SizedBox( - width: _getPaddingWidth(), - ), - textWidget() - ]); } + + return Flex( + // spacing: _getPaddingSize(), + mainAxisSize: MainAxisSize.min, + direction: axis, + children: [ + indicator, + axis == Axis.vertical + ? SizedBox(height: _getPaddingSize()) + : SizedBox(width: _getPaddingSize()), + textWidget(context), + ], + ); } } @@ -147,14 +158,14 @@ class TDLoading extends StatelessWidget { case TDLoadingSize.small: return TDCircleIndicator( color: iconColor, - size: 18, // 设计稿框位24,图形宽位19.5,推导lineWidth为3时,size位18 + size: 18, // 设计稿框为24,图形宽为19.5,推导lineWidth为3时,size为18 lineWidth: 3, duration: _innerDuration, ); } } - double _getPaddingWidth() { + double _getPaddingSize() { switch (size) { case TDLoadingSize.large: return 10; @@ -165,31 +176,30 @@ class TDLoading extends StatelessWidget { } } - Font fitFont() { - switch (size) { - case TDLoadingSize.large: - return TDTheme.of().fontBodyLarge ?? Font(size: 16, lineHeight: 24); - case TDLoadingSize.medium: - return TDTheme.of().fontBodyMedium ?? Font(size: 14, lineHeight: 22); - case TDLoadingSize.small: - return TDTheme.of().fontBodySmall ?? Font(size: 12, lineHeight: 20); - } - } + Widget textWidget(BuildContext context) { + final font = switch (size) { + TDLoadingSize.large => + TDTheme.of(context).fontBodyLarge ?? Font(size: 16, lineHeight: 24), + TDLoadingSize.medium => + TDTheme.of(context).fontBodyMedium ?? Font(size: 14, lineHeight: 22), + TDLoadingSize.small => + TDTheme.of(context).fontBodySmall ?? Font(size: 12, lineHeight: 20), + }; - Widget textWidget() { - Widget result = TDText( + Widget result = TDText( text, - textColor: textColor, + textColor: textColor ?? TDTheme.of(context).textColorPrimary, fontWeight: FontWeight.w400, - font: fitFont(), + font: font, textAlign: TextAlign.center, ); - if(refreshWidget != null){ + if (refreshWidget != null) { result = Row( + // spacing: 8, mainAxisSize: MainAxisSize.min, children: [ result, - const SizedBox(width: 8,), + const SizedBox(width: 8), refreshWidget!, ], ); diff --git a/tdesign-component/lib/src/components/loading/td_loading_controller.dart b/tdesign-component/lib/src/components/loading/td_loading_controller.dart index 1a0c79e41..fedf83324 100644 --- a/tdesign-component/lib/src/components/loading/td_loading_controller.dart +++ b/tdesign-component/lib/src/components/loading/td_loading_controller.dart @@ -16,11 +16,10 @@ class TDLoadingController { Color? iconColor, String? text, Widget? refreshWidget, - Color textColor = Colors.black, + Color? textColor, Axis axis = Axis.vertical, Widget? customIcon, int duration = 2000}) { - if (_isShowing) { print('warn: TDLoading is showing!'); return; @@ -55,10 +54,10 @@ class TDLoadingController { // 消失 static void dismiss() { if (_isShowing) { - if (_overlayEntry != null) { - _overlayEntry?.remove(); - _overlayEntry = null; - } + if (_overlayEntry != null) { + _overlayEntry?.remove(); + _overlayEntry = null; + } _isShowing = false; } } diff --git a/tdesign-component/lib/src/components/message/td_message.dart b/tdesign-component/lib/src/components/message/td_message.dart index 7416188a1..a782252fe 100644 --- a/tdesign-component/lib/src/components/message/td_message.dart +++ b/tdesign-component/lib/src/components/message/td_message.dart @@ -3,7 +3,7 @@ import 'package:flutter/src/scheduler/binding.dart'; import '../../../tdesign_flutter.dart'; -//链接设置 +/// 链接设置 class MessageLink { MessageLink({ required this.name, @@ -21,7 +21,7 @@ class MessageLink { final Color? color; } -// 跑马灯配置 +/// 跑马灯配置 class MessageMarquee { MessageMarquee({this.speed, this.loop, this.delay}); @@ -35,7 +35,7 @@ class MessageMarquee { final int? delay; } -// 定义消息主题枚举 +/// 定义消息主题枚举 enum MessageTheme { /// 普通通知 info, @@ -50,7 +50,7 @@ enum MessageTheme { error } -// TDMessage 组件 +/// TDMessage 组件 class TDMessage extends StatefulWidget { const TDMessage({ Key? key, @@ -236,7 +236,7 @@ class _TDMessageState extends State with TickerProviderStateMixin { alignment: Alignment.centerLeft, child: Text( widget.content ?? '', - style: const TextStyle(color: Colors.black), + style: TextStyle(color: TDTheme.of(context).textColorPrimary), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -245,7 +245,7 @@ class _TDMessageState extends State with TickerProviderStateMixin { final textPainter = TextPainter( text: TextSpan( text: widget.content ?? '', - style: const TextStyle(color: Colors.black)), + style: TextStyle(color: TDTheme.of(context).textColorPrimary)), maxLines: 1, textDirection: TextDirection.ltr, )..layout(minWidth: 0, maxWidth: double.infinity); @@ -289,7 +289,8 @@ class _TDMessageState extends State with TickerProviderStateMixin { child: SizedBox( child: Text( widget.content ?? '', - style: const TextStyle(color: Colors.black), + style: TextStyle( + color: TDTheme.of(context).textColorPrimary), maxLines: 1, ), ), @@ -308,17 +309,25 @@ class _TDMessageState extends State with TickerProviderStateMixin { } else { switch (widget.theme) { case MessageTheme.info: - return Icon(TDIcons.error_circle_filled, - color: TDTheme.of(context).brandColor7); + return Icon( + TDIcons.error_circle_filled, + color: TDTheme.of(context).brandNormalColor, + ); case MessageTheme.success: - return Icon(TDIcons.check_circle_filled, - color: TDTheme.of(context).successColor5); + return Icon( + TDIcons.check_circle_filled, + color: TDTheme.of(context).successNormalColor, + ); case MessageTheme.warning: - return Icon(TDIcons.error_circle_filled, - color: TDTheme.of(context).warningColor5); + return Icon( + TDIcons.error_circle_filled, + color: TDTheme.of(context).warningNormalColor, + ); case MessageTheme.error: - return Icon(TDIcons.error_circle_filled, - color: TDTheme.of(context).errorColor6); + return Icon( + TDIcons.error_circle_filled, + color: TDTheme.of(context).errorNormalColor, + ); case null: return const SizedBox.shrink(); } @@ -339,9 +348,9 @@ class _TDMessageState extends State with TickerProviderStateMixin { } else if (widget.closeBtn == true) { return GestureDetector( onTap: clickCloseButton, - child: const Icon( + child: Icon( TDIcons.close, - color: Color.fromRGBO(0, 0, 0, 0.4), + color: TDTheme.of(context).textColorPlaceholder, ), ); } else if (widget.closeBtn is String) { @@ -366,9 +375,9 @@ class _TDMessageState extends State with TickerProviderStateMixin { label: widget.link.name, style: TDLinkStyle.primary, type: TDLinkType.basic, - uri: widget.link.uri ?? Uri.parse('https://example.com'), + uri: widget.link.uri, size: TDLinkSize.medium, - color: widget.link.color ?? TDTheme.of(context).brandColor7, + color: widget.link.color ?? TDTheme.of(context).brandNormalColor, linkClick: (link) => clickLink(), )); } else if (widget.link is String) { @@ -379,7 +388,7 @@ class _TDMessageState extends State with TickerProviderStateMixin { child: Text( widget.link ?? '', style: TextStyle( - color: TDTheme.of(context).brandColor7, + color: TDTheme.of(context).brandNormalColor, fontSize: 14, ), maxLines: 1, @@ -404,8 +413,9 @@ class _TDMessageState extends State with TickerProviderStateMixin { height: 48, padding: const EdgeInsets.fromLTRB(16, 13, 16, 13), decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(6), + color: TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusDefault), boxShadow: TDTheme.of(context).shadowsMiddle), child: Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -437,15 +447,12 @@ class _TDMessageState extends State with TickerProviderStateMixin { height: 22, child: getLink(context)), if (widget.closeBtn != null) - Padding( - padding: const EdgeInsets.only(left: 12), - child: Align( - alignment: Alignment.center, - child: SizedBox( - width: 22, - height: 22, - child: getCloseBtn(context), - ), + Align( + alignment: Alignment.center, + child: SizedBox( + width: 22, + height: 22, + child: getCloseBtn(context), ), ), ], @@ -460,7 +467,7 @@ class _TDMessageState extends State with TickerProviderStateMixin { } double calculateTextWidth() { - double width = totalWidth - 32; + var width = totalWidth - 32; if (widget.icon != null && widget.icon != false) { width -= 30; } diff --git a/tdesign-component/lib/src/components/navbar/td_nav_bar.dart b/tdesign-component/lib/src/components/navbar/td_nav_bar.dart index a52edbf88..9c5cfcf7c 100644 --- a/tdesign-component/lib/src/components/navbar/td_nav_bar.dart +++ b/tdesign-component/lib/src/components/navbar/td_nav_bar.dart @@ -4,7 +4,6 @@ import '../../../tdesign_flutter.dart'; typedef TDBarItemAction = void Function(); class TDNavBar extends StatefulWidget implements PreferredSizeWidget { - const TDNavBar({ Key? key, this.leftBarItems, @@ -20,7 +19,7 @@ class TDNavBar extends StatefulWidget implements PreferredSizeWidget { this.backgroundColor, this.titleMargin = 16, this.padding, - this.height = 44, + this.height = 48, this.screenAdaptation = true, this.useDefaultBack = true, this.onBack, @@ -33,35 +32,47 @@ class TDNavBar extends StatefulWidget implements PreferredSizeWidget { /// 左边操作项 final List? leftBarItems; + /// 右边操作项 final List? rightBarItems; - /// 标题控件,优先级高于title文案 + + /// 标题控件,优先级高于 title 文案 final Widget? titleWidget; + /// 标题文案 final String? title; + /// 标题颜色 final Color? titleColor; + /// 标题字体尺寸 final Font? titleFont; + /// 标题字体粗细 final FontWeight? titleFontWeight; + /// 标题字体样式 final FontFamily? titleFontFamily; + /// 标题是否居中 final bool centerTitle; + /// 透明度 final double opacity; + /// 背景颜色 final Color? backgroundColor; + /// 内部填充 final EdgeInsetsGeometry? padding; /// 中间文案左右两边间距 final double titleMargin; + /// 高度 final double height; - /// 是否进行屏幕适配,默认true + /// 是否进行屏幕适配,默认 true final bool screenAdaptation; /// 是否使用默认的返回 @@ -76,7 +87,7 @@ class TDNavBar extends StatefulWidget implements PreferredSizeWidget { /// 边框 final TDNavBarItemBorder? border; - /// belowTitleWidget navbar 下方的widget + /// belowTitleWidget navbar 下方的 widget final Widget? belowTitleWidget; /// 底部阴影 @@ -95,7 +106,7 @@ class TDNavBar extends StatefulWidget implements PreferredSizeWidget { class _TDNavBarState extends State { Widget _addBorder(List items) { var border = widget.border ?? TDNavBarItemBorder(); - var borderColor = border.color ?? TDTheme.of(context).grayColor3; + var borderColor = border.color ?? TDTheme.of(context).componentStrokeColor; var children = []; for (var i = 0; i < items.length; i++) { children.add(items[i]); @@ -129,7 +140,8 @@ class _TDNavBarState extends State { Widget get backButton { return TDNavBarItem( - icon: Icons.chevron_left, + icon: TDIcons.chevron_left, + iconSize: 28.0, action: () { widget.onBack?.call(); Navigator.maybePop(context); @@ -138,8 +150,7 @@ class _TDNavBarState extends State { } Widget _buildTitleBarItems(bool isLeft) { - var barItems = - (isLeft ? widget.leftBarItems : widget.rightBarItems) ?? []; + var barItems = (isLeft ? widget.leftBarItems : widget.rightBarItems) ?? []; var children = barItems .map( (e) => e.toWidget(context, isLeft: isLeft), @@ -148,8 +159,7 @@ class _TDNavBarState extends State { return Row( children: [ - if (isLeft && widget.useDefaultBack) - backButton, + if (isLeft && widget.useDefaultBack) backButton, if (children.isNotEmpty) widget.useBorderStyle ? _addBorder(children) @@ -163,7 +173,7 @@ class _TDNavBarState extends State { } TextStyle _getTitleStyle(BuildContext context) { - var titleColor = widget.titleColor ?? TDTheme.of(context).fontGyColor1; + var titleColor = widget.titleColor ?? TDTheme.of(context).textColorPrimary; var titleFont = widget.titleFont ?? TDTheme.of(context).fontBodyLarge; @@ -193,8 +203,8 @@ class _TDNavBarState extends State { ); } - Widget _getNavbarChild(){ - final Widget toolbar = NavigationToolbar( + Widget _getNavbarChild() { + final Widget toolbar = NavigationToolbar( leading: _buildTitleBarItems(true), middle: _getTitleWidget(context), trailing: _buildTitleBarItems(false), @@ -204,9 +214,7 @@ class _TDNavBarState extends State { if (widget.belowTitleWidget == null) { return toolbar; } - var children = [ - Expanded(child: toolbar) - ]; + var children = [Expanded(child: toolbar)]; children.add(widget.belowTitleWidget as Widget); return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -216,12 +224,14 @@ class _TDNavBarState extends State { @override Widget build(BuildContext context) { - var bcc = widget.backgroundColor ?? TDTheme.of(context).whiteColor1; - if (bcc != Colors.transparent) { - bcc = bcc.withOpacity(widget.opacity); + var _backgroundColor = + widget.backgroundColor ?? TDTheme.of(context).bgColorContainer; + if (_backgroundColor != Colors.transparent) { + _backgroundColor = _backgroundColor.withOpacity(widget.opacity); } - var paddingTop = widget.screenAdaptation ? MediaQuery.of(context).padding.top : 0.0; + var paddingTop = + widget.screenAdaptation ? MediaQuery.of(context).padding.top : 0.0; var padding = widget.padding ?? EdgeInsets.symmetric( horizontal: TDTheme.of(context).spacer16, @@ -231,11 +241,10 @@ class _TDNavBarState extends State { height: widget.height + paddingTop, padding: padding.add(EdgeInsets.only(top: paddingTop)), decoration: BoxDecoration( - color: bcc, + color: _backgroundColor, boxShadow: widget.boxShadow, ), - child: _getNavbarChild() - ); + child: _getNavbarChild()); if (widget.flexibleSpace != null) { appBar = Stack( fit: StackFit.passthrough, @@ -253,15 +262,20 @@ class _TDNavBarState extends State { class TDNavBarItem { /// 图标 IconData? icon; + /// 图标颜色 Color? iconColor; + /// 操作回调 TDBarItemAction? action; + /// 图标尺寸 double? iconSize; + /// 内部填充 EdgeInsetsGeometry? padding; - /// 图标组件,优先级高与icon + + /// 图标组件,优先级高于 icon Widget? iconWidget; TDNavBarItem({ @@ -273,12 +287,15 @@ class TDNavBarItem { this.iconWidget, }); - Widget toWidget(BuildContext context,{bool isLeft = true}) => GestureDetector( + Widget toWidget(BuildContext context, {bool isLeft = true}) => + GestureDetector( behavior: HitTestBehavior.opaque, onTap: action, child: Padding( - padding: - padding ?? (isLeft ? EdgeInsets.only(right: TDTheme.of(context).spacer8) : EdgeInsets.only(left: TDTheme.of(context).spacer8)), + padding: padding ?? + (isLeft + ? EdgeInsets.only(right: TDTheme.of(context).spacer8) + : EdgeInsets.only(left: TDTheme.of(context).spacer8)), child: iconWidget ?? Icon( icon, diff --git a/tdesign-component/lib/src/components/notice_bar/td_notice_bar.dart b/tdesign-component/lib/src/components/notice_bar/td_notice_bar.dart index 9299a7af3..7b32c47c7 100644 --- a/tdesign-component/lib/src/components/notice_bar/td_notice_bar.dart +++ b/tdesign-component/lib/src/components/notice_bar/td_notice_bar.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:math' as math; import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; @@ -11,6 +12,7 @@ import '../../../tdesign_flutter.dart'; class TDNoticeBar extends StatefulWidget { const TDNoticeBar({ super.key, + this.content, this.context, this.style, this.left, @@ -25,12 +27,20 @@ class TDNoticeBar extends StatefulWidget { this.onTap, this.height = 22, this.maxLines = 1, - }); - - /// 文本内容 + }) : assert(content == null || content is String || content is List, + 'content must be String or List'), + assert(speed == null || speed >= 0, 'speed must not be less than 0'), + assert(interval == null || interval >= 0, + 'interval must not be less than 0'); + + /// 文本内容(请使用content属性) + @deprecated final dynamic context; - /// 公告栏样式 + /// 文本内容(字符串或字符串数组等) + final dynamic content; + + /// 公告栏样式 [TDNoticeBarStyle] final TDNoticeBarStyle? style; /// 左侧内容(自定义左侧内容,优先级高于prefixIcon) @@ -76,23 +86,22 @@ class TDNoticeBar extends StatefulWidget { class _TDNoticeBarState extends State { ScrollController? _scrollController; Timer? _timer; + Size? _size; TDNoticeBarStyle? _style; Color? _backgroundColor; - Widget? _left; - Widget? _right; + final GlobalKey _key = GlobalKey(); - final GlobalKey _contextKey = GlobalKey(); + final GlobalKey _contentKey = GlobalKey(); + + dynamic _content; @override void initState() { + /// todo 初始化内容数据,兼用旧版本,后续版本待移除 + _content = widget.content ?? widget.context; + super.initState(); - if (widget.speed! < 0) { - throw Exception('speed must not be less than 0'); - } - if (widget.interval! <= 0) { - throw Exception('interval must not be less than 0'); - } _scrollController = ScrollController(); WidgetsBinding.instance.addPostFrameCallback((time) { if (widget.marquee == true) { @@ -101,22 +110,21 @@ class _TDNoticeBarState extends State { }); } - @override - void dispose() { - super.dispose(); - _timer?.cancel(); - _scrollController?.dispose(); - } - void _init() { + // 初始化样式及左右widget if (widget.style != null) { _style = widget.style; } else { _style = TDNoticeBarStyle.generateTheme(context, theme: widget.theme); } _backgroundColor = _style!.backgroundColor; - _setLeftWidget(); - _setRightWidget(); + } + + @override + void dispose() { + super.dispose(); + _timer?.cancel(); + _scrollController?.dispose(); } void _startTimer() { @@ -166,7 +174,7 @@ class _TDNoticeBarState extends State { var offset = 0.0; _timer = Timer.periodic(Duration(milliseconds: widget.interval!), (timer) { var time = (widget.height / widget.speed! * 1000).round(); - if (step >= widget.context.length) { + if (step >= _content.length) { step = 0; offset = 0; _scrollController!.jumpTo(0); @@ -181,14 +189,14 @@ class _TDNoticeBarState extends State { /// 获取文本内容尺寸消息 Size _getFontSize() { - var text = widget.context; - if (widget.context is List) { - text = widget.context[0]; + var text = _content; + if (_content is List) { + text = _content[0]; } final textPainter = TextPainter( text: TextSpan( text: text, - style: _style!.getTextStyle, + style: _style!.textStyle, ), locale: Localizations.localeOf(context), textDirection: TextDirection.ltr, @@ -197,34 +205,6 @@ class _TDNoticeBarState extends State { return textPainter.size; } - /// 设置左侧内容 - void _setLeftWidget() { - if (widget.prefixIcon != null) { - _left = Icon( - widget.prefixIcon, - color: _style!.leftIconColor, - size: widget.height, - ); - } - if (widget.left != null) { - _left = widget.left; - } - } - - /// 设置右侧内容 - void _setRightWidget() { - if (widget.suffixIcon != null) { - _right = Icon( - widget.suffixIcon, - color: _style!.rightIconColor, - size: widget.height, - ); - } - if (widget.right != null) { - _right = widget.right; - } - } - /// 获取文本内容宽度 double _getContextWidth() { var contextWidth = @@ -237,7 +217,7 @@ class _TDNoticeBarState extends State { /// 获取滚动区域宽度 double _getEmptyWidth() { - return _contextKey.currentContext + return _contentKey.currentContext ?.findRenderObject() ?.paintBounds .size @@ -251,54 +231,45 @@ class _TDNoticeBarState extends State { } /// 内容区域 - Widget _contextWidget() { - var valid = false; + Widget _contentWidget() { Widget? textWidget; - if (widget.context is String) { - valid = true; - textWidget = SizedBox( - height: _getTextHeight(), - child: Align( - alignment: Alignment.centerLeft, - child: SizedBox( - height: _getTextHeight(), - child: TDText( - widget.context, - style: _style?.getTextStyle, - maxLines: widget.marquee! ? 1 : widget.maxLines, - forceVerticalCenter: true, - ), - ), - ), - ); + + String? displayText; + if (_content is String) { + displayText = _content as String; + } else if (_content is List && _content.isNotEmpty) { + displayText = _content[0]; } - if (widget.context is List) { - valid = true; + + if (displayText != null) { textWidget = SizedBox( height: _getTextHeight(), child: Align( alignment: Alignment.centerLeft, - child: SizedBox( - height: _getTextHeight(), - child: TDText( - widget.context[0], - style: _style?.getTextStyle, - maxLines: 1, - forceVerticalCenter: true, - ), + child: TDText( + displayText, + style: _style?.textStyle, + maxLines: widget.marquee == true ? 1 : widget.maxLines, + forceVerticalCenter: true, ), ), ); + } else { + // 如果 content 类型不支持或为空,返回空容器 + textWidget = const SizedBox.shrink(); } - if (!valid) { - throw Exception('context must be String or List'); - } + if (widget.marquee == false) { - return textWidget!; + return textWidget; } + Widget? child; switch (widget.direction) { case Axis.horizontal: + final emptyWidth = _getEmptyWidth(); + final textHeight = _getTextHeight(); + final contextWidth = _getContextWidth(); + child = SingleChildScrollView( controller: _scrollController, scrollDirection: Axis.horizontal, @@ -307,15 +278,13 @@ class _TDNoticeBarState extends State { children: [ SizedBox( key: _key, - height: _getTextHeight(), + height: textHeight, child: textWidget, ), - SizedBox(width: _getEmptyWidth()), + SizedBox(width: emptyWidth), SizedBox( - width: _getEmptyWidth() > _getContextWidth() - ? _getEmptyWidth() - : _getContextWidth(), - height: _getTextHeight(), + width: math.max(emptyWidth, contextWidth), + height: textHeight, child: textWidget, ) ], @@ -323,7 +292,7 @@ class _TDNoticeBarState extends State { ); break; case Axis.vertical: - var contexts = widget.context as List; + var content = _content as List; child = SizedBox( height: widget.height, child: SingleChildScrollView( @@ -334,14 +303,14 @@ class _TDNoticeBarState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - for (int i = 0; i < contexts.length; i++) + for (int i = 0; i < content.length; i++) SizedBox( height: widget.height, child: Align( alignment: Alignment.centerLeft, child: TDText( - contexts[i], - style: _style!.getTextStyle, + content[i], + style: _style!.textStyle, maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -353,8 +322,8 @@ class _TDNoticeBarState extends State { child: Align( alignment: Alignment.centerLeft, child: TDText( - contexts[0], - style: _style?.getTextStyle, + content[0], + style: _style?.textStyle, maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -368,7 +337,7 @@ class _TDNoticeBarState extends State { child = textWidget; break; } - return child!; + return child; } void _onTap(trigger) { @@ -379,42 +348,55 @@ class _TDNoticeBarState extends State { @override Widget build(BuildContext context) { - // 初始化样式及左右widget _init(); _size = MediaQuery.of(context).size; return Container( padding: _style!.getPadding, - decoration: BoxDecoration( - color: _backgroundColor, - ), + color: _backgroundColor, child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start, + // spacing: 8, children: [ - Visibility( - visible: _left != null, - child: GestureDetector( + /// 左侧widget + if (widget.left != null) + widget.left! + else if (widget.prefixIcon != null) + GestureDetector( onTap: () => _onTap('prefix-icon'), child: Container( margin: const EdgeInsets.only(right: 8), - child: _left, + child: Icon( + widget.prefixIcon, + color: _style?.leftIconColor, + size: widget.height, + ), ), ), - ), + + /// 中间内容 Expanded( - key: _contextKey, + key: _contentKey, child: GestureDetector( onTap: () => _onTap('context'), - child: _contextWidget(), - ), - ), - Visibility( - visible: _right != null, - child: GestureDetector( - onTap: () => _onTap('suffix-icon'), - child: _right, + child: _contentWidget(), ), ), + + /// 左侧widget + if (widget.right != null) + widget.right! + else if (widget.suffixIcon != null) + GestureDetector( + onTap: () => _onTap('suffix-icon'), + child: Container( + margin: const EdgeInsets.only(left: 8), + child: Icon( + widget.suffixIcon, + color: _style?.rightIconColor, + size: widget.height, + ), + )), ], ), ); diff --git a/tdesign-component/lib/src/components/notice_bar/td_notice_bar_style.dart b/tdesign-component/lib/src/components/notice_bar/td_notice_bar_style.dart index b08c4e184..87412d0b9 100644 --- a/tdesign-component/lib/src/components/notice_bar/td_notice_bar_style.dart +++ b/tdesign-component/lib/src/components/notice_bar/td_notice_bar_style.dart @@ -18,7 +18,7 @@ enum TDNoticeBarType { /// 公告栏主题 enum TDNoticeBarTheme { - /// 默认 + /// 信息(默认) info, /// 成功 @@ -33,13 +33,14 @@ enum TDNoticeBarTheme { /// 公告栏样式 class TDNoticeBarStyle { - TDNoticeBarStyle( - {this.context, - this.backgroundColor, - this.textStyle, - this.leftIconColor, - this.rightIconColor, - this.padding}); + TDNoticeBarStyle({ + this.context, + this.backgroundColor, + this.textStyle, + this.leftIconColor, + this.rightIconColor, + this.padding, + }); /// 上下文 BuildContext? context; @@ -64,21 +65,20 @@ class TDNoticeBarStyle { padding ?? const EdgeInsets.only(top: 13, bottom: 13, left: 16, right: 12); - /// 公告栏内容样式,用于获取默认值 - TextStyle get getTextStyle => - textStyle ?? - TextStyle( - color: TDTheme.of(context).fontGyColor1, - fontSize: 14, - height: 1, - fontWeight: FontWeight.normal, - fontStyle: FontStyle.normal, - ); - /// 根据主题生成样式 - TDNoticeBarStyle.generateTheme(BuildContext context, - {TDNoticeBarTheme? theme = TDNoticeBarTheme.info}) { - rightIconColor = TDTheme.of(context).grayColor7; + TDNoticeBarStyle.generateTheme( + BuildContext context, { + TDNoticeBarTheme? theme = TDNoticeBarTheme.info, + }) { + rightIconColor = TDTheme.of(context).textColorPlaceholder; + textStyle = textStyle ?? + TextStyle( + color: TDTheme.of(context).textColorPrimary, + fontSize: 14, + height: 1, + fontWeight: FontWeight.normal, + fontStyle: FontStyle.normal, + ); switch (theme) { case TDNoticeBarTheme.warning: leftIconColor = TDTheme.of(context).warningNormalColor; diff --git a/tdesign-component/lib/src/components/picker/td_date_picker.dart b/tdesign-component/lib/src/components/picker/td_date_picker.dart index 6030b8987..987e19fb7 100644 --- a/tdesign-component/lib/src/components/picker/td_date_picker.dart +++ b/tdesign-component/lib/src/components/picker/td_date_picker.dart @@ -7,46 +7,49 @@ import '../../util/context_extension.dart'; import 'no_wave_behavior.dart'; typedef DatePickerCallback = void Function(Map selected); + enum DateTypeKey { year, month, weekDay, day, hour, minute, second } /// 时间选择器 class TDDatePicker extends StatefulWidget { - const TDDatePicker( - {required this.title, - required this.onConfirm, - this.rightText, - this.leftText, - this.onCancel, - this.backgroundColor, - this.titleDividerColor, - this.topRadius, - this.titleHeight, - this.padding, - this.leftPadding, - this.rightPadding, - this.leftTextStyle, - this.rightTextStyle, - this.centerTextStyle, - this.customSelectWidget, - this.itemDistanceCalculator, - required this.model, - this.showTitle = true, - this.pickerHeight = 200, - required this.pickerItemCount, - this.isTimeUnit, - this.onSelectedItemChanged, - this.itemBuilder, - Key? key}) - : super(key: key); + const TDDatePicker({ + this.title, + this.titleHeight, + this.titleDividerColor, + this.onConfirm, + this.onCancel, + this.onChange, + this.onSelectedItemChanged, + this.leftText, + this.rightText, + this.leftTextStyle, + this.centerTextStyle, + this.rightTextStyle, + this.padding, + this.leftPadding, + this.topPadding, + this.rightPadding, + this.topRadius, + this.backgroundColor, + this.customSelectWidget, + this.header = true, + this.itemDistanceCalculator, + required this.model, + this.pickerHeight = 200, + this.pickerItemCount = 5, + this.isTimeUnit, + this.itemBuilder, + Key? key, + }) : super(key: key); /// 选择器标题 - final String title; + final String? title; - /// 右侧按钮文案 - final String? rightText; + /// 标题高度 + final double? titleHeight; - /// 左侧按钮文案 - final String? leftText; + /// 标题分割线颜色 + final Color? titleDividerColor; /// 选择器确认按钮回调 final DatePickerCallback? onConfirm; @@ -54,17 +57,32 @@ class TDDatePicker extends StatefulWidget { /// 选择器取消按钮回调 final DatePickerCallback? onCancel; - /// 背景颜色 - final Color? backgroundColor; + /// 选择器值改变回调 + final DatePickerCallback? onChange; - /// 标题分割线颜色 - final Color? titleDividerColor; + /// 选择器选中项改变回调 + final void Function(int wheelIndex, int index)? onSelectedItemChanged; - /// 顶部圆角 - final double? topRadius; + /// 左侧按钮文案 + final String? leftText; - /// 标题高度 - final double? titleHeight; + /// 右侧按钮文案 + final String? rightText; + + /// 自定义左侧文案样式 + final TextStyle? leftTextStyle; + + /// 自定义中间文案样式 + final TextStyle? centerTextStyle; + + /// 自定义右侧文案样式 + final TextStyle? rightTextStyle; + + /// 适配padding + final EdgeInsets? padding; + + /// 顶部填充 + final double? topPadding; /// 左边填充 final double? leftPadding; @@ -72,42 +90,33 @@ class TDDatePicker extends StatefulWidget { /// 右边填充 final double? rightPadding; + /// 顶部圆角 + final double? topRadius; + + /// 背景颜色 + final Color? backgroundColor; + /// 根据距离计算字体颜色、透明度、粗细 final ItemDistanceCalculator? itemDistanceCalculator; + /// 是否显示头部内容 + final bool header; + /// 选择器List的视窗高度,默认200 final double pickerHeight; - /// 选择器List视窗中item个数,pickerHeight / pickerItemCount即item高度 + /// 选择器List视窗中item个数,pickerHeight / pickerItemCount,即item高度 final int pickerItemCount; /// 自定义选择框样式 final Widget? customSelectWidget; - /// 自定义左侧文案样式 - final TextStyle? leftTextStyle; - - /// 自定义右侧文案样式 - final TextStyle? rightTextStyle; - - /// 自定义中间文案样式 - final TextStyle? centerTextStyle; - - /// 适配padding - final EdgeInsets? padding; - - /// 是否展示标题 - final bool showTitle; - /// 数据模型 final DatePickerModel model; /// 是否时间显示 final bool? isTimeUnit; - /// 选择器选中项改变回调 - final void Function(int wheelIndex,int index)? onSelectedItemChanged; - /// 自定义item构建 final ItemBuilderType? itemBuilder; @@ -132,51 +141,58 @@ class _TDDatePickerState extends State { } bool useAll() { - if (widget.model.useYear && + return widget.model.useYear && widget.model.useMonth && widget.model.useDay && widget.model.useHour && widget.model.useMinute && - widget.model.useSecond) { - return true; - } - return false; + widget.model.useSecond; } selectListItem(String ev) { var selected = { 'year': widget.model.useYear - ? widget.model.yearFixedExtentScrollController.selectedItem + widget.model.data[0][0] + ? widget.model.yearFixedExtentScrollController.selectedItem + + widget.model.data[0][0] : -1, 'month': widget.model.useMonth - ? widget.model.monthFixedExtentScrollController.selectedItem + widget.model.data[1][0] + ? widget.model.monthFixedExtentScrollController.selectedItem + + widget.model.data[1][0] + : -1, + 'day': widget.model.useDay + ? widget.model.dayFixedExtentScrollController.selectedItem + + widget.model.data[2][0] : -1, - 'day': - widget.model.useDay ? widget.model.dayFixedExtentScrollController.selectedItem + widget.model.data[2][0] : -1, 'weekDay': widget.model.useWeekDay - ? widget.model.weekDayFixedExtentScrollController.selectedItem + widget.model.data[3][0] + ? widget.model.weekDayFixedExtentScrollController.selectedItem + + widget.model.data[3][0] : -1, 'hour': widget.model.useHour - ? selectItemValue(widget.model.data[4], widget.model.hourFixedExtentScrollController.selectedItem) + ? selectItemValue(widget.model.data[4], + widget.model.hourFixedExtentScrollController.selectedItem) : -1, 'minute': widget.model.useMinute - ? selectItemValue(widget.model.data[5], widget.model.minuteFixedExtentScrollController.selectedItem) + ? selectItemValue(widget.model.data[5], + widget.model.minuteFixedExtentScrollController.selectedItem) : -1, 'second': widget.model.useSecond - ? selectItemValue(widget.model.data[6], widget.model.secondFixedExtentScrollController.selectedItem) + ? selectItemValue(widget.model.data[6], + widget.model.secondFixedExtentScrollController.selectedItem) : -1, }; if (ev == 'onCancel' && widget.onCancel != null) { widget.onCancel!(selected); } else if (ev == 'onConfirm' && widget.onConfirm != null) { widget.onConfirm!(selected); + } else if (ev == 'onChange' && widget.onChange != null) { + widget.onChange!(selected); } else { Navigator.of(context).pop(); } } int selectItemValue(List items, int itemIndex) { - ///选择列表索引对应的项的值 + /// 选择列表索引对应的项的值 return items[itemIndex]; } @@ -185,21 +201,19 @@ class _TDDatePickerState extends State { var maxWidth = MediaQuery.of(context).size.width; return Container( width: maxWidth, - padding: widget.padding ?? EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + padding: widget.padding ?? + EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), decoration: BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), - topRight: Radius.circular(widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), ), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - Visibility( - child: buildTitle(context), - visible: widget.showTitle == true, - ), + if (widget.header) _buildHeader(context), SizedBox( height: pickerHeight, child: Stack( @@ -211,8 +225,10 @@ class _TDDatePickerState extends State { Container( height: 40, decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, - borderRadius: const BorderRadius.all(Radius.circular(6))), + color: + TDTheme.of(context).bgColorSecondaryContainer, + borderRadius: BorderRadius.all(Radius.circular( + TDTheme.of(context).radiusDefault))), ), ), Container( @@ -229,12 +245,24 @@ class _TDDatePickerState extends State { ) : Expanded(child: buildList(context, 0)) : Container(), - widget.model.useMonth ? Expanded(child: buildList(context, 1)) : Container(), - widget.model.useDay ? Expanded(child: buildList(context, 2)) : Container(), - widget.model.useWeekDay ? Expanded(child: buildList(context, 3)) : Container(), - widget.model.useHour ? Expanded(child: buildList(context, 4)) : Container(), - widget.model.useMinute ? Expanded(child: buildList(context, 5)) : Container(), - widget.model.useSecond ? Expanded(child: buildList(context, 6)) : Container(), + widget.model.useMonth + ? Expanded(child: buildList(context, 1)) + : Container(), + widget.model.useDay + ? Expanded(child: buildList(context, 2)) + : Container(), + widget.model.useWeekDay + ? Expanded(child: buildList(context, 3)) + : Container(), + widget.model.useHour + ? Expanded(child: buildList(context, 4)) + : Container(), + widget.model.useMinute + ? Expanded(child: buildList(context, 5)) + : Container(), + widget.model.useSecond + ? Expanded(child: buildList(context, 6)) + : Container(), ], )), // 蒙层 @@ -246,10 +274,13 @@ class _TDDatePickerState extends State { height: _pickerTitleHeight, width: MediaQuery.of(context).size.width, decoration: BoxDecoration( - gradient: LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - TDTheme.of(context).whiteColor1, - TDTheme.of(context).whiteColor1.withOpacity(0) - ])), + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + TDTheme.of(context).bgColorContainer, + TDTheme.of(context).bgColorContainer.withOpacity(0) + ])), ), ), ), @@ -261,10 +292,13 @@ class _TDDatePickerState extends State { height: _pickerTitleHeight, width: MediaQuery.of(context).size.width, decoration: BoxDecoration( - gradient: LinearGradient(begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [ - TDTheme.of(context).whiteColor1, - TDTheme.of(context).whiteColor1.withOpacity(0) - ])), + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + colors: [ + TDTheme.of(context).bgColorContainer, + TDTheme.of(context).bgColorContainer.withOpacity(0) + ])), ), ), ) @@ -288,7 +322,9 @@ class _TDDatePickerState extends State { itemExtent: pickerHeight / widget.pickerItemCount, diameterRatio: 100, controller: widget.model.controllers[whichLine], - physics: whichLine == 3 ? const NeverScrollableScrollPhysics() : const FixedExtentScrollPhysics(), + physics: whichLine == 3 + ? const NeverScrollableScrollPhysics() + : const FixedExtentScrollPhysics(), onSelectedItemChanged: (index) { if (whichLine == 0 || whichLine == 1 || @@ -319,15 +355,20 @@ class _TDDatePickerState extends State { break; } if (useAll()) { - widget.model.refreshTimeDataInitialAndController(whichLine); + widget.model + .refreshTimeDataInitialAndController(whichLine); } /// 使用动态高度,强制列表组件的state刷新,以展现更新的数据,详见下方链接 /// FIX:https://github.com/flutter/flutter/issues/22999 - pickerHeight = pickerHeight - Random().nextDouble() / 100000000; + pickerHeight = + pickerHeight - Random().nextDouble() / 100000000; }); } - widget.onSelectedItemChanged?.call(whichLine,index); + if (widget.onChange != null) { + selectListItem('onChange'); + } + widget.onSelectedItemChanged?.call(whichLine, index); }, childDelegate: ListWheelChildBuilderDelegate( childCount: widget.model.data[whichLine].length, @@ -341,9 +382,12 @@ class _TDDatePickerState extends State { index: index, itemHeight: pickerHeight / widget.pickerItemCount, content: whichLine == 3 - ? weekUnitMap(widget.model.data[whichLine][index] - 1) - : widget.model.data[whichLine][index].toString() + timeUnitMap(widget.model.mapping[whichLine]), - fixedExtentScrollController: widget.model.controllers[whichLine], + ? weekUnitMap( + widget.model.data[whichLine][index] - 1) + : widget.model.data[whichLine][index].toString() + + timeUnitMap(widget.model.mapping[whichLine]), + fixedExtentScrollController: + widget.model.controllers[whichLine], itemDistanceCalculator: widget.itemDistanceCalculator, itemBuilder: widget.itemBuilder, )); @@ -351,16 +395,23 @@ class _TDDatePickerState extends State { )); } - Widget buildTitle(BuildContext context) { + Widget _buildHeader(BuildContext context) { + final padding = TDTheme.of(context).spacer16; + return Container( - padding: EdgeInsets.only(left: widget.leftPadding ?? 16, right: widget.rightPadding ?? 16), + padding: EdgeInsets.only( + left: widget.leftPadding ?? padding, + right: widget.rightPadding ?? padding, + top: widget.topPadding ?? padding, + ), decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - width: 1, - color: widget.titleDividerColor ?? Colors.transparent, + border: Border( + bottom: BorderSide( + width: 0.5, + color: widget.titleDividerColor ?? Colors.transparent, + ), ), - )), + ), /// 减去分割线的空间 height: getTitleHeight() - 0.5, @@ -369,25 +420,29 @@ class _TDDatePickerState extends State { children: [ /// 左边按钮 GestureDetector( - onTap: () { - selectListItem('onCancel'); - }, - behavior: HitTestBehavior.opaque, - child: TDText(widget.leftText ?? context.resource.cancel, - style: widget.leftTextStyle ?? - TextStyle( - fontSize: TDTheme.of(context).fontBodyLarge!.size, color: TDTheme.of(context).fontGyColor2))), + onTap: () { + selectListItem('onCancel'); + }, + behavior: HitTestBehavior.opaque, + child: TDText( + widget.leftText ?? context.resource.cancel, + style: widget.leftTextStyle ?? + TextStyle( + fontSize: TDTheme.of(context).fontBodyLarge!.size, + color: TDTheme.of(context).textColorSecondary), + ), + ), /// 中间title Expanded( child: Center( child: TDText( - widget.title, + widget.title ?? '', style: widget.centerTextStyle ?? TextStyle( - fontSize: 18, + fontSize: TDTheme.of(context).fontBodyLarge!.size, fontWeight: FontWeight.w600, - color: TDTheme.of(context).fontGyColor1, + color: TDTheme.of(context).textColorPrimary, ), ), ), @@ -403,32 +458,34 @@ class _TDDatePickerState extends State { widget.rightText ?? context.resource.confirm, style: widget.rightTextStyle ?? TextStyle( - fontSize: TDTheme.of(context).fontBodyLarge!.size, color: TDTheme.of(context).brandNormalColor), + fontSize: TDTheme.of(context).fontBodyLarge!.size, + color: TDTheme.of(context).brandNormalColor), ), ), ], ), ); } - timeUnitMap(String name){ - if(widget.isTimeUnit!=null&&widget.isTimeUnit==true){ - var times={ - '年':context.resource.yearLabel, - '月':context.resource.monthLabel, + + timeUnitMap(String name) { + if (widget.isTimeUnit != null && widget.isTimeUnit == true) { + var times = { + '年': context.resource.yearLabel, + '月': context.resource.monthLabel, '日': context.resource.dateLabel, - '周':context.resource.weeksLabel, - '时':context.resource.hours, - '分':context.resource.minutes, - '秒':context.resource.seconds + '周': context.resource.weeksLabel, + '时': context.resource.hours, + '分': context.resource.minutes, + '秒': context.resource.seconds }; return times[name]; - }else{ + } else { return ''; } } - weekUnitMap(int index){ - if(index < 0 || index > 6){ + weekUnitMap(int index) { + if (index < 0 || index > 6) { return ''; } return [ @@ -442,7 +499,6 @@ class _TDDatePickerState extends State { ][index]; } - double getTitleHeight() => widget.titleHeight ?? _pickerTitleHeight; } @@ -459,8 +515,8 @@ class DatePickerModel { List dateEnd; List? dateInitial; List Function(DateTypeKey key, List nums)? filterItems; - final mapping = ['年', '月', '日', '周', '时', '分', '秒']; - final weekMap= ['一', '二', '三', '四', '五', '六', '日']; + final mapping = ['年', '月', '日', '周', '时', '分', '秒']; + final weekMap = ['一', '二', '三', '四', '五', '六', '日']; late DateTime initialTime; @@ -490,34 +546,38 @@ class DatePickerModel { late FixedExtentScrollController minuteFixedExtentScrollController; late FixedExtentScrollController secondFixedExtentScrollController; - DatePickerModel( - {required this.useYear, - required this.useMonth, - required this.useDay, - required this.useHour, - required this.useMinute, - required this.useWeekDay, - required this.useSecond, - required this.dateStart, - required this.dateEnd, - this.dateInitial, - this.filterItems, -}) { - assert(!useWeekDay || (!useSecond && !useMinute && !useHour), 'WeekDay can only used with Year, Month and Day!'); + DatePickerModel({ + required this.useYear, + required this.useMonth, + required this.useDay, + required this.useHour, + required this.useMinute, + required this.useSecond, + required this.useWeekDay, + required this.dateStart, + required this.dateEnd, + this.dateInitial, + this.filterItems, + }) { + assert(!useWeekDay || (!useSecond && !useMinute && !useHour), + 'WeekDay can only used with Year, Month and Day!'); setInitialTime(); setInitialYearData(); setInitialMonthData(); setInitialDayData(); - setInitialWeekDayData(); setInitialTimeData(); + setInitialWeekDayData(); setControllers(); addListener(); } void setInitialTime() { - dateStart = List.generate(6, (index) => index < dateStart.length ? dateStart[index] : 0); - var startTime = DateTime(dateStart[0], dateStart[1], dateStart[2], dateStart[3], dateStart[4], dateStart[5]); - dateEnd = List.generate(6, (index) => index < dateEnd.length ? dateEnd[index] : 0); + dateStart = List.generate( + 6, (index) => index < dateStart.length ? dateStart[index] : 0); + var startTime = DateTime(dateStart[0], dateStart[1], dateStart[2], + dateStart[3], dateStart[4], dateStart[5]); + dateEnd = List.generate( + 6, (index) => index < dateEnd.length ? dateEnd[index] : 0); var endTime = DateTime( dateEnd[0], dateEnd[1], @@ -527,8 +587,10 @@ class DatePickerModel { dateEnd[5], ); if (dateInitial != null) { - var initList = List.generate(6, (index) => index < dateInitial!.length ? dateInitial![index] : 0); - initialTime = DateTime(initList[0], initList[1], initList[2], initList[3], initList[4], initList[5]); + var initList = List.generate( + 6, (index) => index < dateInitial!.length ? dateInitial![index] : 0); + initialTime = DateTime(initList[0], initList[1], initList[2], initList[3], + initList[4], initList[5]); if (initialTime.isBefore(startTime)) { initialTime = startTime; } else if (initialTime.isAfter(endTime)) { @@ -548,42 +610,61 @@ class DatePickerModel { } void setInitialYearData() { - var years = List.generate(dateEnd[0] - dateStart[0] + 1, (index) => index + dateStart[0]); - data[0] = useYear && filterItems != null ? filterItems!(DateTypeKey.year, years) : years; + var years = List.generate( + dateEnd[0] - dateStart[0] + 1, (index) => index + dateStart[0]); + data[0] = useYear && filterItems != null + ? filterItems!(DateTypeKey.year, years) + : years; } void setInitialMonthData() { late List month; if (dateEnd[0] == dateStart[0]) { - month = List.generate(dateEnd[1] - dateStart[1] + 1, (index) => index + dateStart[1]); + month = List.generate( + dateEnd[1] - dateStart[1] + 1, (index) => index + dateStart[1]); } else if (initialTime.year == dateStart[0]) { - month = List.generate(12 - dateStart[1] + 1, (index) => index + dateStart[1]); + month = + List.generate(12 - dateStart[1] + 1, (index) => index + dateStart[1]); } else if (initialTime.year == dateEnd[0]) { month = List.generate(dateEnd[1], (index) => index + 1); } else { month = List.generate(12, (index) => index + 1); } - data[1] = useMonth && filterItems != null ? filterItems!(DateTypeKey.month, month) : month; + data[1] = useMonth && filterItems != null + ? filterItems!(DateTypeKey.month, month) + : month; } void setInitialDayData() { late List day; if (dateEnd[0] == dateStart[0] && dateEnd[1] == dateStart[1]) { - day = List.generate(dateEnd[2] - dateStart[2] + 1, (index) => index + dateStart[2]); - } else if (initialTime.year == dateStart[0] && initialTime.month == dateStart[1]) { day = List.generate( - DateTime(initialTime.year, initialTime.month + 1, 0).day - dateStart[2] + 1, (index) => index + dateStart[2]); - } else if (initialTime.year == dateEnd[0] && initialTime.month == dateEnd[1]) { + dateEnd[2] - dateStart[2] + 1, (index) => index + dateStart[2]); + } else if (initialTime.year == dateStart[0] && + initialTime.month == dateStart[1]) { + day = List.generate( + DateTime(initialTime.year, initialTime.month + 1, 0).day - + dateStart[2] + + 1, + (index) => index + dateStart[2]); + } else if (initialTime.year == dateEnd[0] && + initialTime.month == dateEnd[1]) { day = List.generate(dateEnd[2], (index) => index + 1); } else { - day = List.generate(DateTime(initialTime.year, initialTime.month + 1, 0).day, (index) => index + 1); + day = List.generate( + DateTime(initialTime.year, initialTime.month + 1, 0).day, + (index) => index + 1); } - data[2] = useDay && filterItems != null ? filterItems!(DateTypeKey.day, day) : day; + data[2] = useDay && filterItems != null + ? filterItems!(DateTypeKey.day, day) + : day; } void setInitialWeekDayData() { var weekDay = [1, 2, 3, 4, 5, 6, 7]; - data[3] = useWeekDay && filterItems != null ? filterItems!(DateTypeKey.weekDay, weekDay) : weekDay; + data[3] = useWeekDay && filterItems != null + ? filterItems!(DateTypeKey.weekDay, weekDay) + : weekDay; } void setInitialTimeData() { @@ -591,29 +672,52 @@ class DatePickerModel { var minute = List.generate(60, (index) => index); var second = List.generate(60, (index) => index); if (dateStart.length > 3) { - if(!useYear&&!useMonth&&!useDay&&dateEnd[0] == dateStart[0] && dateEnd[1] == dateStart[1]&& dateEnd[2] == dateStart[2]){ - hour = List.generate(max(0, dateEnd[3] - dateStart[3] + 1), (i) => i + dateStart[3]); - minute = List.generate(max(0, dateEnd[4] - dateStart[4] + 1), (i) => i + dateStart[4]); - second = List.generate(max(0, dateEnd[5] - dateStart[5] + 1), (i) => i + dateStart[5]); - - data[4] = useHour && filterItems != null ? filterItems!(DateTypeKey.hour, hour) : hour; - data[5] = useMinute && filterItems != null ? filterItems!(DateTypeKey.minute, minute) : minute; - data[6] = useSecond && filterItems != null ? filterItems!(DateTypeKey.second, second) : second; - return; + if (!useYear && + !useMonth && + !useDay && + dateEnd[0] == dateStart[0] && + dateEnd[1] == dateStart[1] && + dateEnd[2] == dateStart[2]) { + hour = List.generate( + max(0, dateEnd[3] - dateStart[3] + 1), (i) => i + dateStart[3]); + minute = List.generate( + max(0, dateEnd[4] - dateStart[4] + 1), (i) => i + dateStart[4]); + second = List.generate( + max(0, dateEnd[5] - dateStart[5] + 1), (i) => i + dateStart[5]); + + data[4] = useHour && filterItems != null + ? filterItems!(DateTypeKey.hour, hour) + : hour; + data[5] = useMinute && filterItems != null + ? filterItems!(DateTypeKey.minute, minute) + : minute; + data[6] = useSecond && filterItems != null + ? filterItems!(DateTypeKey.second, second) + : second; + return; } if (initialTime.hour >= dateStart[3]) { - hour = List.generate(24 - dateStart[3], (index) => index + dateStart[3]); + hour = + List.generate(24 - dateStart[3], (index) => index + dateStart[3]); } if (initialTime.minute >= dateStart[4]) { - minute = List.generate(60 - dateStart[4], (index) => index + dateStart[4]); + minute = + List.generate(60 - dateStart[4], (index) => index + dateStart[4]); } if (initialTime.second >= dateStart[5]) { - second = List.generate(60 - dateStart[5], (index) => index + dateStart[5]); + second = + List.generate(60 - dateStart[5], (index) => index + dateStart[5]); } } - data[4] = useHour && filterItems != null ? filterItems!(DateTypeKey.hour, hour) : hour; - data[5] = useMinute && filterItems != null ? filterItems!(DateTypeKey.minute, minute) : minute; - data[6] = useSecond && filterItems != null ? filterItems!(DateTypeKey.second, second) : second; + data[4] = useHour && filterItems != null + ? filterItems!(DateTypeKey.hour, hour) + : hour; + data[5] = useMinute && filterItems != null + ? filterItems!(DateTypeKey.minute, minute) + : minute; + data[6] = useSecond && filterItems != null + ? filterItems!(DateTypeKey.second, second) + : second; } void setControllers() { @@ -697,16 +801,21 @@ class DatePickerModel { var selectedYear = yearIndex + data[0][0]; late List month; if (dateEnd[0] == dateStart[0]) { - month = List.generate(dateEnd[1] - dateStart[1] + 1, (index) => index + dateStart[1]); + month = List.generate( + dateEnd[1] - dateStart[1] + 1, (index) => index + dateStart[1]); } else if (selectedYear == dateStart[0]) { - month = List.generate(12 - dateStart[1] + 1, (index) => index + dateStart[1]); + month = + List.generate(12 - dateStart[1] + 1, (index) => index + dateStart[1]); } else if (selectedYear == dateEnd[0]) { month = List.generate(dateEnd[1], (index) => index + 1); } else { month = List.generate(12, (index) => index + 1); } - data[1] = useMonth && filterItems != null ? filterItems!(DateTypeKey.month, month) : month; - monthFixedExtentScrollController.jumpToItem(monthIndex > data[1].length - 1 ? data[1].length - 1 : monthIndex); + data[1] = useMonth && filterItems != null + ? filterItems!(DateTypeKey.month, month) + : month; + monthFixedExtentScrollController.jumpToItem( + monthIndex > data[1].length - 1 ? data[1].length - 1 : monthIndex); } void refreshDayDataAndController() { @@ -715,22 +824,30 @@ class DatePickerModel { var selectedMonth = monthIndex + data[1][0]; late List day; if (dateEnd[0] == dateStart[0] && dateEnd[1] == dateStart[1]) { - day = List.generate(dateEnd[2] - dateStart[2] + 1, (index) => index + dateStart[2]); + day = List.generate( + dateEnd[2] - dateStart[2] + 1, (index) => index + dateStart[2]); } else if (selectedYear == dateStart[0] && selectedMonth == dateStart[1]) { day = List.generate( - DateTime(selectedYear, selectedMonth + 1, 0).day - dateStart[2] + 1, (index) => index + dateStart[2]); + DateTime(selectedYear, selectedMonth + 1, 0).day - dateStart[2] + 1, + (index) => index + dateStart[2]); } else if (selectedYear == dateEnd[0] && selectedMonth == dateEnd[1]) { day = List.generate(dateEnd[2], (index) => index + 1); } else { - day = List.generate(DateTime(selectedYear, selectedMonth + 1, 0).day, (index) => index + 1); + day = List.generate(DateTime(selectedYear, selectedMonth + 1, 0).day, + (index) => index + 1); } - data[2] = useDay && filterItems != null ? filterItems!(DateTypeKey.day, day) : day; - dayFixedExtentScrollController.jumpToItem(dayIndex > data[2].length - 1 ? data[2].length - 1 : dayIndex); + data[2] = useDay && filterItems != null + ? filterItems!(DateTypeKey.day, day) + : day; + dayFixedExtentScrollController.jumpToItem( + dayIndex > data[2].length - 1 ? data[2].length - 1 : dayIndex); } void refreshWeekDayDataAndController() { - var date = DateTime(data[0][yearFixedExtentScrollController.selectedItem], - data[1][monthFixedExtentScrollController.selectedItem], data[2][dayFixedExtentScrollController.selectedItem]); + var date = DateTime( + data[0][yearFixedExtentScrollController.selectedItem], + data[1][monthFixedExtentScrollController.selectedItem], + data[2][dayFixedExtentScrollController.selectedItem]); weekDayFixedExtentScrollController.jumpToItem(date.weekday - 1); } @@ -739,38 +856,64 @@ class DatePickerModel { var selectedMonth = monthIndex + data[1][0]; var selectDay = dayIndex + data[2][0]; if (wheel <= 2) { - refreshHourData(selectedYear: selectedYear, selectedMonth: selectedMonth, selectDay: selectDay); - refreshMinuteData(selectedYear: selectedYear, selectedMonth: selectedMonth, selectDay: selectDay); + refreshHourData( + selectedYear: selectedYear, + selectedMonth: selectedMonth, + selectDay: selectDay); + refreshMinuteData( + selectedYear: selectedYear, + selectedMonth: selectedMonth, + selectDay: selectDay); } else { - refreshMinuteData(selectedYear: selectedYear, selectedMonth: selectedMonth, selectDay: selectDay); + refreshMinuteData( + selectedYear: selectedYear, + selectedMonth: selectedMonth, + selectDay: selectDay); } - refreshSecondData(selectedYear: selectedYear, selectedMonth: selectedMonth, selectDay: selectDay); + refreshSecondData( + selectedYear: selectedYear, + selectedMonth: selectedMonth, + selectDay: selectDay); } - void refreshHourData({required int selectedYear, required int selectedMonth, required int selectDay}) { + void refreshHourData( + {required int selectedYear, + required int selectedMonth, + required int selectDay}) { var selectHour = selectDay == data[2][0] ? 0 : hourIndex; late List hour; - if (selectedYear == dateStart[0] && selectedMonth == dateStart[1] && selectDay == dateStart[2]) { - hour = List.generate(24 - (dateStart[3]), (index) => index + dateStart[3]); - } else if (selectedYear == dateEnd[0] && selectedMonth == dateEnd[1] && selectDay == dateEnd[2]) { + if (selectedYear == dateStart[0] && + selectedMonth == dateStart[1] && + selectDay == dateStart[2]) { + hour = + List.generate(24 - (dateStart[3]), (index) => index + dateStart[3]); + } else if (selectedYear == dateEnd[0] && + selectedMonth == dateEnd[1] && + selectDay == dateEnd[2]) { hour = dateEnd[3] >= dateStart[3] ? List.generate(dateEnd[3] + 1, (index) => index) : List.generate(24 - dateStart[3], (index) => index); } else { hour = List.generate(24, (index) => index); } - data[4] = useHour && filterItems != null ? filterItems!(DateTypeKey.hour, hour) : hour; + data[4] = useHour && filterItems != null + ? filterItems!(DateTypeKey.hour, hour) + : hour; hourFixedExtentScrollController.jumpToItem(selectHour > 0 ? hourIndex : 0); } - void refreshMinuteData({required int selectedYear, required int selectedMonth, required int selectDay}) { + void refreshMinuteData( + {required int selectedYear, + required int selectedMonth, + required int selectDay}) { var selectHour = hourIndex + data[4][0]; late List minute; if (selectedYear == dateStart[0] && selectedMonth == dateStart[1] && selectDay == dateStart[2] && selectHour == dateStart[3]) { - minute = List.generate(60 - (dateStart[4]), (index) => index + dateStart[4]); + minute = + List.generate(60 - (dateStart[4]), (index) => index + dateStart[4]); } else if (selectedYear == dateEnd[0] && selectedMonth == dateEnd[1] && selectDay == dateEnd[2] && @@ -781,10 +924,15 @@ class DatePickerModel { } else { minute = List.generate(60, (index) => index); } - data[5] = useMinute && filterItems != null ? filterItems!(DateTypeKey.minute, minute) : minute; + data[5] = useMinute && filterItems != null + ? filterItems!(DateTypeKey.minute, minute) + : minute; } - void refreshSecondData({required int selectedYear, required int selectedMonth, required int selectDay}) { + void refreshSecondData( + {required int selectedYear, + required int selectedMonth, + required int selectDay}) { var selectHour = hourIndex + data[4][0]; var selectMinute = minuteIndex + data[5][0]; late List second; @@ -793,7 +941,8 @@ class DatePickerModel { selectDay == dateStart[2] && selectHour == dateStart[3] && selectMinute == dateStart[4]) { - second = List.generate(60 - (dateStart[5]), (index) => index + dateStart[5]); + second = + List.generate(60 - (dateStart[5]), (index) => index + dateStart[5]); } else if (selectedYear == dateEnd[0] && selectedMonth == dateEnd[1] && selectDay == dateEnd[2] && @@ -805,7 +954,9 @@ class DatePickerModel { } else { second = List.generate(60, (index) => index); } - data[6] = useSecond && filterItems != null ? filterItems!(DateTypeKey.second, second) : second; + data[6] = useSecond && filterItems != null + ? filterItems!(DateTypeKey.second, second) + : second; } Map getSelectedMap() { diff --git a/tdesign-component/lib/src/components/picker/td_item_widget.dart b/tdesign-component/lib/src/components/picker/td_item_widget.dart index 703d1b9ed..5c965e8e2 100644 --- a/tdesign-component/lib/src/components/picker/td_item_widget.dart +++ b/tdesign-component/lib/src/components/picker/td_item_widget.dart @@ -4,14 +4,19 @@ import '../../../tdesign_flutter.dart'; typedef ItemBuilderType = Widget? Function( /// 上下文 BuildContext context, + /// 文字内容 String content, + /// 列号 int colIndex, + /// 行号 int index, + /// 根据距离计算字体颜色、透明度、粗细 ItemDistanceCalculator itemDistanceCalculator, + /// 子项此时离中心的距离 double distance, ); @@ -26,16 +31,16 @@ class TDItemWidget extends StatefulWidget { final ItemDistanceCalculator? itemDistanceCalculator; final ItemBuilderType? itemBuilder; - const TDItemWidget( - {required this.fixedExtentScrollController, - required this.colIndex, - required this.index, - required this.content, - required this.itemHeight, - this.itemDistanceCalculator, - this.itemBuilder, - Key? key}) - : super(key: key); + const TDItemWidget({ + required this.fixedExtentScrollController, + required this.colIndex, + required this.index, + required this.content, + required this.itemHeight, + this.itemDistanceCalculator, + this.itemBuilder, + Key? key, + }) : super(key: key); @override _TDItemWidgetState createState() => _TDItemWidgetState(); @@ -61,7 +66,11 @@ class _TDItemWidgetState extends State { /// 子项此时离中心的距离 /// 不要使用widget.fixedExtentScrollController.selectedItem /// 其中selectedItem会报错,原因是一开始minScrollExtent为空 - var distance = (widget.fixedExtentScrollController.offset / widget.itemHeight - widget.index).abs().toDouble(); + var distance = + (widget.fixedExtentScrollController.offset / widget.itemHeight - + widget.index) + .abs() + .toDouble(); _itemDistanceCalculator ??= ItemDistanceCalculator(); return widget.itemBuilder?.call( context, @@ -76,7 +85,8 @@ class _TDItemWidgetState extends State { maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( - fontWeight: _itemDistanceCalculator!.calculateFontWeight(context, distance), + fontWeight: + _itemDistanceCalculator!.calculateFontWeight(context, distance), fontSize: _itemDistanceCalculator!.calculateFont(context, distance), color: _itemDistanceCalculator!.calculateColor(context, distance), ), @@ -92,15 +102,14 @@ class _TDItemWidgetState extends State { } class ItemDistanceCalculator { - ItemDistanceCalculator(); Color calculateColor(BuildContext context, double distance) { /// 线性插值 if (distance < 0.5) { - return TDTheme.of(context).fontGyColor1; + return TDTheme.of(context).textColorPrimary; } else { - return TDTheme.of(context).fontGyColor4; + return TDTheme.of(context).textColorDisabled; } } diff --git a/tdesign-component/lib/src/components/picker/td_multi_picker.dart b/tdesign-component/lib/src/components/picker/td_multi_picker.dart index e9340f057..74c273606 100644 --- a/tdesign-component/lib/src/components/picker/td_multi_picker.dart +++ b/tdesign-component/lib/src/components/picker/td_multi_picker.dart @@ -19,13 +19,16 @@ class TDMultiPicker extends StatelessWidget { /// 选择器取消按钮回调 final MultiPickerCallback? onCancel; + /// todo 选择器数据改变时回调 + final MultiPickerCallback? onChange; + /// 选择器的数据源 final List> data; /// 选择器List的视窗高度,默认200 final double pickerHeight; - /// 选择器List视窗中item个数,pickerHeight / pickerItemCount即item高度 + /// 选择器List视窗中item个数,pickerHeight / pickerItemCount,即item高度 final int pickerItemCount; /// 自定义选择框样式 @@ -79,84 +82,95 @@ class TDMultiPicker extends StatelessWidget { /// 自定义item构建 final ItemBuilderType? itemBuilder; + /// 是否显示头部内容 + final bool header; + static const _pickerTitleHeight = 56.0; - const TDMultiPicker( - {required this.title, - required this.onConfirm, - this.onCancel, - required this.data, - required this.pickerHeight, - required this.pickerItemCount, - this.initialIndexes, - this.rightText, - this.leftText, - this.leftTextStyle, - this.rightTextStyle, - this.centerTextStyle, - this.titleHeight, - this.topPadding, - this.leftPadding, - this.rightPadding, - this.titleDividerColor, - this.backgroundColor, - this.topRadius, - this.padding, - this.itemDistanceCalculator, - this.customSelectWidget, - this.itemBuilder, - Key? key}) - : super(key: key); + const TDMultiPicker({ + this.title, + required this.onConfirm, + this.onCancel, + this.onChange, + required this.data, + this.pickerHeight = 200, + this.pickerItemCount = 5, + this.initialIndexes, + this.rightText, + this.leftText, + this.leftTextStyle, + this.rightTextStyle, + this.centerTextStyle, + this.titleHeight, + this.topPadding, + this.leftPadding, + this.rightPadding, + this.titleDividerColor, + this.backgroundColor, + this.topRadius, + this.padding, + this.itemDistanceCalculator, + this.customSelectWidget, + this.itemBuilder, + this.header = true, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { - var lines = data.length; - var indexes = initialIndexes ?? [for (var i = 0; i < lines; i++) 0]; - var controllers = [ - for (var i = 0; i < lines; i++) - FixedExtentScrollController(initialItem: indexes[i]) - ]; - var maxWidth = MediaQuery.of(context).size.width; + final dataLength = data.length; + + var indexes = initialIndexes ?? List.generate(dataLength, (i) => 0); + + var controllers = List.generate( + dataLength, + (i) => FixedExtentScrollController(initialItem: indexes[i]), + ); + + final maxWidth = MediaQuery.of(context).size.width; + return Container( width: maxWidth, - padding: padding ?? EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + padding: padding ?? + EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), decoration: BoxDecoration( - color: backgroundColor ?? TDTheme.of(context).whiteColor1, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(topRadius ?? TDTheme.of(context).radiusExtraLarge), - topRight: Radius.circular(topRadius ?? TDTheme.of(context).radiusExtraLarge), + color: backgroundColor ?? TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + topRadius ?? TDTheme.of(context).radiusExtraLarge), ), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - buildTitle(context, controllers), + if (header) _buildHeader(context, controllers), Stack( alignment: Alignment.center, children: [ Padding( - padding: const EdgeInsets.only(left: 16, right: 16), - child: customSelectWidget ?? Container( - height: 40, - decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, - borderRadius: BorderRadius.all(Radius.circular(TDTheme.of(context).radiusDefault)) - ), - ), + padding: const EdgeInsets.symmetric(horizontal: 16), + child: customSelectWidget ?? + Container( + height: 40, + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorSecondaryContainer, + borderRadius: BorderRadius.all( + Radius.circular(TDTheme.of(context).radiusDefault)), + ), + ), ), // 列表 Container( - padding: const EdgeInsets.only(left: 32, right: 32), - height: pickerHeight, - width: maxWidth, - child: Row( - children: [ - for (var i = 0; i < data.length; i++) - Expanded( - child: buildList(context, i, controllers), - ) - ], - )), + padding: const EdgeInsets.symmetric(horizontal: 32), + height: pickerHeight, + width: maxWidth, + child: Row( + children: List.generate( + dataLength, + (i) => Expanded(child: _buildList(context, i, controllers)), + ), + ), + ), // 蒙层 Positioned( top: 0, @@ -166,11 +180,14 @@ class TDMultiPicker extends StatelessWidget { height: _pickerTitleHeight, width: MediaQuery.of(context).size.width, decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [TDTheme.of(context).whiteColor1, TDTheme.of(context).whiteColor1.withOpacity(0)] - ) + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + TDTheme.of(context).bgColorContainer, + TDTheme.of(context).bgColorContainer.withOpacity(0) + ], + ), ), ), ), @@ -183,11 +200,14 @@ class TDMultiPicker extends StatelessWidget { height: _pickerTitleHeight, width: MediaQuery.of(context).size.width, decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.bottomCenter, - end: Alignment.topCenter, - colors: [TDTheme.of(context).whiteColor1, TDTheme.of(context).whiteColor1.withOpacity(0)] - ) + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + colors: [ + TDTheme.of(context).bgColorContainer, + TDTheme.of(context).bgColorContainer.withOpacity(0) + ], + ), ), ), ), @@ -199,33 +219,37 @@ class TDMultiPicker extends StatelessWidget { ); } - Widget buildTitle(BuildContext context, List controllers) { + Widget _buildHeader( + BuildContext context, + List controllers, + ) { + final padding = TDTheme.of(context).spacer16; + return Container( padding: EdgeInsets.only( - left: leftPadding ?? 16, - right: rightPadding ?? 16, - top: topPadding ?? 16, + left: leftPadding ?? padding, + right: rightPadding ?? padding, + top: topPadding ?? padding, ), decoration: BoxDecoration( border: Border( - bottom: BorderSide( - width: 0.5, - color: titleDividerColor ?? Colors.transparent, - ) + bottom: BorderSide( + width: 0.5, + color: titleDividerColor ?? Colors.transparent, + ), ), ), height: getTitleHeight(), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - // 左边按钮 + /// 左边按钮 GestureDetector( onTap: () { if (onCancel != null) { - onCancel!([ - for (var i = 0; i < controllers.length; i++) - controllers[i].selectedItem - ]); + onCancel!(controllers + .map((controller) => controller.selectedItem) + .toList()); } else { Navigator.of(context).pop(); } @@ -233,24 +257,22 @@ class TDMultiPicker extends StatelessWidget { behavior: HitTestBehavior.opaque, child: TDText( leftText ?? context.resource.cancel, - style: leftTextStyle?? TextStyle( - fontSize: TDTheme.of(context).fontBodyLarge!.size, - color: TDTheme.of(context).fontGyColor2 - ), + style: leftTextStyle ?? + TextStyle( + fontSize: TDTheme.of(context).fontBodyLarge!.size, + color: TDTheme.of(context).textColorSecondary), )), - // 中间title + /// 中间title Expanded( - child: title == null - ? Container() - : Center( + child: Center( child: TDText( - title, - style: centerTextStyle ?? TextStyle( - fontSize: TDTheme.of(context).fontTitleLarge!.size, - fontWeight: FontWeight.w600, - color: TDTheme.of(context).fontGyColor1 - ), + title ?? '', + style: centerTextStyle ?? + TextStyle( + fontSize: TDTheme.of(context).fontTitleLarge!.size, + fontWeight: FontWeight.w600, + color: TDTheme.of(context).textColorPrimary), ), ), ), @@ -259,19 +281,18 @@ class TDMultiPicker extends StatelessWidget { GestureDetector( onTap: () { if (onConfirm != null) { - onConfirm!([ - for (var i = 0; i < controllers.length; i++) - controllers[i].selectedItem - ]); + onConfirm!(controllers + .map((controller) => controller.selectedItem) + .toList()); } }, behavior: HitTestBehavior.opaque, child: TDText( rightText ?? context.resource.confirm, - style: rightTextStyle?? TextStyle( - fontSize: TDTheme.of(context).fontBodyLarge!.size, - color: TDTheme.of(context).brandNormalColor - ), + style: rightTextStyle ?? + TextStyle( + fontSize: TDTheme.of(context).fontBodyLarge!.size, + color: TDTheme.of(context).brandNormalColor), ), ), ], @@ -281,7 +302,11 @@ class TDMultiPicker extends StatelessWidget { double getTitleHeight() => titleHeight ?? _pickerTitleHeight; - Widget buildList(context, int position, List controllers) { + Widget _buildList( + context, + int position, + List controllers, + ) { var maxWidth = MediaQuery.of(context).size.width; return MediaQuery.removePadding( context: context, @@ -310,8 +335,7 @@ class TDMultiPicker extends StatelessWidget { itemDistanceCalculator: itemDistanceCalculator, fixedExtentScrollController: controllers[position], itemBuilder: itemBuilder, - ) - ); + )); })), )); } @@ -328,6 +352,9 @@ class TDMultiLinkedPicker extends StatefulWidget { /// 选择器取消按钮回调 final MultiPickerCallback? onCancel; + /// todo 选择器数据改变时回调 + final MultiPickerCallback? onChange; + /// 选中数据 final List selectedData; @@ -340,7 +367,7 @@ class TDMultiLinkedPicker extends StatefulWidget { /// 选择器List的视窗高度 final double pickerHeight; - /// 选择器List视窗中item个数,pickerHeight / pickerItemCount即item高度 + /// 选择器List视窗中item个数,pickerHeight / pickerItemCount,即item高度 final int pickerItemCount; /// 自定义选择框样式 @@ -394,10 +421,14 @@ class TDMultiLinkedPicker extends StatefulWidget { /// 是否保留相同选项 final bool keepSameSelection; + /// 是否显示头部内容 + final bool header; + const TDMultiLinkedPicker({ this.title, required this.onConfirm, this.onCancel, + this.onChange, required this.selectedData, required this.data, required this.columnNum, @@ -420,6 +451,7 @@ class TDMultiLinkedPicker extends StatefulWidget { this.itemDistanceCalculator, this.itemBuilder, this.keepSameSelection = false, + this.header = true, Key? key, }) : super(key: key); @@ -448,96 +480,99 @@ class _TDMultiLinkedPickerState extends State { @override Widget build(BuildContext context) { - var maxWidth = MediaQuery.of(context).size.width; + final maxWidth = MediaQuery.of(context).size.width; return Container( width: maxWidth, - padding: widget.padding ?? EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + padding: widget.padding ?? + EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), decoration: BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), - topRight: Radius.circular(widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + widget.topRadius ?? TDTheme.of(context).radiusExtraLarge), ), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ - buildTitle(context), - SizedBox( - height: widget.pickerHeight, - child: Stack( - alignment: Alignment.center, - children: [ - Padding(//选项 - padding: const EdgeInsets.only(left: 16, right: 16), - child: widget.customSelectWidget ?? Container( - height: 40, - decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, - borderRadius: BorderRadius.all(Radius.circular(TDTheme.of(context).radiusDefault)) + if (widget.header) _buildHeader(context), + Stack( + alignment: Alignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: widget.customSelectWidget ?? + Container( + height: 40, + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorSecondaryContainer, + borderRadius: BorderRadius.all(Radius.circular( + TDTheme.of(context).radiusDefault))), ), - ), - ), + ), - // 列表 - Container( - padding: const EdgeInsets.only(left: 32, right: 32), - height: pickerHeight, - width: maxWidth, - child: Row( - children: [ - for (var i = 0; i < widget.columnNum; i++) - Expanded( - child: buildList(context, i), - ) - ], - )), - // 蒙层 - Positioned( - top: 0, - child: IgnorePointer( - ignoring: true, - child: Container( - height: _pickerTitleHeight, - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [TDTheme.of(context).whiteColor1, TDTheme.of(context).whiteColor1.withOpacity(0)] - ) + // 列表 + Container( + padding: const EdgeInsets.symmetric(horizontal: 32), + height: pickerHeight, + width: maxWidth, + child: Row( + children: List.generate( + widget.columnNum, + (i) => Expanded(child: buildList(context, i)), + ), + )), + // 蒙层 + Positioned( + top: 0, + child: IgnorePointer( + ignoring: true, + child: Container( + height: _pickerTitleHeight, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + TDTheme.of(context).bgColorContainer, + TDTheme.of(context).bgColorContainer.withOpacity(0) + ], ), ), ), ), - Positioned( - bottom: 0, - child: IgnorePointer( - ignoring: true, - child: Container( - height: _pickerTitleHeight, - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.bottomCenter, - end: Alignment.topCenter, - colors: [TDTheme.of(context).whiteColor1, TDTheme.of(context).whiteColor1.withOpacity(0)] - ) + ), + Positioned( + bottom: 0, + child: IgnorePointer( + ignoring: true, + child: Container( + height: _pickerTitleHeight, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + colors: [ + TDTheme.of(context).bgColorContainer, + TDTheme.of(context).bgColorContainer.withOpacity(0) + ], ), ), ), - ) - ], - ), - ) + ), + ) + ], + ), ], ), ); } Widget buildList(context, int position) { + // position参数表示这个第几列 var maxWidth = MediaQuery.of(context).size.width; - return MediaQuery.removePadding( context: context, removeTop: true, @@ -564,17 +599,27 @@ class _TDMultiLinkedPickerState extends State { onSelectedItemChanged: (index) { if (index >= 0 && index < model.presentData[position].length) { setState(() { - model.refreshPresentDataAndController(position, index, false); + model.refreshPresentDataAndController( + position, + index, + false, + ); if (index >= model.presentData[position].length - 5 && model.hasMoreData[position]) { if (model.loadMoreData(position)) { // 延迟一下再刷新,避免连续setState - Future.delayed(Duration(milliseconds: 50), () { - if (mounted) setState(() {}); + Future.delayed(const Duration(milliseconds: 50), () { + if (mounted) { + setState(() {}); + } }); } } - pickerHeight = pickerHeight - Random().nextDouble() / 100000000; + + /// todo 通过随机数改变高度来触发UI刷新,这是hack式的解决方案!有待优化! + /// fix https://github.com/flutter/flutter/issues/22999 + pickerHeight = + pickerHeight - Random().nextDouble() / 100000000; }); } }, @@ -587,10 +632,16 @@ class _TDMultiLinkedPickerState extends State { return Container( alignment: Alignment.center, height: pickerHeight / widget.pickerItemCount, - child: Text('加载中...', style: TextStyle(color: Colors.grey)), + child: Text( + context.resource.loadingWithPoint, + style: TextStyle( + color: TDTheme.of(context).textColorPlaceholder, + ), + ), ); } - if (index < 0 || index >= model.presentData[position].length) { + if (index < 0 || + index >= model.presentData[position].length) { return Container(); } return Container( @@ -601,39 +652,41 @@ class _TDMultiLinkedPickerState extends State { colIndex: position, index: index, itemHeight: pickerHeight / widget.pickerItemCount, - content: model.presentData[position][index].toString(), - fixedExtentScrollController: model.controllers[position], + content: + model.presentData[position][index].toString(), + fixedExtentScrollController: + model.controllers[position], itemDistanceCalculator: widget.itemDistanceCalculator, itemBuilder: widget.itemBuilder, )); - } - ) - ), + })), ), ), ); } - Widget buildTitle(BuildContext context) { + Widget _buildHeader(BuildContext context) { + final padding = TDTheme.of(context).spacer16; + return Container( padding: EdgeInsets.only( - left: widget.leftPadding ?? 16, - right: widget.rightPadding ?? 16, - top: widget.topPadding ?? 16, + left: widget.leftPadding ?? padding, + right: widget.rightPadding ?? padding, + top: widget.topPadding ?? padding, ), decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - width: 0.5, - color: widget.titleDividerColor ?? Colors.transparent, - ) - ) + border: Border( + bottom: BorderSide( + width: 0.5, + color: widget.titleDividerColor ?? Colors.transparent, + ), + ), ), height: getTitleHeight() - 0.5, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - // 左边按钮 + /// 左边按钮 GestureDetector( onTap: () { if (widget.onCancel != null) { @@ -645,27 +698,29 @@ class _TDMultiLinkedPickerState extends State { behavior: HitTestBehavior.opaque, child: TDText( widget.leftText ?? context.resource.cancel, - style: widget.leftTextStyle ?? TextStyle( - fontSize: TDTheme.of(context).fontBodyLarge!.size, - color: TDTheme.of(context).fontGyColor2, - ), + style: widget.leftTextStyle ?? + TextStyle( + fontSize: TDTheme.of(context).fontBodyLarge!.size, + color: TDTheme.of(context).textColorSecondary, + ), )), - // 中间title + + /// 中间title Expanded( - child: widget.title == null - ? Container() - : Center( + child: Center( child: TDText( - widget.title, - style: widget.centerTextStyle ?? TextStyle( - fontSize: TDTheme.of(context).fontTitleLarge!.size, - fontWeight: FontWeight.w700, - color: TDTheme.of(context).fontGyColor1 - ), + widget.title ?? '', + style: widget.centerTextStyle ?? + TextStyle( + fontSize: TDTheme.of(context).fontTitleLarge!.size, + fontWeight: FontWeight.w700, + color: TDTheme.of(context).textColorPrimary, + ), ), ), ), - // 右边按钮 + + /// 右边按钮 GestureDetector( onTap: () { if (widget.onConfirm != null) { @@ -675,10 +730,11 @@ class _TDMultiLinkedPickerState extends State { behavior: HitTestBehavior.opaque, child: TDText( widget.rightText ?? context.resource.confirm, - style: widget.rightTextStyle ?? TextStyle( - fontSize: TDTheme.of(context).fontBodyLarge!.size, - color: TDTheme.of(context).brandNormalColor, - ), + style: widget.rightTextStyle ?? + TextStyle( + fontSize: TDTheme.of(context).fontBodyLarge!.size, + color: TDTheme.of(context).brandNormalColor, + ), ), ), ], @@ -713,13 +769,16 @@ class MultiLinkedPickerModel { /// 是否保留相同选项 bool keepSameSelection = false; - // 添加一个常量定义每页加载数量 + /// 添加一个常量定义每页加载数量 static const int pageSize = 10; - // 每列的当前页码 + + /// 每列的当前页码 late List currentPages; - // 每列是否还有更多数据 + + /// 每列是否还有更多数据 late List hasMoreData; - // 每列的总数据量 + + /// 每列的总数据量 late List totalCounts; MultiLinkedPickerModel({ @@ -737,7 +796,7 @@ class MultiLinkedPickerModel { if (i >= initialData.length) { selectedData.add(''); } else { - selectedData.add(initialData[i]); + selectedData.add(initialData[i]?.toString() ?? ''); } selectedIndexes.add(0); } @@ -753,7 +812,7 @@ class MultiLinkedPickerModel { } List currentLevelData; if (i == 0) { - currentLevelData = _getNextLevelDataPaginated(0,0); + currentLevelData = _getNextLevelDataPaginated(0, 0); if (currentLevelData.isEmpty) { currentLevelData = [placeData]; } @@ -761,24 +820,24 @@ class MultiLinkedPickerModel { currentLevelData = _getNextLevelDataPaginated(i, 0); } // 处理选中项 - int selectedIndex = currentLevelData.indexOf(selectedData[i]); + var selectedIndex = currentLevelData.indexOf(selectedData[i]); if (selectedIndex < 0) { - selectedData[i] = currentLevelData.isNotEmpty ? currentLevelData.first : placeData; + selectedData[i] = + currentLevelData.isNotEmpty ? currentLevelData.first : placeData; selectedIndex = 0; } selectedIndexes[i] = selectedIndex; presentData[i] = currentLevelData; // 创建控制器 controllers.add(FixedExtentScrollController( - initialItem: selectedIndex.clamp(0, currentLevelData.length - 1) - )); + initialItem: selectedIndex.clamp(0, currentLevelData.length - 1))); } } List _getNextLevelDataPaginated(int level, int page) { try { dynamic currentData = data; - for (int i = 0; i < level; i++) { + for (var i = 0; i < level; i++) { if (currentData is Map && currentData.containsKey(selectedData[i])) { currentData = currentData[selectedData[i]]; } else { @@ -796,8 +855,12 @@ class MultiLinkedPickerModel { totalCounts[level] = allData.length; int start = page * pageSize; int end = start + pageSize; - if (start >= allData.length) return []; - if (end > allData.length) end = allData.length; + if (start >= allData.length) { + return []; + } + if (end > allData.length) { + end = allData.length; + } hasMoreData[level] = end < allData.length; return allData.sublist(start, end); } catch (e) { @@ -806,11 +869,13 @@ class MultiLinkedPickerModel { } bool loadMoreData(int columnIndex) { - if (columnIndex >= columnNum || !hasMoreData[columnIndex]) return false; + if (columnIndex >= columnNum || !hasMoreData[columnIndex]) { + return false; + } List newData; int nextPage = currentPages[columnIndex] + 1; if (columnIndex == 0) { - newData = _getNextLevelDataPaginated(0,nextPage); + newData = _getNextLevelDataPaginated(0, nextPage); } else { newData = _getNextLevelDataPaginated(columnIndex, nextPage); } @@ -827,7 +892,11 @@ class MultiLinkedPickerModel { /// [position] 变动的列 /// [selectedIndex] 对应选中的index /// [jump] 是否需要jumpToItem - void refreshPresentDataAndController(int position, int selectedIndex, bool jump) { + void refreshPresentDataAndController( + int position, + int selectedIndex, + bool jump, + ) { // 严格的边界检查 if (position >= presentData.length || selectedIndex >= presentData[position].length || @@ -836,18 +905,21 @@ class MultiLinkedPickerModel { } selectedIndex = selectedIndex.clamp(0, presentData[position].length - 1); var selectValue = presentData[position][selectedIndex]; + // 更新选中的数据 selectedData[position] = selectValue; selectedIndexes[position] = selectedIndex; if (jump) { controllers[position].jumpToItem(selectedIndex); } // 检查是否需要预加载更多数据 - if (selectedIndex >= presentData[position].length - 5 && hasMoreData[position]) { + if (selectedIndex >= presentData[position].length - 5 && + hasMoreData[position]) { loadMoreData(position); } if (position < columnNum - 1) { List nextColumnData; - if (presentData[position].length == 1 && presentData[position].first == placeData) { + if (presentData[position].length == 1 && + presentData[position].first == placeData) { nextColumnData = [placeData]; } else { nextColumnData = _getNextLevelDataPaginated(position + 1, 0); diff --git a/tdesign-component/lib/src/components/picker/td_picker.dart b/tdesign-component/lib/src/components/picker/td_picker.dart index 5f381ec7e..e2d997615 100644 --- a/tdesign-component/lib/src/components/picker/td_picker.dart +++ b/tdesign-component/lib/src/components/picker/td_picker.dart @@ -3,172 +3,237 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; class TDPicker { - /// 显示时间选择器 - static void showDatePicker(context, - {required String title, - required DatePickerCallback? onConfirm, - DatePickerCallback? onCancel, - bool useYear = true, - bool useMonth = true, - bool useDay = true, - bool useHour = false, - bool useMinute = false, - bool useSecond = false, - bool useWeekDay = false, - Color? barrierColor, - List dateStart = const [1970, 1, 1], - List? dateEnd, - List? initialDate, - String? rightText, - String? leftText, - TextStyle? leftTextStyle, - TextStyle? centerTextStyle, - TextStyle? rightTextStyle, - Color? titleDividerColor, - Widget? customSelectWidget, - Duration duration = const Duration(milliseconds: 100), - double pickerHeight = 200, - bool isTimeUnit=true, - Function(int wheelIndex, int index)? onSelectedItemChanged, - int pickerItemCount = 5, - List Function(DateTypeKey key, List nums)? filterItems, - ItemBuilderType? itemBuilder}) { + static void showDatePicker( + context, { + String? title, + double? titleHeight, + Color? titleDividerColor, + required DatePickerCallback? onConfirm, + DatePickerCallback? onCancel, + DatePickerCallback? onChange, + Function(int wheelIndex, int index)? onSelectedItemChanged, + String? leftText, + TextStyle? leftTextStyle, + TextStyle? centerTextStyle, + String? rightText, + TextStyle? rightTextStyle, + EdgeInsets? padding, + double? leftPadding, + double? topPadding, + double? rightPadding, + double? topRadius, + Color? backgroundColor, + Widget? customSelectWidget, + // 通过弹窗方式打开必须展示header + // bool header = true, + // ItemDistanceCalculator? itemDistanceCalculator, + /// DatePickerModel参数 + bool useYear = true, + bool useMonth = true, + bool useDay = true, + bool useHour = false, + bool useMinute = false, + bool useSecond = false, + bool useWeekDay = false, + List dateStart = const [1970, 1, 1], + List? dateEnd, + List? initialDate, + List Function(DateTypeKey key, List nums)? filterItems, + double pickerHeight = 200, + int pickerItemCount = 5, + bool isTimeUnit = true, + ItemBuilderType? itemBuilder, + Color? barrierColor, + + /// todo 未传参 + Duration duration = const Duration(milliseconds: 100), + }) { if (dateEnd == null || initialDate == null) { - var now = DateTime.now(); + final now = DateTime.now(); // 如果未指定结束时间,则取当前时间 dateEnd ??= [now.year, now.month, now.day]; initialDate ??= [now.year, now.month, now.day]; } showModalBottomSheet( - context: context, - backgroundColor: Colors.transparent, - barrierColor: barrierColor ?? TDTheme.of(context).fontGyColor2.withOpacity(0.6), - enableDrag:false, - builder: (context) { - return TDDatePicker( - title: title, - onConfirm: onConfirm, - onCancel: onCancel, - rightText: rightText, - leftText: leftText, - leftTextStyle: leftTextStyle, - centerTextStyle: centerTextStyle, - rightTextStyle: rightTextStyle, - titleDividerColor: titleDividerColor, - isTimeUnit: isTimeUnit, - customSelectWidget: customSelectWidget, - model: DatePickerModel( - useYear: useYear, - useMonth: useMonth, - useDay: useDay, - useWeekDay: useWeekDay, - useHour: useHour, - useMinute: useMinute, - useSecond: useSecond, - dateStart: dateStart, - dateEnd: dateEnd!, - dateInitial: initialDate, - filterItems: filterItems, - ), - pickerHeight: pickerHeight, - pickerItemCount: pickerItemCount, - onSelectedItemChanged:onSelectedItemChanged, - itemBuilder: itemBuilder); - }); + context: context, + backgroundColor: Colors.transparent, + barrierColor: barrierColor, + enableDrag: false, + builder: (context) { + return TDDatePicker( + title: title, + titleHeight: titleHeight, + titleDividerColor: titleDividerColor, + onConfirm: onConfirm, + onCancel: onCancel, + onChange: onChange, + onSelectedItemChanged: onSelectedItemChanged, + leftText: leftText, + leftTextStyle: leftTextStyle, + centerTextStyle: centerTextStyle, + rightText: rightText, + rightTextStyle: rightTextStyle, + padding: padding, + leftPadding: leftPadding, + topPadding: topPadding, + rightPadding: rightPadding, + topRadius: topRadius, + backgroundColor: backgroundColor, + customSelectWidget: customSelectWidget, + // header: header, + model: DatePickerModel( + useYear: useYear, + useMonth: useMonth, + useDay: useDay, + useHour: useHour, + useMinute: useMinute, + useSecond: useSecond, + useWeekDay: useWeekDay, + dateStart: dateStart, + dateEnd: dateEnd!, + dateInitial: initialDate, + filterItems: filterItems, + ), + pickerHeight: pickerHeight, + pickerItemCount: pickerItemCount, + isTimeUnit: isTimeUnit, + itemBuilder: itemBuilder, + ); + }, + ); } /// 显示多级选择器 - static void showMultiPicker(context, - {String? title, - required MultiPickerCallback? onConfirm, - MultiPickerCallback? onCancel, - required List> data, - List? initialIndexes, - Duration duration = const Duration(milliseconds: 100), - Color? barrierColor, - double pickerHeight = 200, - String? rightText, - String? leftText, - TextStyle? leftTextStyle, - TextStyle? centerTextStyle, - TextStyle? rightTextStyle, - Color? titleDividerColor, - double? topPadding, - int pickerItemCount = 5, - Widget? customSelectWidget, - ItemBuilderType? itemBuilder}) { + static void showMultiPicker( + context, { + String? title, + required MultiPickerCallback? onConfirm, + MultiPickerCallback? onCancel, + required List> data, + double pickerHeight = 200, + int pickerItemCount = 5, + List? initialIndexes, + String? rightText, + String? leftText, + TextStyle? leftTextStyle, + TextStyle? centerTextStyle, + TextStyle? rightTextStyle, + double? titleHeight, + double? topPadding, + double? leftPadding, + double? rightPadding, + Color? titleDividerColor, + Color? backgroundColor, + double? topRadius, + EdgeInsets? padding, + Widget? customSelectWidget, + ItemBuilderType? itemBuilder, + + /// todo 未传参 + Duration duration = const Duration(milliseconds: 100), + Color? barrierColor, + }) { showModalBottomSheet( - context: context, - backgroundColor: Colors.transparent, - barrierColor: barrierColor ?? TDTheme.of(context).fontGyColor2.withOpacity(0.6), - builder: (context) { - return TDMultiPicker( - title: title, - onConfirm: onConfirm, - onCancel: onCancel, - data: data, - rightText: rightText, - leftText: leftText, - leftTextStyle: leftTextStyle, - centerTextStyle: centerTextStyle, - rightTextStyle: rightTextStyle, - initialIndexes: initialIndexes, - pickerHeight: pickerHeight, - pickerItemCount: pickerItemCount, - titleDividerColor: titleDividerColor, - topPadding: topPadding, - itemBuilder: itemBuilder, - customSelectWidget: customSelectWidget, - ); - }); + context: context, + backgroundColor: Colors.transparent, + barrierColor: barrierColor, + builder: (context) { + return TDMultiPicker( + title: title, + onConfirm: onConfirm, + onCancel: onCancel, + data: data, + pickerHeight: pickerHeight, + pickerItemCount: pickerItemCount, + initialIndexes: initialIndexes, + rightText: rightText, + leftText: leftText, + leftTextStyle: leftTextStyle, + rightTextStyle: rightTextStyle, + centerTextStyle: centerTextStyle, + titleHeight: titleHeight, + topPadding: topPadding, + leftPadding: leftPadding, + rightPadding: rightPadding, + titleDividerColor: titleDividerColor, + backgroundColor: backgroundColor, + topRadius: topRadius, + padding: padding, + itemBuilder: itemBuilder, + customSelectWidget: customSelectWidget, + ); + }, + ); } /// 显示多级联动选择器 - static void showMultiLinkedPicker(context, - {String? title, - required MultiPickerCallback? onConfirm, - MultiPickerCallback? onCancel, - required Map data, - required int columnNum, - required List initialData, - Duration duration = const Duration(milliseconds: 100), - Color? barrierColor, - String? rightText, - String? leftText, - TextStyle? leftTextStyle, - TextStyle? centerTextStyle, - TextStyle? rightTextStyle, - double pickerHeight = 200, - Color? titleDividerColor, - Widget? customSelectWidget, - double? topPadding, - bool keepSameSelection = false, - int pickerItemCount = 5}) { + // required this.selectedData, + static void showMultiLinkedPicker( + context, { + String? title, + required MultiPickerCallback? onConfirm, + MultiPickerCallback? onCancel, + required List initialData, + required Map data, + required int columnNum, + double pickerHeight = 200, + int pickerItemCount = 5, + Widget? customSelectWidget, + String? rightText, + String? leftText, + TextStyle? leftTextStyle, + TextStyle? centerTextStyle, + TextStyle? rightTextStyle, + double? titleHeight, + double? topPadding, + double? leftPadding, + double? rightPadding, + Color? titleDividerColor, + Color? backgroundColor, + double? topRadius, + EdgeInsets? padding, + ItemBuilderType? itemBuilder, + // ItemDistanceCalculator? itemDistanceCalculator, + bool keepSameSelection = false, + Color? barrierColor, + + /// todo 未传参 + Duration duration = const Duration(milliseconds: 100), + }) { showModalBottomSheet( - context: context, - backgroundColor: Colors.transparent, - barrierColor: barrierColor ?? TDTheme.of(context).fontGyColor2.withOpacity(0.6), - builder: (context) { - return TDMultiLinkedPicker( - title: title, - onConfirm: onConfirm, - onCancel: onCancel, - data: data, - rightText: rightText, - leftText: leftText, - leftTextStyle: leftTextStyle, - centerTextStyle: centerTextStyle, - rightTextStyle: rightTextStyle, - pickerHeight: pickerHeight, - pickerItemCount: pickerItemCount, - columnNum: columnNum, - selectedData: initialData, - titleDividerColor: titleDividerColor, - topPadding: topPadding, - customSelectWidget: customSelectWidget, - keepSameSelection: keepSameSelection, - ); - }); + context: context, + backgroundColor: Colors.transparent, + barrierColor: barrierColor, + builder: (context) { + return TDMultiLinkedPicker( + title: title, + onConfirm: onConfirm, + onCancel: onCancel, + selectedData: initialData, + data: data, + columnNum: columnNum, + pickerHeight: pickerHeight, + pickerItemCount: pickerItemCount, + rightText: rightText, + leftText: leftText, + leftTextStyle: leftTextStyle, + rightTextStyle: rightTextStyle, + centerTextStyle: centerTextStyle, + titleHeight: titleHeight, + topPadding: topPadding, + leftPadding: leftPadding, + rightPadding: rightPadding, + titleDividerColor: titleDividerColor, + backgroundColor: backgroundColor, + topRadius: topRadius, + padding: padding, + itemBuilder: itemBuilder, + customSelectWidget: customSelectWidget, + keepSameSelection: keepSameSelection, + // itemDistanceCalculator: itemDistanceCalculator, + ); + }, + ); } } diff --git a/tdesign-component/lib/src/components/popover/td_popover.dart b/tdesign-component/lib/src/components/popover/td_popover.dart index bd73cc35e..83305a6b9 100644 --- a/tdesign-component/lib/src/components/popover/td_popover.dart +++ b/tdesign-component/lib/src/components/popover/td_popover.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; class TDPopover { - static Future showPopover({ required BuildContext context, String? content, @@ -45,4 +44,4 @@ class TDPopover { ), ); } -} \ No newline at end of file +} diff --git a/tdesign-component/lib/src/components/popover/td_popover_widget.dart b/tdesign-component/lib/src/components/popover/td_popover_widget.dart index 7fc165eb6..540417c55 100644 --- a/tdesign-component/lib/src/components/popover/td_popover_widget.dart +++ b/tdesign-component/lib/src/components/popover/td_popover_widget.dart @@ -78,7 +78,7 @@ class TDPopoverWidget extends StatefulWidget { this.height, this.onTap, this.onLongTap, - this.radius + this.radius, }); /// 上下文 @@ -136,12 +136,14 @@ class _TDPopoverWidgetState extends State { void initState() { super.initState(); _initTheme(); - if(widget.contentWidget != null) { - if(widget.width == null) { - throw FlutterError('width must not be null when contentWidget is not null'); + if (widget.contentWidget != null) { + if (widget.width == null) { + throw FlutterError( + 'width must not be null when contentWidget is not null'); } - if(widget.height == null) { - throw FlutterError('height must not be null when contentWidget is not null'); + if (widget.height == null) { + throw FlutterError( + 'height must not be null when contentWidget is not null'); } } } @@ -149,28 +151,78 @@ class _TDPopoverWidgetState extends State { /// 绘制箭头 Widget _drawArrow() { var border = Border( - right: BorderSide(width: widget.arrowSize, color: Colors.transparent, style: BorderStyle.solid), - bottom: BorderSide(width: widget.arrowSize, color: _backgroundColor, style: BorderStyle.solid), - left: BorderSide(width: widget.arrowSize, color: Colors.transparent, style: BorderStyle.solid) - ); - if(widget.placement == TDPopoverPlacement.bottom || widget.placement == TDPopoverPlacement.bottomLeft || widget.placement == TDPopoverPlacement.bottomRight) { + right: BorderSide( + width: widget.arrowSize, + color: Colors.transparent, + style: BorderStyle.solid, + ), + bottom: BorderSide( + width: widget.arrowSize, + color: _backgroundColor, + style: BorderStyle.solid, + ), + left: BorderSide( + width: widget.arrowSize, + color: Colors.transparent, + style: BorderStyle.solid, + )); + if (widget.placement == TDPopoverPlacement.bottom || + widget.placement == TDPopoverPlacement.bottomLeft || + widget.placement == TDPopoverPlacement.bottomRight) { border = Border( - top: BorderSide(width: widget.arrowSize, color: _backgroundColor, style: BorderStyle.solid), - right: BorderSide(width: widget.arrowSize, color: Colors.transparent, style: BorderStyle.solid), - left: BorderSide(width: widget.arrowSize, color: Colors.transparent, style: BorderStyle.solid) - ); - } else if(widget.placement == TDPopoverPlacement.left || widget.placement == TDPopoverPlacement.leftTop || widget.placement == TDPopoverPlacement.leftBottom) { + top: BorderSide( + width: widget.arrowSize, + color: _backgroundColor, + style: BorderStyle.solid, + ), + right: BorderSide( + width: widget.arrowSize, + color: Colors.transparent, + style: BorderStyle.solid, + ), + left: BorderSide( + width: widget.arrowSize, + color: Colors.transparent, + style: BorderStyle.solid, + )); + } else if (widget.placement == TDPopoverPlacement.left || + widget.placement == TDPopoverPlacement.leftTop || + widget.placement == TDPopoverPlacement.leftBottom) { border = Border( - top: BorderSide(width: widget.arrowSize, color: Colors.transparent, style: BorderStyle.solid), - bottom: BorderSide(width: widget.arrowSize, color: Colors.transparent, style: BorderStyle.solid), - right: BorderSide(width: widget.arrowSize, color: _backgroundColor, style: BorderStyle.solid) - ); - } else if(widget.placement == TDPopoverPlacement.right || widget.placement == TDPopoverPlacement.rightTop || widget.placement == TDPopoverPlacement.rightBottom) { + top: BorderSide( + width: widget.arrowSize, + color: Colors.transparent, + style: BorderStyle.solid, + ), + bottom: BorderSide( + width: widget.arrowSize, + color: Colors.transparent, + style: BorderStyle.solid, + ), + right: BorderSide( + width: widget.arrowSize, + color: _backgroundColor, + style: BorderStyle.solid, + )); + } else if (widget.placement == TDPopoverPlacement.right || + widget.placement == TDPopoverPlacement.rightTop || + widget.placement == TDPopoverPlacement.rightBottom) { border = Border( - top: BorderSide(width: widget.arrowSize, color: Colors.transparent, style: BorderStyle.solid), - bottom: BorderSide(width: widget.arrowSize, color: Colors.transparent, style: BorderStyle.solid), - left: BorderSide(width: widget.arrowSize, color: _backgroundColor, style: BorderStyle.solid) - ); + top: BorderSide( + width: widget.arrowSize, + color: Colors.transparent, + style: BorderStyle.solid, + ), + bottom: BorderSide( + width: widget.arrowSize, + color: Colors.transparent, + style: BorderStyle.solid, + ), + left: BorderSide( + width: widget.arrowSize, + color: _backgroundColor, + style: BorderStyle.solid, + )); } return Container( width: 0, @@ -202,7 +254,7 @@ class _TDPopoverWidgetState extends State { _color = TDTheme.of(widget.context).grayColor14; _backgroundColor = TDTheme.of(widget.context).whiteColor1; break; - default : + default: _color = TDTheme.of(widget.context).whiteColor1; _backgroundColor = TDTheme.of(widget.context).grayColor14; break; @@ -227,7 +279,9 @@ class _TDPopoverWidgetState extends State { var dy = widgetLocalToGlobal?.dy ?? 0; var arrowSize = widget.showArrow ?? false ? widget.arrowSize : 0; var contentSize = _getContentSize(); - var popoverHeight = widget.height ?? (widget.padding != null ? widget.padding!.vertical : 24) + (widget.height ?? contentSize.height); + var popoverHeight = widget.height ?? + (widget.padding != null ? widget.padding!.vertical : 24) + + (widget.height ?? contentSize.height); switch (widget.placement) { case TDPopoverPlacement.bottomLeft: case TDPopoverPlacement.bottom: @@ -252,7 +306,9 @@ class _TDPopoverWidgetState extends State { var widgetBounds = _getWidgetBounds(widget.context); var widgetWidth = widgetBounds?.width ?? 0; var contentSize = _getContentSize(); - var popoverWidth = widget.width ?? (widget.padding != null ? widget.padding!.horizontal : 24) + contentSize.width; + var popoverWidth = widget.width ?? + (widget.padding != null ? widget.padding!.horizontal : 24) + + contentSize.width; var dx = widgetLocalToGlobal?.dx ?? 0; switch (widget.placement) { case TDPopoverPlacement.topLeft: @@ -260,58 +316,67 @@ class _TDPopoverWidgetState extends State { return dx; case TDPopoverPlacement.topRight: case TDPopoverPlacement.bottomRight: - return dx + widgetWidth - popoverWidth; + return dx + widgetWidth - popoverWidth; case TDPopoverPlacement.rightTop: case TDPopoverPlacement.right: case TDPopoverPlacement.rightBottom: - return dx + widgetWidth + widget.offset + 8; + return dx + widgetWidth + widget.offset; case TDPopoverPlacement.leftTop: case TDPopoverPlacement.left: case TDPopoverPlacement.leftBottom: - return dx - popoverWidth - widget.arrowSize - widget.offset - 8; - default : + return dx - popoverWidth - widget.arrowSize - widget.offset; + default: return dx - (popoverWidth - widgetWidth) / 2; } } /// 获取箭头Widget + /// todo 通过 CustomPainter 绘制箭头进行优化 Widget _getArrowWidget() { var margin = EdgeInsets.only(top: widget.arrowSize); switch (widget.placement) { case TDPopoverPlacement.topLeft: - margin = EdgeInsets.only(top: widget.arrowSize, left: widget.arrowSize + 12); - break; + margin = + EdgeInsets.only(top: widget.arrowSize, left: widget.arrowSize + 12); + break; case TDPopoverPlacement.topRight: - margin = EdgeInsets.only(top: widget.arrowSize, right: widget.arrowSize + 12); - break; + margin = EdgeInsets.only( + top: widget.arrowSize, right: widget.arrowSize + 12); + break; case TDPopoverPlacement.bottomLeft: - margin = EdgeInsets.only(bottom: widget.arrowSize, left: widget.arrowSize + 12); - break; + margin = EdgeInsets.only( + bottom: widget.arrowSize, left: widget.arrowSize + 12); + break; case TDPopoverPlacement.bottom: - margin = EdgeInsets.only(bottom: widget.arrowSize); - break; + margin = EdgeInsets.only(bottom: widget.arrowSize); + break; case TDPopoverPlacement.bottomRight: - margin = EdgeInsets.only(bottom: widget.arrowSize, right: widget.arrowSize + 12); - break; + margin = EdgeInsets.only( + bottom: widget.arrowSize, right: widget.arrowSize + 12); + break; case TDPopoverPlacement.rightTop: - margin = EdgeInsets.only(top: widget.arrowSize + 6, right: widget.arrowSize); + margin = + EdgeInsets.only(top: widget.arrowSize + 6, right: widget.arrowSize); break; case TDPopoverPlacement.right: - margin = EdgeInsets.only(right: widget.arrowSize); - break; + margin = EdgeInsets.only(right: widget.arrowSize); + break; case TDPopoverPlacement.rightBottom: - margin = EdgeInsets.only(bottom: widget.arrowSize + 6, right: widget.arrowSize); - break; + margin = EdgeInsets.only( + bottom: widget.arrowSize + 6, right: widget.arrowSize); + break; case TDPopoverPlacement.leftTop: - margin = EdgeInsets.only(top: widget.arrowSize + 6, left: widget.arrowSize); + margin = + EdgeInsets.only(top: widget.arrowSize + 6, left: widget.arrowSize); break; case TDPopoverPlacement.left: margin = EdgeInsets.only(left: widget.arrowSize); break; case TDPopoverPlacement.leftBottom: - margin = EdgeInsets.only(bottom: widget.arrowSize + 6, left: widget.arrowSize); + margin = EdgeInsets.only( + bottom: widget.arrowSize + 6, left: widget.arrowSize); break; - default : + default: margin = EdgeInsets.only(top: widget.arrowSize); } return Container( @@ -322,7 +387,7 @@ class _TDPopoverWidgetState extends State { /// 获取弹出内容大小 Size _getContentSize() { - if(widget.contentWidget != null) { + if (widget.contentWidget != null) { return Size(widget.width!, widget.height!); } return _getTextSize(); @@ -342,36 +407,54 @@ class _TDPopoverWidgetState extends State { ), locale: Localizations.localeOf(context), textDirection: TextDirection.ltr, - )..layout(maxWidth: (widget.width ?? 300) - (widget.padding != null ? widget.padding!.horizontal : 24)); + )..layout( + maxWidth: (widget.width ?? 300) - + (widget.padding != null ? widget.padding!.horizontal : 24)); return textPainter.size; } + Widget _getContainerWidget() { + return Container( + width: widget.width, + height: widget.height, + padding: widget.padding ?? const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: widget.radius ?? + BorderRadius.circular(TDTheme.of(context).radiusDefault), + color: _backgroundColor, + boxShadow: const [ + BoxShadow( + color: Color(0x0d000000), + offset: Offset(0, 6), + blurRadius: 30, + spreadRadius: 5), + BoxShadow( + color: Color(0x0a000000), + offset: Offset(0, 16), + blurRadius: 24, + spreadRadius: 2), + BoxShadow( + color: Color(0x14000000), + offset: Offset(0, 8), + blurRadius: 10, + spreadRadius: -5), + ]), + child: widget.contentWidget != null + ? widget.contentWidget! + : TDText(widget.content, + style: TextStyle( + color: _color, + letterSpacing: 0, + fontSize: 16, + height: 1.5, + )), + ); + } + /// 获取子Widget Widget _getChild() { var children = [ - Container( - width: widget.width, - height: widget.height, - padding: widget.padding ?? const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: widget.radius ?? BorderRadius.circular(6), - color: _backgroundColor, - boxShadow: const [ - BoxShadow(color: Color(0x0d000000), offset: Offset(0, 6), blurRadius: 30, spreadRadius: 5), - BoxShadow(color: Color(0x0a000000), offset: Offset(0, 16), blurRadius: 24, spreadRadius: 2), - BoxShadow(color: Color(0x14000000), offset: Offset(0, 8), blurRadius: 10, spreadRadius: -5), - ] - ), - child: widget.contentWidget != null ? widget.contentWidget! : TDText( - widget.content, - style: TextStyle( - color: _color, - letterSpacing: 0, - fontSize: 16, - height: 1.5, - ) - ), - ), + _getContainerWidget(), Visibility( visible: widget.showArrow ?? false, child: _getArrowWidget(), @@ -390,37 +473,17 @@ class _TDPopoverWidgetState extends State { case TDPopoverPlacement.right: case TDPopoverPlacement.rightTop: case TDPopoverPlacement.rightBottom: + /// 反转内容和箭头 children = [ Visibility( visible: widget.showArrow ?? false, - child: Container( - child: _getArrowWidget(), - ), - ), - Container( - padding: widget.padding ?? const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6), - color: _backgroundColor, - boxShadow: [ - BoxShadow(color: TDTheme.of(context).grayColor7, offset: const Offset(6, 3), blurRadius: 6) - ] - ), - child: widget.contentWidget != null ? widget.contentWidget! : TDText( - widget.content, - style: TextStyle( - color: _color, - letterSpacing: 0, - fontSize: 16, - height: 1.5, - overflow: TextOverflow.ellipsis, - ) - ), + child: _getArrowWidget(), ), + _getContainerWidget(), ]; break; - default : + default: direction = VerticalDirection.down; break; } @@ -433,7 +496,7 @@ class _TDPopoverWidgetState extends State { break; case TDPopoverPlacement.topRight: case TDPopoverPlacement.bottomRight: - axis = CrossAxisAlignment.end; + axis = CrossAxisAlignment.end; break; case TDPopoverPlacement.rightTop: case TDPopoverPlacement.leftTop: @@ -443,22 +506,23 @@ class _TDPopoverWidgetState extends State { case TDPopoverPlacement.leftBottom: axis = CrossAxisAlignment.end; break; - default : + default: axis = CrossAxisAlignment.center; } /// 横向布局 - if(widget.placement == TDPopoverPlacement.right || - widget.placement == TDPopoverPlacement.rightTop || - widget.placement == TDPopoverPlacement.rightBottom || - widget.placement == TDPopoverPlacement.left || - widget.placement == TDPopoverPlacement.leftBottom || - widget.placement == TDPopoverPlacement.leftTop) { + if (widget.placement == TDPopoverPlacement.right || + widget.placement == TDPopoverPlacement.rightTop || + widget.placement == TDPopoverPlacement.rightBottom || + widget.placement == TDPopoverPlacement.left || + widget.placement == TDPopoverPlacement.leftBottom || + widget.placement == TDPopoverPlacement.leftTop) { return Row( crossAxisAlignment: axis, children: children, ); } + /// 纵向布局 return Column( crossAxisAlignment: axis, @@ -483,4 +547,4 @@ class _TDPopoverWidgetState extends State { ], ); } -} \ No newline at end of file +} diff --git a/tdesign-component/lib/src/components/popup/td_popup_panel.dart b/tdesign-component/lib/src/components/popup/td_popup_panel.dart index fcf27128d..1ba6614dd 100644 --- a/tdesign-component/lib/src/components/popup/td_popup_panel.dart +++ b/tdesign-component/lib/src/components/popup/td_popup_panel.dart @@ -22,18 +22,25 @@ abstract class TDPopupBasePanel extends StatefulWidget { /// 子控件 final Widget child; + /// 标题 final String? title; + /// 标题颜色 final Color? titleColor; + /// 背景颜色 final Color? backgroundColor; + /// 圆角 final double? radius; + /// 边缘是否可拖动 final bool draggable; + /// 最大高度比例 final double maxHeightRatio; + /// 最小高度比例 final double minHeightRatio; @@ -73,9 +80,13 @@ abstract class _TDPopupBaseState extends State void _measureChildHeight() { // 获取子组件渲染对象 final context = _childKey.currentContext; - if (context == null) return; + if (context == null) { + return; + } final renderBox = context.findRenderObject() as RenderBox?; - if (renderBox == null || !renderBox.hasSize) return; + if (renderBox == null || !renderBox.hasSize) { + return; + } final screenHeight = MediaQuery.of(context).size.height; final childHeight = renderBox.size.height; @@ -96,16 +107,17 @@ abstract class _TDPopupBaseState extends State // 初始化当前高度 _currentHeight = baseHeight.clamp(_minHeight, _maxHeight); // 同步动画控制器 - _controller.value = (_currentHeight - _minHeight) / - (_maxHeight - _minHeight).clamp(0.1, 1.0); + _controller.value = (_currentHeight - _minHeight) / (_maxHeight - _minHeight).clamp(0.1, 1.0); } void _updateHeight() => setState(() { - _currentHeight = _minHeight + (_maxHeight - _minHeight) * _controller.value; - }); + _currentHeight = _minHeight + (_maxHeight - _minHeight) * _controller.value; + }); void _toggleFullscreen(bool fullscreen) { - if (_isAnimating || _isFullscreen == fullscreen) return; + if (_isAnimating || _isFullscreen == fullscreen) { + return; + } setState(() { _isFullscreen = fullscreen; @@ -122,18 +134,25 @@ abstract class _TDPopupBaseState extends State } void _animateTo(double height) { - if (_isAnimating) return; + if (_isAnimating) { + return; + } _isAnimating = true; final value = (height - _minHeight) / (_maxHeight - _minHeight); - _controller.animateTo(value.clamp(0.0, 1.0), - duration: const Duration(milliseconds: 300), - curve: Curves.easeOutBack, - ).whenComplete(() => _isAnimating = false); + _controller + .animateTo( + value.clamp(0.0, 1.0), + duration: const Duration(milliseconds: 300), + curve: Curves.easeOutBack, + ) + .whenComplete(() => _isAnimating = false); } Widget _buildDragHandle() { - if (!widget.draggable) return const SizedBox.shrink(); + if (!widget.draggable) { + return const SizedBox.shrink(); + } return GestureDetector( behavior: HitTestBehavior.opaque, @@ -147,7 +166,7 @@ abstract class _TDPopupBaseState extends State width: 48, height: 4, decoration: BoxDecoration( - color: TDTheme.of(context).grayColor3, + color: TDTheme.of(context).componentStrokeColor, borderRadius: BorderRadius.circular(2), ), ), @@ -163,17 +182,18 @@ abstract class _TDPopupBaseState extends State _measureChildHeight(); } }); - + return AnimatedBuilder( animation: _controller, builder: (context, _) => RepaintBoundary( child: Container( height: _currentHeight, decoration: BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, borderRadius: _isFullscreen ? null - : BorderRadius.vertical(top: Radius.circular(widget.radius ?? 12)), + : BorderRadius.vertical( + top: Radius.circular(widget.radius ?? TDTheme.of(context).radiusExtraLarge)), ), child: Column(children: [ _buildDragHandle(), @@ -188,21 +208,21 @@ abstract class _TDPopupBaseState extends State } Widget _buildContent() => NotificationListener( - onNotification: (notification) { - if (notification is ScrollUpdateNotification) { - final metrics = notification.metrics; - if ((metrics.pixels <= 0 || metrics.pixels >= metrics.maxScrollExtent) && - notification.dragDetails != null) { - _handleDragUpdate(notification.dragDetails!); - } - } - return false; - }, - child: Container( - key: _childKey, - child: widget.child, - ), - ); + onNotification: (notification) { + if (notification is ScrollUpdateNotification) { + final metrics = notification.metrics; + if ((metrics.pixels <= 0 || metrics.pixels >= metrics.maxScrollExtent) && + notification.dragDetails != null) { + _handleDragUpdate(notification.dragDetails!); + } + } + return false; + }, + child: Container( + key: _childKey, + child: widget.child, + ), + ); @protected void _handleDragUpdate(DragUpdateDetails details); @@ -254,16 +274,22 @@ class TDPopupBottomDisplayPanel extends TDPopupBasePanel { super.maxHeightRatio, super.minHeightRatio, }); + /// 标题字体大小 final double? titleFontSize; + /// 标题是否靠左 final bool titleLeft; + /// 是否隐藏关闭按钮 final bool hideClose; + /// 关闭按钮颜色 final Color? closeColor; + /// 关闭按钮图标尺寸 final double? closeSize; + /// 关闭按钮点击回调 final PopupClick? closeClick; @@ -279,11 +305,9 @@ class _TDPopupBottomDisplayPanelState extends _TDPopupBaseState GestureDetector( - onTap: onTap, - child: Padding( - padding: EdgeInsets.only( - left: left ? 16 : 0, - right: left ? 0 : 16, - ), - child: TDText( - text, - textColor: color, - font: (left - ? TDTheme.of(context).fontBodyLarge - : TDTheme.of(context).fontTitleMedium - )?.withSize( - left - ? widget.leftTextFontSize?.toInt() ?? TDTheme.of(context).fontBodyLarge!.size.toInt() - : widget.rightTextFontSize?.toInt() ?? TDTheme.of(context).fontTitleMedium!.size.toInt() + }) => + GestureDetector( + onTap: onTap, + child: Padding( + padding: EdgeInsets.only( + left: left ? 16 : 0, + right: left ? 0 : 16, + ), + child: TDText( + text, + textColor: color, + font: (left ? TDTheme.of(context).fontBodyLarge : TDTheme.of(context).fontTitleMedium) + ?.withSize(left + ? widget.leftTextFontSize?.toInt() ?? + TDTheme.of(context).fontBodyLarge!.size.toInt() + : widget.rightTextFontSize?.toInt() ?? + TDTheme.of(context).fontTitleMedium!.size.toInt()), + fontWeight: left ? FontWeight.w400 : FontWeight.w600, + ), ), - fontWeight: left ? FontWeight.w400 : FontWeight.w600, - ), - ), - ); + ); @override void _handleDragUpdate(DragUpdateDetails details) { @@ -486,16 +514,22 @@ class TDPopupCenterPanel extends StatelessWidget { /// 子控件 final Widget child; + /// 关闭按钮是否在视图框下方 final bool closeUnderBottom; + /// 关闭按钮颜色 final Color? closeColor; + /// 关闭按钮图标尺寸 final double? closeSize; + /// 关闭按钮点击回调 final PopupClick? closeClick; + /// 背景颜色 final Color? backgroundColor; + /// 圆角 final double? radius; @@ -509,15 +543,16 @@ class TDPopupCenterPanel extends StatelessWidget { Container( margin: const EdgeInsets.symmetric(vertical: 24), decoration: BoxDecoration( - color: backgroundColor ?? TDTheme.of(context).whiteColor1, - borderRadius: BorderRadius.circular(radius ?? 12), + color: backgroundColor ?? TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.circular(radius ?? TDTheme.of(context).radiusExtraLarge), ), child: child, ), IconButton( - icon: Icon(TDIcons.close_circle, + icon: Icon( + TDIcons.close_circle, color: closeColor ?? TDTheme.of(context).fontWhColor1, - size: closeSize, + size: closeSize ?? 32, ), onPressed: closeClick, ), @@ -527,8 +562,8 @@ class TDPopupCenterPanel extends StatelessWidget { return Container( decoration: BoxDecoration( - color: backgroundColor ?? TDTheme.of(context).whiteColor1, - borderRadius: BorderRadius.circular(radius ?? 12), + color: backgroundColor ?? TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.circular(radius ?? TDTheme.of(context).radiusExtraLarge), ), child: Stack( children: [ @@ -537,7 +572,8 @@ class TDPopupCenterPanel extends StatelessWidget { top: TDTheme.of(context).spacer8, right: TDTheme.of(context).spacer8, child: IconButton( - icon: Icon(TDIcons.close, + icon: Icon( + TDIcons.close, color: closeColor, size: closeSize, ), diff --git a/tdesign-component/lib/src/components/popup/td_popup_route.dart b/tdesign-component/lib/src/components/popup/td_popup_route.dart index b4eea0e11..a709cadc6 100644 --- a/tdesign-component/lib/src/components/popup/td_popup_route.dart +++ b/tdesign-component/lib/src/components/popup/td_popup_route.dart @@ -177,7 +177,6 @@ class TDSlidePopupRoute extends PopupRoute { @override void dispose() { - // close?.call(); stopFocusListener(navigator!.context); super.dispose(); } diff --git a/tdesign-component/lib/src/components/progress/td_progress.dart b/tdesign-component/lib/src/components/progress/td_progress.dart index eb32f4c61..57dd6ab47 100644 --- a/tdesign-component/lib/src/components/progress/td_progress.dart +++ b/tdesign-component/lib/src/components/progress/td_progress.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; -import './td_progress_circular.dart'; + import '../../../tdesign_flutter.dart'; +import './td_progress_circular.dart'; enum TDProgressType { linear, circular, micro, button } @@ -13,13 +14,20 @@ abstract class TDLabelWidget extends Widget { } class TDTextLabel extends Text implements TDLabelWidget { - const TDTextLabel(String data, {Key? key, TextStyle? style}) - : super(data, key: key, style: style); + const TDTextLabel( + String data, { + Key? key, + TextStyle? style, + }) : super(data, key: key, style: style); } class TDIconLabel extends Icon implements TDLabelWidget { - const TDIconLabel(IconData icon, {Key? key, double? size, Color? color}) - : super(icon, key: key, size: size, color: color); + const TDIconLabel( + IconData icon, { + Key? key, + double? size, + Color? color, + }) : super(icon, key: key, size: size, color: color); } class TDProgress extends StatelessWidget { @@ -51,7 +59,7 @@ class TDProgress extends StatelessWidget { /// 进度条类型 final TDProgressType type; - /// 进度值 (0.0 到 1.0 之间的正数) + /// 进度值(0.0 到 1.0 之间的正数) final double? value; /// 进度条标签 @@ -63,7 +71,7 @@ class TDProgress extends StatelessWidget { /// 标签显示位置 final TDProgressLabelPosition progressLabelPosition; - /// 进度条粗细 (正数) + /// 进度条粗细(正数) final double? strokeWidth; /// 进度条颜色 @@ -75,7 +83,7 @@ class TDProgress extends StatelessWidget { /// 条形进度条末端形状 final BorderRadiusGeometry? linearBorderRadius; - /// 环形进度条半径 (正数) + /// 环形进度条半径(正数) final double? circleRadius; /// 是否显示标签 @@ -96,7 +104,7 @@ class TDProgress extends StatelessWidget { /// 长按事件 final VoidCallback? onLongPress; - /// 动画持续时间 (正整数,单位为毫秒) + /// 动画持续时间(正整数,单位为毫秒) final int? animationDuration; static double? _validateProgress(double? value) => @@ -122,10 +130,11 @@ class TDProgress extends StatelessWidget { strokeWidth: strokeWidth ?? defaultValues.strokeWidth, color: color, backgroundColor: backgroundColor ?? defaultValues.backgroundColor, - linearBorderRadius: linearBorderRadius ?? defaultValues.linearBorderRadius, + linearBorderRadius: + linearBorderRadius ?? defaultValues.linearBorderRadius, circleRadius: circleRadius ?? defaultValues.circleRadius, showLabel: showLabel, - customProgressLabel:customProgressLabel, + customProgressLabel: customProgressLabel, labelWidgetWidth: labelWidgetWidth, labelWidgetAlignment: labelWidgetAlignment, onTap: onTap, @@ -140,21 +149,21 @@ class TDProgress extends StatelessWidget { case TDProgressType.linear: return _DefaultValues( strokeWidth: 20.0, - backgroundColor: TDTheme.of(context).grayColor3, + backgroundColor: TDTheme.of(context).bgColorComponent, linearBorderRadius: BorderRadius.circular(20), circleRadius: 0, ); case TDProgressType.circular: return _DefaultValues( strokeWidth: 5.0, - backgroundColor: TDTheme.of(context).grayColor2, + backgroundColor: TDTheme.of(context).bgColorComponent, linearBorderRadius: BorderRadius.circular(20), circleRadius: 100.0, ); case TDProgressType.micro: return _DefaultValues( strokeWidth: 2.0, - backgroundColor: TDTheme.of(context).grayColor2, + backgroundColor: TDTheme.of(context).bgColorComponent, linearBorderRadius: BorderRadius.circular(20), circleRadius: 25.0, ); @@ -252,6 +261,7 @@ class _ProgressIndicatorState extends State super.didUpdateWidget(oldWidget); if (oldWidget.value != widget.value) { _updateAnimation(oldWidgetValue: oldWidget.value); + _updateEffectiveLabel(); } if (oldWidget.color != widget.color || oldWidget.progressStatus != widget.progressStatus) { @@ -358,9 +368,8 @@ class _ProgressIndicatorState extends State if (widget.value != null && widget.progressLabelPosition == TDProgressLabelPosition.inside) { return _buildInsideLabel(maxWidth); - } else { - return _buildOutsideLabel(maxWidth); } + return _buildOutsideLabel(maxWidth); }, ); } @@ -370,15 +379,18 @@ class _ProgressIndicatorState extends State animation: _animation, builder: (context, child) { final progressWidth = _animation.value * maxWidth; - return Stack( - children: [ - _buildBackgroundContainer(), - if (widget.value! > 0.1) - _buildProgressContainerWithLabel(progressWidth) - else - _buildProgressContainerWithLabelOutside(progressWidth), - ], - ); + return ClipRRect( + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusRound), + child: Stack( + children: [ + _buildBackgroundContainer(), + if (widget.value! > 0.1) + _buildProgressContainerWithLabel(progressWidth) + else + _buildProgressContainerWithLabelOutside(progressWidth), + ], + )); }, ); } @@ -387,46 +399,48 @@ class _ProgressIndicatorState extends State return AnimatedBuilder( animation: _animation, builder: (context, child) { - final progressWidth = _animation.value * maxWidth; return Row( crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + // spacing: TDTheme.of(context).spacer8, + textDirection: + widget.progressLabelPosition == TDProgressLabelPosition.right + ? TextDirection.rtl + : TextDirection.ltr, children: [ - if (widget.progressLabelPosition == TDProgressLabelPosition.left) - Container( - padding: const EdgeInsets.only(right: 8.0), - alignment:widget.labelWidgetAlignment??Alignment.centerRight, - constraints: BoxConstraints( - minWidth:widget.labelWidgetWidth??(maxWidth*0.1>70?maxWidth*0.04 - :maxWidth*0.1), - ), - child:widget.customProgressLabel?? - _buildLabelWidget(TDTheme.of(context).fontGyColor1), - ), - Expanded( - child: Stack( - children: [ - _buildBackgroundContainer(), - Container( - height: widget.strokeWidth, - width: progressWidth, - decoration: BoxDecoration( - color: _effectiveColor, - borderRadius: widget.linearBorderRadius, - ), - ) - ], - )), - if (widget.progressLabelPosition == TDProgressLabelPosition.right) Container( - padding: const EdgeInsets.only(left: 8.0), - alignment:widget.labelWidgetAlignment??Alignment.centerLeft, - constraints: BoxConstraints( - minWidth:widget.labelWidgetWidth??(maxWidth*0.1>70?maxWidth*0.04 - :maxWidth*0.1), - ), - child:widget.customProgressLabel?? - _buildLabelWidget(TDTheme.of(context).fontGyColor1), - ) + alignment: widget.labelWidgetAlignment ?? + (widget.progressLabelPosition == TDProgressLabelPosition.left + ? Alignment.centerRight + : Alignment.centerLeft), + constraints: + BoxConstraints(minWidth: widget.labelWidgetWidth ?? 0), + child: widget.customProgressLabel ?? + _buildLabelWidget(TDTheme.of(context).textColorPrimary), + ), + SizedBox(width: TDTheme.of(context).spacer8), + Expanded( + child: ClipRRect( + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusRound), + child: LayoutBuilder( + builder: (context, constraints) { + return Stack( + children: [ + _buildBackgroundContainer(), + Container( + height: widget.strokeWidth, + width: constraints.maxWidth * _animation.value, + decoration: BoxDecoration( + color: _effectiveColor, + borderRadius: widget.linearBorderRadius, + ), + ), + ], + ); + }, + )), + ), ], ); }, @@ -455,8 +469,8 @@ class _ProgressIndicatorState extends State ? Align( alignment: Alignment.centerRight, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: _buildLabelWidget(TDTheme.of(context).fontWhColor1), + padding: const EdgeInsets.symmetric(horizontal: 6.0), + child: _buildLabelWidget(TDTheme.of(context).textColorAnti), ), ) : null, @@ -473,22 +487,26 @@ class _ProgressIndicatorState extends State decoration: BoxDecoration( color: _effectiveColor, borderRadius: BorderRadius.only( - topLeft: widget.linearBorderRadius.resolve(TextDirection.ltr).topLeft, - bottomLeft: - widget.linearBorderRadius.resolve(TextDirection.ltr).bottomLeft, - topRight: Radius.circular( - widget.linearBorderRadius.resolve(TextDirection.ltr).topRight.x / - 2), - bottomRight: Radius.circular( - widget.linearBorderRadius.resolve(TextDirection.ltr).bottomRight.x / - 2), + topLeft: + widget.linearBorderRadius.resolve(TextDirection.ltr).topLeft, + bottomLeft: widget.linearBorderRadius + .resolve(TextDirection.ltr) + .bottomLeft, + topRight: Radius.circular(widget.linearBorderRadius + .resolve(TextDirection.ltr) + .topRight + .x), + bottomRight: Radius.circular(widget.linearBorderRadius + .resolve(TextDirection.ltr) + .bottomRight + .x), ), ), ), if (widget.showLabel) Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: _buildLabelWidget(TDTheme.of(context).fontGyColor1), + child: _buildLabelWidget(TDTheme.of(context).textColorPrimary), ), ], ); @@ -508,8 +526,7 @@ class _ProgressIndicatorState extends State fontSize = widget.strokeWidth * 0.6; iconSize = widget.strokeWidth; } - fontWeight = - _animation.value <= 0.1 ? FontWeight.bold : FontWeight.normal; + fontWeight = FontWeight.normal; break; case TDProgressType.circular: iconSize = widget.circleRadius * 0.4; @@ -563,7 +580,7 @@ class _ProgressIndicatorState extends State ), ), if (widget.showLabel) - _buildLabelWidget(TDTheme.of(widget.context).fontGyColor1), + _buildLabelWidget(TDTheme.of(widget.context).textColorPrimary), ], ); }, @@ -582,7 +599,8 @@ class _ProgressIndicatorState extends State children: [ _buildMicroOutline(), if (widget.showLabel) - _buildLabelWidget(TDTheme.of(widget.context).fontGyColor1), + _buildLabelWidget( + TDTheme.of(widget.context).textColorPrimary), ], )); }); diff --git a/tdesign-component/lib/src/components/radio/td_radio.dart b/tdesign-component/lib/src/components/radio/td_radio.dart index ceb4caea3..4bdb64f12 100644 --- a/tdesign-component/lib/src/components/radio/td_radio.dart +++ b/tdesign-component/lib/src/components/radio/td_radio.dart @@ -68,7 +68,8 @@ class TDRadio extends TDCheckbox { customSpace: customSpace); @override - Widget buildDefaultIcon(BuildContext context, TDCheckboxGroupState? groupState, bool isSelected) { + Widget buildDefaultIcon( + BuildContext context, TDCheckboxGroupState? groupState, bool isSelected) { if (cardMode == true) { return Container(); } @@ -82,7 +83,7 @@ class TDRadio extends TDCheckbox { var size = 24.0; final theme = TDTheme.of(context); - // 由于镂空圆没有现成icon,因而自己画一个` + // 由于镂空圆没有现成icon,因而自己画一个 if (style == TDRadioStyle.hollowCircle) { return SizedBox( width: size, @@ -103,7 +104,8 @@ class TDRadio extends TDCheckbox { iconData = isSelected ? TDIcons.check : null; break; case TDRadioStyle.square: - iconData = isSelected ? TDIcons.check_rectangle_filled : TDIcons.rectangle; + iconData = + isSelected ? TDIcons.check_rectangle_filled : TDIcons.rectangle; break; default: iconData = isSelected ? TDIcons.check_circle_filled : TDIcons.circle; @@ -113,10 +115,12 @@ class TDRadio extends TDCheckbox { return Icon(iconData, size: size, color: !enable - ? (isSelected ? (disableColor ?? theme.brandDisabledColor) : theme.grayColor4) + ? (isSelected + ? (disableColor ?? theme.brandDisabledColor) + : theme.componentStrokeColor) : isSelected ? selectColor ?? theme.brandNormalColor - : theme.grayColor4); + : theme.componentStrokeColor); } else { return SizedBox( width: size, @@ -214,22 +218,26 @@ class TDRadioGroup extends TDCheckboxGroup { : assert(() { // 使用direction属性则必须配合directionalTdRadios,child字段无效 if (direction != null && directionalTdRadios == null) { - throw FlutterError('[TDRadioGroup] direction and directionalTdRadios must set at the same time'); + throw FlutterError( + '[TDRadioGroup] direction and directionalTdRadios must set at the same time'); } // 未使用direction则必须设置child if (direction == null && child == null) { - throw FlutterError('[TDRadioGroup] direction means use child as the exact one, but child is null'); + throw FlutterError( + '[TDRadioGroup] direction means use child as the exact one, but child is null'); } // 横向单选框 每个选项有字数限制 if (direction == Axis.horizontal && directionalTdRadios != null) { directionalTdRadios.forEach((element) { if (element.subTitle != null) { - throw FlutterError('horizontal radios style should not have subTilte, ' + throw FlutterError( + 'horizontal radios style should not have subTilte, ' 'because there left no room for it'); } }); var maxWordCount = 2; - var tips = '[TDRadioGroup] radio title please not exceed $maxWordCount words.\n' + var tips = + '[TDRadioGroup] radio title please not exceed $maxWordCount words.\n' '2tabs: 7words maximum\n' '3tabs: 4words maximum\n' '4tabs: 2words maximum'; @@ -255,11 +263,13 @@ class TDRadioGroup extends TDCheckboxGroup { // if use cardMode at TDRadioGroup, then every TDRadio should // set it's own carMode to true. if (element.cardMode == false) { - throw FlutterError('if use cardMode at TDRadioGroup, then every ' + throw FlutterError( + 'if use cardMode at TDRadioGroup, then every ' 'TDRadio should set it\'s own carMode to true.'); } if (element.subTitle != null && direction == Axis.horizontal) { - throw FlutterError('horizontal card style should not have subTilte, ' + throw FlutterError( + 'horizontal card style should not have subTilte, ' 'because there left no room for it'); } }); @@ -268,7 +278,9 @@ class TDRadioGroup extends TDCheckboxGroup { }()), super( child: Container( - clipBehavior: (passThrough ?? false) && direction != Axis.horizontal ? Clip.hardEdge : Clip.none, + clipBehavior: (passThrough ?? false) && direction != Axis.horizontal + ? Clip.hardEdge + : Clip.none, decoration: (passThrough ?? false) && direction != Axis.horizontal ? BoxDecoration(borderRadius: BorderRadius.circular(10)) : null, @@ -284,7 +296,9 @@ class TDRadioGroup extends TDCheckboxGroup { physics: const NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) { return Container( - margin: cardMode ? const EdgeInsets.symmetric(horizontal: 16) : null, + margin: cardMode + ? const EdgeInsets.symmetric(horizontal: 16) + : null, height: cardMode ? 82 : null, child: directionalTdRadios[index], ); @@ -300,31 +314,40 @@ class TDRadioGroup extends TDCheckboxGroup { }, ) : Container( - margin: cardMode ? const EdgeInsets.symmetric(horizontal: 16) : null, - height: cardMode ? (directionalTdRadios!.length / rowCount).ceil() * (56 + 10) : null, + margin: cardMode + ? const EdgeInsets.symmetric(horizontal: 16) + : null, + height: cardMode + ? (directionalTdRadios!.length / rowCount).ceil() * + (56 + 10) + : null, alignment: cardMode ? Alignment.topLeft : null, child: cardMode && rowCount != null ? GridView.builder( itemCount: directionalTdRadios!.length, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( crossAxisSpacing: 10.0, mainAxisSpacing: 10.0, crossAxisCount: rowCount, //一行的 Widget 数量 mainAxisExtent: 56, ), itemBuilder: (BuildContext context, int index) { - return Container( + return SizedBox( width: 160.scale, height: 56, - child: directionalTdRadios![index], + child: directionalTdRadios[index], ); }) : Column( children: [ Row( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: directionalTdRadios!.map((e) => Expanded(child: e)).toList(), + crossAxisAlignment: + CrossAxisAlignment.start, + children: directionalTdRadios! + .map((e) => Expanded(child: e)) + .toList(), ), if (showDivider) divider ?? diff --git a/tdesign-component/lib/src/components/rate/td_rate.dart b/tdesign-component/lib/src/components/rate/td_rate.dart index ffe201382..7339e82dd 100644 --- a/tdesign-component/lib/src/components/rate/td_rate.dart +++ b/tdesign-component/lib/src/components/rate/td_rate.dart @@ -148,10 +148,13 @@ class _TDRateState extends State with TickerProviderStateMixin { void initState() { super.initState(); _activeValue = widget.value ?? 0; - _globalKeys = List.generate((widget.count ?? 5) * 2, (index) => index / 2 + 0.5) - .asMap() - .map((index, e) => MapEntry(e, GlobalKey())); - _overlay = TDRateOverlay(context: context, builder: (context) => _buildOverlay())..show(); + _globalKeys = + List.generate((widget.count ?? 5) * 2, (index) => index / 2 + 0.5) + .asMap() + .map((index, e) => MapEntry(e, GlobalKey())); + _overlay = + TDRateOverlay(context: context, builder: (context) => _buildOverlay()) + ..show(); _tipSize = Size(widget.allowHalf == true ? 76 : 40, 52); _controller = List.generate( widget.count ?? 5, @@ -159,8 +162,10 @@ class _TDRateState extends State with TickerProviderStateMixin { duration: const Duration(milliseconds: 300), vsync: this, ))); - _animation = - List.generate(widget.count ?? 5, ((index) => Tween(begin: 1.0, end: 1.33).animate(_controller[index]))); + _animation = List.generate( + widget.count ?? 5, + ((index) => + Tween(begin: 1.0, end: 1.33).animate(_controller[index]))); } @override @@ -170,9 +175,10 @@ class _TDRateState extends State with TickerProviderStateMixin { _activeValue = widget.value ?? 0; } if (widget.count != oldWidget.count) { - _globalKeys = List.generate((widget.count ?? 5) * 2, (index) => index / 2 + 0.5) - .asMap() - .map((index, e) => MapEntry(e, GlobalKey())); + _globalKeys = + List.generate((widget.count ?? 5) * 2, (index) => index / 2 + 0.5) + .asMap() + .map((index, e) => MapEntry(e, GlobalKey())); } if (widget.allowHalf != oldWidget.allowHalf) { _tipSize = Size(widget.allowHalf == true ? 76 : 40, 52); @@ -192,7 +198,8 @@ class _TDRateState extends State with TickerProviderStateMixin { return Flex( direction: widget.direction ?? Axis.horizontal, mainAxisAlignment: widget.mainAxisAlignment ?? MainAxisAlignment.start, - crossAxisAlignment: widget.crossAxisAlignment ?? CrossAxisAlignment.center, + crossAxisAlignment: + widget.crossAxisAlignment ?? CrossAxisAlignment.center, mainAxisSize: widget.mainAxisSize ?? MainAxisSize.min, children: [ GestureDetector( @@ -227,7 +234,9 @@ class _TDRateState extends State with TickerProviderStateMixin { children: List.generate(widget.count ?? 5, (index) { final isLast = index == (widget.count ?? 5) - 1; return Padding( - padding: EdgeInsets.only(right: isLast ? 0 : widget.gap ?? TDTheme.of(context).spacer8), + padding: EdgeInsets.only( + right: + isLast ? 0 : widget.gap ?? TDTheme.of(context).spacer8), child: AnimatedBuilder( animation: _animation[index], builder: (context, child) { @@ -269,7 +278,8 @@ class _TDRateState extends State with TickerProviderStateMixin { }), ), ), - if (widget.showText ?? false) widget.builderText?.call(context, _activeValue) ?? _getDefText() + if (widget.showText ?? false) + widget.builderText?.call(context, _activeValue) ?? _getDefText() ], ); } @@ -317,14 +327,19 @@ class _TDRateState extends State with TickerProviderStateMixin { return 0; } for (var entry in _globalKeys.entries) { - final renderBox = entry.value.currentContext?.findRenderObject() as RenderBox?; + final renderBox = + entry.value.currentContext?.findRenderObject() as RenderBox?; if (renderBox != null) { final localPosition = renderBox.globalToLocal(globalPosition); - final isIn = renderBox.hitTest(BoxHitTestResult(), position: localPosition); + final isIn = + renderBox.hitTest(BoxHitTestResult(), position: localPosition); if (isIn) { - var value = widget.allowHalf == true ? entry.key : entry.key.ceil().toDouble(); + var value = widget.allowHalf == true + ? entry.key + : entry.key.ceil().toDouble(); var index = _index(value); - if (!_rateSize.containsKey(index) || !_rateOffset.containsKey(index)) { + if (!_rateSize.containsKey(index) || + !_rateOffset.containsKey(index)) { final parentRenderBox = renderBox.parent as RenderBox; _rateSize[index] = parentRenderBox.size; _rateOffset[index] = parentRenderBox.localToGlobal(Offset.zero); @@ -339,7 +354,8 @@ class _TDRateState extends State with TickerProviderStateMixin { void _hideTip() { _hideTipTimer?.cancel(); _hideTipTimer = Timer( - Duration(milliseconds: _isClick && widget.allowHalf == true ? 3000 : 1000), + Duration( + milliseconds: _isClick && widget.allowHalf == true ? 3000 : 1000), () { _showTip = false; _isClick = true; @@ -351,36 +367,51 @@ class _TDRateState extends State with TickerProviderStateMixin { Widget _getDefText() { final notRated = _activeValue == 0; - final textIndex = (widget.allowHalf == true ? _activeValue * 2 : _activeValue) - 1; + final textIndex = + (widget.allowHalf == true ? _activeValue * 2 : _activeValue) - 1; return Padding( padding: widget.direction == Axis.horizontal - ? EdgeInsets.only(left: widget.iconTextGap ?? TDTheme.of(context).spacer16) - : EdgeInsets.only(top: widget.iconTextGap ?? TDTheme.of(context).spacer8), + ? EdgeInsets.only( + left: widget.iconTextGap ?? TDTheme.of(context).spacer16) + : EdgeInsets.only( + top: widget.iconTextGap ?? TDTheme.of(context).spacer8), child: SizedBox( width: widget.textWidth ?? 50, child: TDText( - notRated ? context.resource.notRated : widget.texts?.getOrNull(textIndex.toInt()) ?? '$_activeValue', - font: notRated ? TDTheme.of(context).fontBodyLarge : TDTheme.of(context).fontTitleMedium, - textColor: notRated ? TDTheme.of(context).fontGyColor4 : TDTheme.of(context).fontGyColor1, + notRated + ? context.resource.notRated + : widget.texts?.getOrNull(textIndex.toInt()) ?? '$_activeValue', + font: notRated + ? TDTheme.of(context).fontBodyLarge + : TDTheme.of(context).fontTitleMedium, + textColor: notRated + ? TDTheme.of(context).textColorDisabled + : TDTheme.of(context).textColorPrimary, ), ), ); } Color _getIconColor({double? value, bool? isActive}) { - return (value != null && _activeValue >= value) || (isActive != null && isActive) + return (value != null && _activeValue >= value) || + (isActive != null && isActive) ? widget.color?.getOrNull(0) ?? TDTheme.of(context).warningColor5 - : widget.color?.getOrNull(1) ?? TDTheme.of(context).grayColor4; + : widget.color?.getOrNull(1) ?? TDTheme.of(context).bgColorComponent; } IconData _getIcon({double? value, bool? isActive}) { final selectIcon = widget.icon?.getOrNull(0) ?? TDIcons.star_filled; final icon = [selectIcon, widget.icon?.getOrNull(1) ?? selectIcon]; - return (value != null && _activeValue >= value) || (isActive != null && isActive) ? icon[0] : icon[1]; + return (value != null && _activeValue >= value) || + (isActive != null && isActive) + ? icon[0] + : icon[1]; } Widget _buildOverlay() { - if (widget.placement == PlacementEnum.none || !_showTip || _activeValue == 0) { + if (widget.placement == PlacementEnum.none || + !_showTip || + _activeValue == 0) { return const SizedBox.shrink(); } var index = _index(); diff --git a/tdesign-component/lib/src/components/rate/td_rate_tips.dart b/tdesign-component/lib/src/components/rate/td_rate_tips.dart index 0155cf427..95330519b 100644 --- a/tdesign-component/lib/src/components/rate/td_rate_tips.dart +++ b/tdesign-component/lib/src/components/rate/td_rate_tips.dart @@ -31,13 +31,14 @@ class TDRateTips extends StatelessWidget { Widget build(BuildContext context) { final _tipKey = GlobalKey(); WidgetsBinding.instance.addPostFrameCallback((_) { - final renderBox = _tipKey.currentContext?.findRenderObject() as RenderBox?; + final renderBox = + _tipKey.currentContext?.findRenderObject() as RenderBox?; sizeCall(renderBox?.size ?? Size.zero); }); return Container( key: _tipKey, decoration: BoxDecoration( - color: TDTheme.of(context).whiteColor1, + color: TDTheme.of(context).bgColorContainer, boxShadow: const [ BoxShadow( color: Color.fromRGBO(0, 0, 0, 0.12), @@ -71,12 +72,16 @@ class TDRateTips extends StatelessWidget { }, child: Container( decoration: BoxDecoration( - color: allowHalf == true && index + 0.5 == activeValue && isClick - ? TDTheme.of(context).grayColor3 - : TDTheme.of(context).whiteColor1, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusSmall), + color: + allowHalf == true && index + 0.5 == activeValue && isClick + ? TDTheme.of(context).bgColorComponent + : Colors.transparent, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusSmall), ), - padding: EdgeInsets.only(left: TDTheme.of(context).spacer4, right: TDTheme.of(context).spacer4), + padding: EdgeInsets.only( + left: TDTheme.of(context).spacer4, + right: TDTheme.of(context).spacer4), child: Column( children: [ Row( @@ -100,7 +105,9 @@ class TDRateTips extends StatelessWidget { icon, size: size ?? 24, color: allowHalf == true - ? (isClick ? getIconColor(isActive: false) : getIconColor(value: index + 1)) + ? (isClick + ? getIconColor(isActive: false) + : getIconColor(value: index + 1)) : getIconColor(isActive: true), ), ), @@ -109,16 +116,19 @@ class TDRateTips extends StatelessWidget { ), Center( child: TDText( - allowHalf == true ? (isClick ? '${index + 0.5}' : '${activeValue}') : '${index + 1}', + allowHalf == true + ? (isClick ? '${index + 0.5}' : '${activeValue}') + : '${index + 1}', font: TDTheme.of(context).fontBodySmall, - textColor: TDTheme.of(context).fontGyColor1, + textColor: TDTheme.of(context).textColorPrimary, ), ), ], ), ), ), - if (allowHalf == true && isClick) SizedBox(width: TDTheme.of(context).spacer4), + if (allowHalf == true && isClick) + SizedBox(width: TDTheme.of(context).spacer4), if (allowHalf == true && isClick) GestureDetector( onTap: () { @@ -128,10 +138,15 @@ class TDRateTips extends StatelessWidget { }, child: Container( decoration: BoxDecoration( - color: index + 1 != activeValue ? TDTheme.of(context).whiteColor1 : TDTheme.of(context).grayColor3, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusSmall), + color: index + 1 != activeValue + ? Colors.transparent + : TDTheme.of(context).bgColorComponent, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusSmall), ), - padding: EdgeInsets.only(left: TDTheme.of(context).spacer4, right: TDTheme.of(context).spacer4), + padding: EdgeInsets.only( + left: TDTheme.of(context).spacer4, + right: TDTheme.of(context).spacer4), child: Column( children: [ Icon( @@ -143,7 +158,7 @@ class TDRateTips extends StatelessWidget { child: TDText( '${index + 1}', font: TDTheme.of(context).fontBodySmall, - textColor: TDTheme.of(context).fontGyColor1, + textColor: TDTheme.of(context).textColorPrimary, ), ), ], diff --git a/tdesign-component/lib/src/components/refresh/td_refresh_header.dart b/tdesign-component/lib/src/components/refresh/td_refresh_header.dart index 236fcdda7..7edc6de72 100644 --- a/tdesign-component/lib/src/components/refresh/td_refresh_header.dart +++ b/tdesign-component/lib/src/components/refresh/td_refresh_header.dart @@ -49,13 +49,17 @@ class TDRefreshHeader extends Header { }) : assert((triggerOffset ?? triggerDistance) > 0.0), assert(extent != null && extent >= 0.0), assert( - extent != null && ((clamping ?? float) || (triggerOffset ?? triggerDistance) >= extent), + extent != null && + ((clamping ?? float) || + (triggerOffset ?? triggerDistance) >= extent), 'The refresh indicator cannot take more space in its final state ' 'than the amount initially created by overscrolling.'), super( triggerOffset: triggerOffset ?? triggerDistance, clamping: clamping ?? float, - processedDuration: processedDuration ?? completeDuration ?? const Duration(seconds: 1), + processedDuration: processedDuration ?? + completeDuration ?? + const Duration(seconds: 1), hapticFeedback: hapticFeedback ?? enableHapticFeedback, infiniteOffset: enableInfiniteRefresh ? infiniteOffset : null, infiniteHitOver: infiniteHitOver ?? overScroll, @@ -99,7 +103,8 @@ class TDRefreshHeader extends Header { Widget build(BuildContext context, IndicatorState state) { // 不能为水平方向 assert( - state.axisDirection == AxisDirection.down || state.axisDirection == AxisDirection.up, + state.axisDirection == AxisDirection.down || + state.axisDirection == AxisDirection.up, 'Widget cannot be horizontal', ); return TGIconHeaderWidget( @@ -140,11 +145,16 @@ class TGIconHeaderWidget extends StatefulWidget { } } -class TGIconHeaderWidgetState extends State with TickerProviderStateMixin { +class TGIconHeaderWidgetState extends State + with TickerProviderStateMixin { IndicatorMode get _refreshState => widget.state.mode; + double get _offset => widget.state.offset; + double get _actualTriggerOffset => widget.state.actualTriggerOffset; + bool get _reverse => widget.state.reverse; + double get _safeOffset => widget.state.safeOffset; Widget _buildLoading() => TDLoading( @@ -153,7 +163,7 @@ class TGIconHeaderWidgetState extends State with TickerProvi iconColor: TDTheme.of(context).brandNormalColor, axis: Axis.horizontal, text: context.resource.refreshing, - textColor: TDTheme.of(context).fontGyColor3, + textColor: TDTheme.of(context).textColorPlaceholder, ); @override @@ -167,10 +177,16 @@ class TGIconHeaderWidgetState extends State with TickerProvi left: 0, right: 0, top: _offset < _actualTriggerOffset - ? -(_actualTriggerOffset - _offset + (_reverse ? _safeOffset : -_safeOffset)) / 2 + ? -(_actualTriggerOffset - + _offset + + (_reverse ? _safeOffset : -_safeOffset)) / + 2 : (!_reverse ? _safeOffset : 0), - bottom: _offset < _actualTriggerOffset ? null : (_reverse ? _safeOffset : 0), - height: _offset < _actualTriggerOffset ? _actualTriggerOffset : null, + bottom: _offset < _actualTriggerOffset + ? null + : (_reverse ? _safeOffset : 0), + height: + _offset < _actualTriggerOffset ? _actualTriggerOffset : null, child: Container( alignment: Alignment.center, height: widget.refreshIndicatorExtent, @@ -179,17 +195,19 @@ class TGIconHeaderWidgetState extends State with TickerProvi child: Container( child: _buildLoading(), ), - visible: _refreshState == IndicatorMode.processing || _refreshState == IndicatorMode.ready, + visible: _refreshState == IndicatorMode.processing || + _refreshState == IndicatorMode.ready, replacement: Visibility( visible: _refreshState != IndicatorMode.inactive, child: TDText( _refreshState == IndicatorMode.drag ? context.resource.pullToRefresh - : _refreshState == IndicatorMode.processed || _refreshState == IndicatorMode.done + : _refreshState == IndicatorMode.processed || + _refreshState == IndicatorMode.done ? context.resource.completeRefresh : context.resource.releaseRefresh, font: TDTheme.of(context).fontBodyMedium, - textColor: TDTheme.of(context).fontGyColor3, + textColor: TDTheme.of(context).textColorPlaceholder, ), ), ), diff --git a/tdesign-component/lib/src/components/result/td_result.dart b/tdesign-component/lib/src/components/result/td_result.dart index 9b012874d..1b71684a4 100644 --- a/tdesign-component/lib/src/components/result/td_result.dart +++ b/tdesign-component/lib/src/components/result/td_result.dart @@ -4,56 +4,57 @@ import '../../../tdesign_flutter.dart'; enum TDResultTheme { defaultTheme, success, warning, error } class TDResult extends StatelessWidget { - /// 构造函数,用于初始化Result组件 const TDResult({ Key? key, this.description, this.icon, this.titleStyle, - this.theme = TDResultTheme.defaultTheme, // 默认主题样式为defaultTheme - this.title = '', // 默认标题为空字符串 + this.theme = TDResultTheme.defaultTheme, + this.title = '', }) : super(key: key); -/// 描述文本,用于提供额外信息 + /// 描述文本,用于提供额外信息 final String? description; -/// 图标组件,用于在结果中显示一个图标 + + /// 图标组件,用于在结果中显示一个图标 final Widget? icon; -/// 自定义字体样式,用于设置标题文本的样式 + + /// 自定义字体样式,用于设置标题文本的样式 final TextStyle? titleStyle; -/// 主题样式,定义了结果组件的视觉风格 + + /// 主题样式,默认主题样式为defaultTheme final TDResultTheme theme; -/// 标题文本,显示结果的主要信息 - final String title; + /// 标题文本,显示结果的主要信息,默认标题为空字符串 + final String title; @override Widget build(BuildContext context) { // 根据主题获取默认的图标组件 - Widget displayIcon = icon ?? _getDefaultIconByTheme(context, theme); - // 构建组件布局 + var displayIcon = icon ?? _getDefaultIconByTheme(context, theme); return Column( mainAxisSize: MainAxisSize.min, children: [ Container( child: displayIcon, ), - // 如果标题不为空,则显示标题 if (title.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 17), child: TDText( title, - textColor: TDTheme.of(context).fontGyColor1, + textColor: TDTheme.of(context).textColorPrimary, font: TDTheme.of(context).fontTitleExtraLarge, style: titleStyle, )), - // 如果描述不为空,则显示描述 - if (description?.isNotEmpty ?? false) + if (description != null && description!.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 8), - child: TDText(description!, - textColor: TDTheme.of(context).fontGyColor2, - font: TDTheme.of(context).fontTitleSmall), + child: TDText( + description!, + textColor: TDTheme.of(context).textColorSecondary, + font: TDTheme.of(context).fontTitleSmall, + ), ), ], ); @@ -63,17 +64,29 @@ class TDResult extends StatelessWidget { Widget _getDefaultIconByTheme(BuildContext context, TDResultTheme theme) { switch (theme) { case TDResultTheme.success: - return Icon(TDIcons.check_circle, - color: TDTheme.of(context).successNormalColor, size: 70); + return Icon( + TDIcons.check_circle, + color: TDTheme.of(context).successNormalColor, + size: 70, + ); case TDResultTheme.warning: - return Icon(TDIcons.error_circle, - color: TDTheme.of(context).warningNormalColor, size: 70); + return Icon( + TDIcons.error_circle, + color: TDTheme.of(context).warningNormalColor, + size: 70, + ); case TDResultTheme.error: - return Icon(TDIcons.close_circle, - color: TDTheme.of(context).errorNormalColor, size: 70); + return Icon( + TDIcons.close_circle, + color: TDTheme.of(context).errorNormalColor, + size: 70, + ); default: - return Icon(TDIcons.info_circle, - color: TDTheme.of(context).brandNormalColor, size: 70); + return Icon( + TDIcons.info_circle, + color: TDTheme.of(context).brandNormalColor, + size: 70, + ); } } } diff --git a/tdesign-component/lib/src/components/search/td_search_bar.dart b/tdesign-component/lib/src/components/search/td_search_bar.dart index f627f0823..d303c08e1 100644 --- a/tdesign-component/lib/src/components/search/td_search_bar.dart +++ b/tdesign-component/lib/src/components/search/td_search_bar.dart @@ -41,7 +41,7 @@ class TDSearchBar extends StatefulWidget { this.cursorHeight, this.needCancel = false, this.controller, - this.backgroundColor = Colors.white, + this.backgroundColor, this.action = '', this.onActionClick, this.onClearClick, @@ -78,7 +78,6 @@ class TDSearchBar extends StatefulWidget { /// 光标的高 final double? cursorHeight; - /// 是否需要取消按钮 final bool needCancel; @@ -102,6 +101,7 @@ class TDSearchBar extends StatefulWidget { /// 输入框点击事件 final GestureTapCallback? onInputClick; + /// 自定义操作回调 final TDSearchBarEvent? onActionClick; @@ -109,7 +109,7 @@ class TDSearchBar extends StatefulWidget { final TDSearchBarClearEvent? onClearClick; /// 自定义焦点 - final FocusNode? focusNode; + final FocusNode? focusNode; /// 键盘动作类型 final TextInputAction? inputAction; @@ -119,6 +119,7 @@ class TDSearchBar extends StatefulWidget { /// 是否只读 final bool? readOnly; + @override State createState() => _TDSearchBarState(); } @@ -131,15 +132,16 @@ class _TDSearchBarState extends State bool clearBtnHide = true; bool cancelBtnHide = true; + @override void initState() { super.initState(); - if(widget.controller==null){ + if (widget.controller == null) { controller.addListener(() { var clearVisible = controller.text.isNotEmpty; _updateClearBtnVisible(clearVisible); }); - }else{ + } else { widget.controller?.addListener(() { var clearVisible = widget.controller?.text.isNotEmpty; _updateClearBtnVisible(clearVisible!); @@ -169,12 +171,12 @@ class _TDSearchBarState extends State }); } - void _cleanInputText(){ - if(!(widget.onClearClick?.call(controller.text) ?? false)){ + void _cleanInputText() { + if (!(widget.onClearClick?.call(controller.text) ?? false)) { // 如果外部没处理,则走默认清除逻辑 - if(widget.controller==null){ + if (widget.controller == null) { controller.clear(); - }else{ + } else { widget.controller?.clear(); } } @@ -186,10 +188,11 @@ class _TDSearchBarState extends State : TDTheme.of(context).fontBodyLarge; } - Widget actionBtn(BuildContext context, String? text, {String? action, TDSearchBarEvent? onActionClick} ){ + Widget actionBtn(BuildContext context, String? text, + {String? action, TDSearchBarEvent? onActionClick}) { return GestureDetector( - onTap: (){ - onActionClick!(text??''); + onTap: () { + onActionClick!(text ?? ''); }, child: Container( padding: const EdgeInsets.only(left: 16), @@ -206,7 +209,7 @@ class _TDSearchBarState extends State return Container( padding: widget.padding, height: widget.autoHeight ? double.infinity : 56, - color: widget.backgroundColor, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Stack(alignment: AlignmentDirectional.center, children: [ Row( children: [ @@ -215,7 +218,7 @@ class _TDSearchBarState extends State child: Container( height: double.infinity, decoration: BoxDecoration( - color: TDTheme.of(context).grayColor1, + color: TDTheme.of(context).bgColorSecondaryContainer, borderRadius: BorderRadius.circular( widget.style == TDSearchStyle.square ? 4 : 28)), child: Row( @@ -227,24 +230,25 @@ class _TDSearchBarState extends State Icon( TDIcons.search, size: widget.mediumStyle ? 20 : 24, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, ), const Padding(padding: EdgeInsets.only(left: 3)), Expanded( flex: 1, child: Container( - margin: const EdgeInsets.only(bottom: 1),// 为了适配TextField与Text的差异,后续需要做通用适配 + margin: const EdgeInsets.only(bottom: 1), + // 为了适配TextField与Text的差异,后续需要做通用适配 child: TextField( - key: _textFieldKey, - controller: widget.controller??controller, + controller: widget.controller ?? controller, autofocus: widget.autoFocus, cursorColor: TDTheme.of(context).brandNormalColor, cursorWidth: 1, - cursorHeight:widget.cursorHeight, - textAlign: widget.alignment == TDSearchAlignment.center - ? TextAlign.center - : TextAlign.left, + cursorHeight: widget.cursorHeight, + textAlign: + widget.alignment == TDSearchAlignment.center + ? TextAlign.center + : TextAlign.left, focusNode: focusNode, onTap: widget.onInputClick, onChanged: widget.onTextChanged, @@ -254,24 +258,25 @@ class _TDSearchBarState extends State style: TextStyle( textBaseline: TextBaseline.ideographic, fontSize: getSize(context)?.size, - color: TDTheme.of(context).fontGyColor1), + color: TDTheme.of(context).textColorPrimary), decoration: InputDecoration( hintText: widget.placeHolder, hintStyle: TextStyle( - fontSize: getSize(context)?.size, - color: TDTheme.of(context).fontGyColor3, + fontSize: getSize(context)?.size, + color: TDTheme.of(context).textColorPlaceholder, textBaseline: TextBaseline.ideographic, - overflow: TextOverflow.ellipsis,), + overflow: TextOverflow.ellipsis, + ), hintMaxLines: 1, border: InputBorder.none, isCollapsed: true, - filled: true, - fillColor: TDTheme.of(context).grayColor1, + // filled: true, + // fillColor: TDTheme.of(context).bgColorSecondaryContainer, ), maxLines: 1, textInputAction: widget.inputAction, - readOnly:widget.readOnly??false, - enabled:widget.enabled, + readOnly: widget.readOnly ?? false, + enabled: widget.enabled, cursorOpacityAnimates: false, ), ), @@ -289,7 +294,7 @@ class _TDSearchBarState extends State child: Icon( TDIcons.close_circle_filled, size: widget.mediumStyle ? 17 : 21, - color: TDTheme.of(context).fontGyColor3, + color: TDTheme.of(context).textColorPlaceholder, )), ), const Padding(padding: EdgeInsets.only(right: 9)), @@ -299,34 +304,33 @@ class _TDSearchBarState extends State ), widget.action.isNotEmpty ? actionBtn( - context, - controller.text, - action: widget.action, - onActionClick: widget.onActionClick ?? (String text) {}, - ) + context, + controller.text, + action: widget.action, + onActionClick: widget.onActionClick ?? (String text) {}, + ) : Offstage( - offstage: cancelBtnHide || !widget.needCancel, - child: GestureDetector( - onTap: () { - _cleanInputText(); - if (widget.onTextChanged != null) { - widget.onTextChanged!(''); - } - focusNode.unfocus(); - }, - child: Container( - padding: const EdgeInsets.only(left: 16), - child: Text(context.resource.cancel, - style: TextStyle( - fontSize: getSize(context)?.size, - color: TDTheme.of(context).brandNormalColor)), - ), - ), - ), + offstage: cancelBtnHide || !widget.needCancel, + child: GestureDetector( + onTap: () { + _cleanInputText(); + if (widget.onTextChanged != null) { + widget.onTextChanged!(''); + } + focusNode.unfocus(); + }, + child: Container( + padding: const EdgeInsets.only(left: 16), + child: Text(context.resource.cancel, + style: TextStyle( + fontSize: getSize(context)?.size, + color: TDTheme.of(context).brandNormalColor)), + ), + ), + ), ], ), ]), ); } - } diff --git a/tdesign-component/lib/src/components/sidebar/td_sidebar.dart b/tdesign-component/lib/src/components/sidebar/td_sidebar.dart index 70f82eaa5..e9fdda43e 100644 --- a/tdesign-component/lib/src/components/sidebar/td_sidebar.dart +++ b/tdesign-component/lib/src/components/sidebar/td_sidebar.dart @@ -17,14 +17,15 @@ class SideItemProps { TDBadge? badge; TextStyle? textStyle; - SideItemProps( - {required this.value, - required this.index, - this.disabled, - this.icon, - this.label, - this.badge, - this.textStyle}); + SideItemProps({ + required this.value, + required this.index, + this.disabled, + this.icon, + this.label, + this.badge, + this.textStyle, + }); } class TDSideBar extends StatefulWidget { @@ -197,26 +198,26 @@ class _TDSideBarState extends State { .asMap() .entries .map((entry) => SideItemProps( - index: entry.key, - disabled: entry.value.disabled, - value: entry.value.value, - icon: entry.value.icon, - label: entry.value.label, - textStyle: entry.value.textStyle, - badge: entry.value.badge)) + index: entry.key, + disabled: entry.value.disabled, + value: entry.value.value, + icon: entry.value.icon, + label: entry.value.label, + textStyle: entry.value.textStyle, + badge: entry.value.badge)) .toList(); - } else if(widget.children.isNotEmpty) { + } else if (widget.children.isNotEmpty) { displayChildren = widget.children .asMap() .entries .map((entry) => SideItemProps( - index: entry.key, - disabled: entry.value.disabled, - value: entry.value.value, - icon: entry.value.icon, - label: entry.value.label, - textStyle: entry.value.textStyle, - badge: entry.value.badge)) + index: entry.key, + disabled: entry.value.disabled, + value: entry.value.value, + icon: entry.value.icon, + label: entry.value.label, + textStyle: entry.value.textStyle, + badge: entry.value.badge)) .toList(); } else { displayChildren = []; @@ -244,15 +245,16 @@ class _TDSideBarState extends State { @override Widget build(BuildContext context) { - if(_loading) { + if (_loading) { widget.controller?.loading = true; - if(widget.loadingWidget != null) { + if (widget.loadingWidget != null) { return widget.loadingWidget!; } return SizedBox( width: MediaQuery.of(context).size.width, child: const Align( - child: TDLoading(icon: TDLoadingIcon.circle, size: TDLoadingSize.large), + child: + TDLoading(icon: TDLoadingIcon.circle, size: TDLoadingSize.large), ), ); } @@ -262,7 +264,6 @@ class _TDSideBarState extends State { minWidth: 106, maxHeight: MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top), - child: SizedBox( height: widget.height ?? MediaQuery.of(context).size.height, child: MediaQuery.removePadding( @@ -285,16 +286,18 @@ class _TDSideBarState extends State { badge: ele.badge, textStyle: ele.textStyle, selected: currentIndex == ele.index, - selectedColor:widget.selectedColor, + selectedColor: widget.selectedColor, unSelectedColor: widget.unSelectedColor, - selectedTextStyle:widget.selectedTextStyle, - contentPadding:widget.contentPadding, + selectedTextStyle: widget.selectedTextStyle, + contentPadding: widget.contentPadding, topAdjacent: currentIndex != null && currentIndex! + 1 == ele.index, bottomAdjacent: currentIndex != null && currentIndex! - 1 == ele.index, - selectedBgColor: widget.selectedBgColor, - unSelectedBgColor: widget.unSelectedBgColor, + selectedBgColor: widget.selectedBgColor ?? + TDTheme.of(context).bgColorContainer, + unSelectedBgColor: widget.unSelectedBgColor ?? + TDTheme.of(context).bgColorSecondaryContainer, onTap: () { if (!(ele.disabled ?? false)) { onSelect(ele, isController: false); diff --git a/tdesign-component/lib/src/components/sidebar/td_wrap_sidebar_item.dart b/tdesign-component/lib/src/components/sidebar/td_wrap_sidebar_item.dart index 10357dddf..eb15c3b84 100644 --- a/tdesign-component/lib/src/components/sidebar/td_wrap_sidebar_item.dart +++ b/tdesign-component/lib/src/components/sidebar/td_wrap_sidebar_item.dart @@ -46,40 +46,45 @@ class TDWrapSideBarItem extends StatelessWidget { final TDSideBarStyle style; static const preLineWidth = 3.0; + @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, - child: style == TDSideBarStyle.normal ? renderNormalItem(context) : renderOutlineItem(context), + child: style == TDSideBarStyle.normal + ? renderNormalItem(context) + : renderOutlineItem(context), ); } Widget renderNormalItem(BuildContext context) { return Container( decoration: BoxDecoration( - color: selectedBgColor ?? Colors.white, + color: selectedBgColor ?? TDTheme.of(context).bgColorContainer, ), child: Container( decoration: BoxDecoration( - color: selected - ? (selectedBgColor ?? Colors.white) - : (unSelectedBgColor ?? const Color.fromRGBO(243, 243, 243, 1)), - borderRadius: bottomAdjacent || topAdjacent - ? bottomAdjacent - ? const BorderRadius.only(bottomRight: Radius.circular(9)) - : const BorderRadius.only(topRight: Radius.circular(9)) - : null), + color: selected + ? selectedBgColor ?? TDTheme.of(context).bgColorContainer + : unSelectedBgColor ?? + TDTheme.of(context).bgColorSecondaryContainer, + borderRadius: BorderRadius.only( + topRight: Radius.circular( + topAdjacent ? TDTheme.of(context).radiusLarge : 0), + bottomRight: Radius.circular( + bottomAdjacent ? TDTheme.of(context).radiusLarge : 0), + ), + ), child: Row( children: [ - renderPreLine(context), - Expanded( - child: Padding( - padding: contentPadding ?? const EdgeInsets.all(16), - child: renderMainContent(context) - )) - ], - ), + renderPreLine(context), + Expanded( + child: Padding( + padding: contentPadding ?? const EdgeInsets.all(16), + child: renderMainContent(context))) + ], ), + ), ); } @@ -88,11 +93,16 @@ class TDWrapSideBarItem extends StatelessWidget { constraints: const BoxConstraints(minHeight: 56), child: Container( // height: 86, - decoration: const BoxDecoration(color: Color.fromRGBO(246, 246, 246, 1)), + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorSecondaryContainer), padding: const EdgeInsets.all(8), child: Container( decoration: BoxDecoration( - color: selected && !disabled ? Colors.white : null, borderRadius: BorderRadius.circular(6)), + color: selected && !disabled + ? TDTheme.of(context).bgColorContainer + : null, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)), padding: const EdgeInsets.all(8), child: renderMainContent(context), ), @@ -100,15 +110,12 @@ class TDWrapSideBarItem extends StatelessWidget { } Widget renderMainContent(BuildContext context) { - return Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ renderIcon(context), - Expanded( - child: renderLabel(context)), - if(label.length>4) - renderBadge(context), + Expanded(child: renderLabel(context)), + if (label.length > 4) renderBadge(context), // SizedBox( // width: !disabled && selected ? 0 : preLineWidth, // ) @@ -140,50 +147,64 @@ class TDWrapSideBarItem extends StatelessWidget { } Widget renderIcon(BuildContext context) { + final iconColor = () { + if (disabled) { + return TDTheme.of(context).textColorDisabled; + } + if (!selected) { + return unSelectedColor ?? TDTheme.of(context).textColorPrimary; + } + if (selectedTextStyle?.color != null) { + return selectedTextStyle!.color!; + } + return selectedColor ?? TDTheme.of(context).brandNormalColor; + }(); + return Visibility( - visible: icon != null, - child: Padding( - padding: const EdgeInsets.only(right: 2), - child: Icon( - icon, - size: 20, - color: disabled - ? TDTheme.of(context).fontGyColor4 - : selected - ? selectedTextStyle != null - ? selectedTextStyle?.color - : (selectedColor ?? TDTheme.of(context).brandNormalColor) - : unSelectedColor ?? Colors.black, - ), - )); + visible: icon != null, + child: Padding( + padding: const EdgeInsets.only(right: 2), + child: Icon(icon, size: 20, color: iconColor), + ), + ); } Widget renderLabel(BuildContext context) { - return TDText.rich( + return TDText.rich( TextSpan( children: [ WidgetSpan( child: TDText( - label, - style: selected ? (selectedTextStyle ?? TextStyle(color: selectedColor)) : textStyle, - fontWeight: selected && !disabled ? FontWeight.w600 : FontWeight.w400, - textColor: disabled - ? TDTheme.of(context).fontGyColor4 - : selected + label, + style: selected + ? (selectedTextStyle ?? TextStyle(color: selectedColor)) + : textStyle, + fontWeight: + selected && !disabled ? FontWeight.w600 : FontWeight.w400, + textColor: disabled + ? TDTheme.of(context).textColorDisabled + : selected ? selectedColor ?? TDTheme.of(context).brandNormalColor - : unSelectedColor ?? Colors.black, - // forceVerticalCenter: true, - )), - if(label.length<4) - WidgetSpan( - child: SizedBox( - width: 1, - height: 16, - child: Stack( - clipBehavior: Clip.none, - children: [badge != null ? Positioned(top: -6, child: badge!) : Container()], - ), - )) + : unSelectedColor ?? TDTheme.of(context).textColorPrimary, + // forceVerticalCenter: true, + )), + + /// todo label.length 长度小于则不展示,为什么??? + /// 应再判断有无icon,无icon时位置够,可以展示 badge + if (label.length <= 4 || icon == null) + WidgetSpan( + child: SizedBox( + width: 1, + height: 16, + child: Stack( + clipBehavior: Clip.none, + children: [ + badge != null + ? Positioned(top: -6, child: badge!) + : Container() + ], + ), + )) ], ), softWrap: true, @@ -194,10 +215,12 @@ class TDWrapSideBarItem extends StatelessWidget { Widget renderBadge(BuildContext context) { return SizedBox( width: 1, - height:40, + height: 40, child: Stack( clipBehavior: Clip.none, - children: [badge != null ? Positioned(top: -6, child: badge!) : Container()], + children: [ + badge != null ? Positioned(top: -6, child: badge!) : Container() + ], ), ); } diff --git a/tdesign-component/lib/src/components/skeleton/td_skeleton.dart b/tdesign-component/lib/src/components/skeleton/td_skeleton.dart index 8cfa5e94c..8126e233c 100644 --- a/tdesign-component/lib/src/components/skeleton/td_skeleton.dart +++ b/tdesign-component/lib/src/components/skeleton/td_skeleton.dart @@ -2,22 +2,28 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; -/// /// 骨架图动画 -/// enum TDSkeletonAnimation { - gradient, // 渐变 - flashed, // 闪烁 + /// 渐变 + gradient, + + /// 闪烁 + flashed, } -/// /// 骨架图风格 -/// enum TDSkeletonTheme { - avatar, // 头像 - image, // 图片 - text, // 文本 - paragraph, // 段落 + /// 头像 + avatar, + + /// 图片 + image, + + /// 文本 + text, + + /// 段落 + paragraph, } class TDSkeleton extends StatefulWidget { @@ -28,65 +34,54 @@ class TDSkeleton extends StatefulWidget { TDSkeletonTheme theme = TDSkeletonTheme.text, }) { assert(delay >= 0); - + + var objects = >[]; + // 根据风格创建骨架图 switch (theme) { case TDSkeletonTheme.avatar: - return TDSkeleton.fromRowCol( - key: key, - animation: animation, - delay: delay, - rowCol: TDSkeletonRowCol( - objects: const [ - [TDSkeletonRowColObj.circle()] - ], - ), - ); + objects = const [ + [TDSkeletonRowColObj.circle()] + ]; + break; case TDSkeletonTheme.image: - return TDSkeleton.fromRowCol( - key: key, - animation: animation, - delay: delay, - rowCol: TDSkeletonRowCol( - objects: const [ - [ - TDSkeletonRowColObj.rect( - width: 72, - height: 72, - flex: null, - ) - ] - ], - ), - ); + objects = const [ + [ + TDSkeletonRowColObj.rect( + width: 72, + height: 72, + flex: null, + ) + ] + ]; + break; case TDSkeletonTheme.text: - return TDSkeleton.fromRowCol( - key: key, - animation: animation, - delay: delay, - rowCol: TDSkeletonRowCol(objects: const [ - [ - TDSkeletonRowColObj.text(flex: 24), - TDSkeletonRowColObj.spacer(width: 16), - TDSkeletonRowColObj.text(flex: 76), - ], - [TDSkeletonRowColObj.text()], - ]), - ); + objects = const [ + [ + TDSkeletonRowColObj.text(flex: 24), + TDSkeletonRowColObj.spacer(width: 16), + TDSkeletonRowColObj.text(flex: 76), + ], + [TDSkeletonRowColObj.text()], + ]; + break; case TDSkeletonTheme.paragraph: - return TDSkeleton.fromRowCol( - key: key, - animation: animation, - delay: delay, - rowCol: TDSkeletonRowCol(objects: [ - for (int i = 0; i < 3; i++) [const TDSkeletonRowColObj.text()], - const [ - TDSkeletonRowColObj.text(flex: 55), - TDSkeletonRowColObj.spacer(flex: 45), - ], - ]), - ); + objects = [ + for (int i = 0; i < 3; i++) [const TDSkeletonRowColObj.text()], + const [ + TDSkeletonRowColObj.text(flex: 55), + TDSkeletonRowColObj.spacer(flex: 45), + ], + ]; + break; } + + return TDSkeleton.fromRowCol( + key: key, + animation: animation, + delay: delay, + rowCol: TDSkeletonRowCol(objects: objects), + ); } /// 从行列框架创建骨架屏 @@ -95,7 +90,7 @@ class TDSkeleton extends StatefulWidget { this.animation, this.delay = 0, required this.rowCol, - }): assert(delay >= 0); + }) : assert(delay >= 0); /// 动画效果 final TDSkeletonAnimation? animation; @@ -132,7 +127,7 @@ class _TDSkeletonState extends State LinearGradient( colors: [ Colors.transparent, - TDTheme.of(context).grayColor4, + TDTheme.of(context).bgColorSecondaryContainerActive, Colors.transparent, ], // 15 deg @@ -160,7 +155,8 @@ class _TDSkeletonState extends State duration: const Duration(seconds: 1), vsync: this, )..repeat(reverse: true); - _animation = Tween(begin: 1, end: _animationFlashed).animate(_controller!) + _animation = Tween(begin: 1, end: _animationFlashed) + .animate(_controller!) ..addListener(() => setState(() {})); break; default: @@ -192,7 +188,8 @@ class _TDSkeletonState extends State case TDSkeletonAnimation.gradient: skeletonObj = ShaderMask( blendMode: BlendMode.srcATop, - shaderCallback: (bounds) => _animationGradient(context).createShader( + shaderCallback: (bounds) => + _animationGradient(context).createShader( Rect.fromLTWH( bounds.width * _animation!.value, 0, @@ -241,12 +238,14 @@ class _TDSkeletonState extends State List skeletonRows = widget.rowCol.objects .map((row) => Row(children: row.map(_buildObj(context)).toList())) .toList(); - if (widget.rowCol.style.rowSpacing(context) > 0) { + final rowSpacing = widget.rowCol.style.rowSpacing(context); + if (rowSpacing > 0) { skeletonRows = skeletonRows - .expand((row) => - [row, SizedBox(height: widget.rowCol.style.rowSpacing(context))]) - .toList() - ..removeLast(); + .expand((row) => [row, SizedBox(height: rowSpacing)]) + .toList(); + if (skeletonRows.isNotEmpty) { + skeletonRows.removeLast(); + } } // 添加行间距 var skeletonRowCol = Column(children: skeletonRows); // 行列布局 @@ -255,9 +254,12 @@ class _TDSkeletonState extends State // 添加弹性布局 ? Flexible( child: Container( - constraints: BoxConstraints( - maxHeight: widget.rowCol.visualHeight(context)), // 限制最大高度 - child: skeletonRowCol)) + constraints: BoxConstraints( + maxHeight: widget.rowCol.visualHeight(context), + ), // 限制最大高度 + child: skeletonRowCol, + ), + ) : skeletonRowCol; } diff --git a/tdesign-component/lib/src/components/skeleton/td_skeleton_rowcol.dart b/tdesign-component/lib/src/components/skeleton/td_skeleton_rowcol.dart index 30a8d34f8..39f144854 100644 --- a/tdesign-component/lib/src/components/skeleton/td_skeleton_rowcol.dart +++ b/tdesign-component/lib/src/components/skeleton/td_skeleton_rowcol.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; - /// 骨架屏样式 class TDSkeletonRowColStyle { const TDSkeletonRowColStyle({ @@ -17,7 +16,6 @@ class TDSkeletonRowColStyle { TDTheme.of(context).spacer16; } - /// 骨架屏行列框架 class TDSkeletonRowCol { TDSkeletonRowCol({ @@ -34,7 +32,7 @@ class TDSkeletonRowCol { /// 视觉高度 double visualHeight(BuildContext context) { var rowSpacing = style.rowSpacing(context); - assert (rowSpacing >= 0); + assert(rowSpacing >= 0); if (rowSpacing < 0) { rowSpacing = 0; } @@ -79,7 +77,7 @@ class TDSkeletonRowColObjStyle { /// 默认背景颜色 static Color _defaultBackground(BuildContext context) => - TDTheme.of(context).grayColor1; + TDTheme.of(context).bgColorComponent; /// 透明背景颜色 static Color _transparentBackground(BuildContext context) => @@ -98,7 +96,6 @@ class TDSkeletonRowColObjStyle { TDTheme.of(context).radiusSmall; } - /// 骨架屏元素 class TDSkeletonRowColObj { const TDSkeletonRowColObj({ diff --git a/tdesign-component/lib/src/components/slider/td_slider.dart b/tdesign-component/lib/src/components/slider/td_slider.dart index 2ed46943c..f2063a458 100644 --- a/tdesign-component/lib/src/components/slider/td_slider.dart +++ b/tdesign-component/lib/src/components/slider/td_slider.dart @@ -2,6 +2,9 @@ /// Created by arvinwli@tencent.com on 4/24/23. /// import 'package:flutter/material.dart'; +import '../../theme/td_colors.dart'; +import '../../theme/td_spacers.dart'; +import '../../theme/td_theme.dart'; import 'td_slider_theme.dart'; enum Position { @@ -41,19 +44,19 @@ class TDSlider extends StatefulWidget { /// Thumb 点击浮标文字 坐标、当前值 final Function(Offset offset, double value)? onThumbTextTap; - const TDSlider( - {Key? key, - required this.value, - this.boxDecoration, - this.onChanged, - this.sliderThemeData, - this.leftLabel, - this.rightLabel, - this.onChangeStart, - this.onChangeEnd, - this.onTap, - this.onThumbTextTap}) - : super(key: key); + const TDSlider({ + Key? key, + required this.value, + this.boxDecoration, + this.onChanged, + this.sliderThemeData, + this.leftLabel, + this.rightLabel, + this.onChangeStart, + this.onChangeEnd, + this.onTap, + this.onThumbTextTap, + }) : super(key: key); @override State createState() { @@ -64,6 +67,7 @@ class TDSlider extends StatefulWidget { class TDSliderState extends State { final GlobalKey _sliderKey = GlobalKey(); double value = 0; + @override void initState() { super.initState(); @@ -76,11 +80,13 @@ class TDSliderState extends State { value = widget.value; } - bool get enabled => widget.onChanged != null; + bool get _enabled => widget.onChanged != null; TextStyle get labelTextStyle => TextStyle( fontSize: 16, - color: enabled ? const Color(0xE6000000) : const Color(0x42000000)); + color: _enabled + ? TDTheme.of(context).textColorPrimary + : TDTheme.of(context).textColorDisabled); Widget get leftLabel => widget.leftLabel?.isNotEmpty == true ? Padding( @@ -99,6 +105,10 @@ class TDSliderState extends State { @override Widget build(BuildContext context) { var tdSliderThemeData = widget.sliderThemeData ?? TDSliderThemeData(); + + final showValue = + tdSliderThemeData.showScaleValue || tdSliderThemeData.showThumbValue; + return Listener( onPointerDown: (event) { final sliderBox = @@ -119,25 +129,20 @@ class TDSliderState extends State { }, child: Container( padding: EdgeInsets.only( - top: (tdSliderThemeData.showScaleValue || - tdSliderThemeData.showThumbValue - ? 16 - : 0) + - 8, + top: (showValue ? 16 : 0) + 8, bottom: 8, ), decoration: widget.boxDecoration ?? - const BoxDecoration( - color: Colors.white, - ), + BoxDecoration(color: TDTheme.of(context).bgColorContainer), child: Row( + // spacing: TDTheme.of(context).spacer8, children: [ leftLabel, const SizedBox(width: 8), Expanded( child: Listener( onPointerDown: (event) { - if (!enabled || widget.onTap == null) { + if (!_enabled || widget.onTap == null) { return; } @@ -160,7 +165,7 @@ class TDSliderState extends State { divisions: tdSliderThemeData.divisions, onChangeStart: widget.onChangeStart, onChangeEnd: widget.onChangeEnd, - onChanged: enabled + onChanged: _enabled ? (slideValue) { setState(() { value = slideValue; @@ -208,26 +213,33 @@ class TDRangeSlider extends StatefulWidget { /// 样式 final TDSliderThemeData? sliderThemeData; - // Thumb 点击事件 位置、坐标、当前值 - final Function(Position position, Offset offset, double value)? onTap; - - /// Thumb 点击浮标文字 位置、坐标、当前值 - final Function(Position position, Offset offset, double value)? - onThumbTextTap; - - const TDRangeSlider( - {Key? key, - required this.value, - this.boxDecoration, - this.onChanged, - this.sliderThemeData, - this.leftLabel, - this.rightLabel, - this.onChangeStart, - this.onChangeEnd, - this.onTap, - this.onThumbTextTap}) - : super(key: key); + /// Thumb 点击事件 位置、坐标、当前值 + final Function( + Position position, + Offset offset, + double value, + )? onTap; + + /// Thumb 点击浮标文字 位置、坐标、当前值 + final Function( + Position position, + Offset offset, + double value, + )? onThumbTextTap; + + const TDRangeSlider({ + Key? key, + required this.value, + this.boxDecoration, + this.onChanged, + this.sliderThemeData, + this.leftLabel, + this.rightLabel, + this.onChangeStart, + this.onChangeEnd, + this.onTap, + this.onThumbTextTap, + }) : super(key: key); @override State createState() { @@ -251,11 +263,13 @@ class _TDRangeSliderState extends State { rangeValues = widget.value; } - bool get enabled => widget.onChanged != null; + bool get _enabled => widget.onChanged != null; TextStyle get labelTextStyle => TextStyle( fontSize: 16, - color: enabled ? const Color(0xE6000000) : const Color(0x42000000)); + color: _enabled + ? TDTheme.of(context).textColorPrimary + : TDTheme.of(context).textColorDisabled); Widget get leftLabel => widget.leftLabel?.isNotEmpty == true ? Padding( @@ -274,6 +288,8 @@ class _TDRangeSliderState extends State { @override Widget build(BuildContext context) { var tdSliderThemeData = widget.sliderThemeData ?? TDSliderThemeData(); + final showValue = + tdSliderThemeData.showScaleValue || tdSliderThemeData.showThumbValue; return Listener( onPointerDown: (event) { @@ -294,33 +310,32 @@ class _TDRangeSliderState extends State { final endTextRect = themeData.sliderMeasureData.endRangeThumbTextRect; if (startTextRect?.contains(localOffset) ?? false) { - widget.onThumbTextTap?.call(Position.start, localOffset, rangeValues.start); + widget.onThumbTextTap + ?.call(Position.start, localOffset, rangeValues.start); } if (endTextRect?.contains(localOffset) ?? false) { - widget.onThumbTextTap?.call(Position.end, localOffset, rangeValues.end); + widget.onThumbTextTap + ?.call(Position.end, localOffset, rangeValues.end); } }, child: Container( padding: EdgeInsets.only( - top: (tdSliderThemeData.showScaleValue || - tdSliderThemeData.showThumbValue - ? 16 - : 0) + - 8, + top: (showValue ? 16 : 0) + 8, bottom: 8, ), decoration: widget.boxDecoration ?? - const BoxDecoration( - color: Colors.white, + BoxDecoration( + color: TDTheme.of(context).bgColorContainer, ), child: Row( + // spacing: 8, children: [ leftLabel, const SizedBox(width: 8), Expanded( child: Listener( onPointerDown: (PointerDownEvent event) { - if (!enabled || widget.onTap == null) { + if (!_enabled || widget.onTap == null) { return; } @@ -336,7 +351,7 @@ class _TDRangeSliderState extends State { final sliderTheme = SliderTheme.of(context); final thumbShape = sliderTheme.rangeThumbShape; final thumbSize = thumbShape?.getPreferredSize( - enabled, + _enabled, widget.sliderThemeData?.divisions != null, ) ?? const Size(20, 20); diff --git a/tdesign-component/lib/src/components/slider/td_slider_theme.dart b/tdesign-component/lib/src/components/slider/td_slider_theme.dart index 8309aacea..51f86e6e3 100644 --- a/tdesign-component/lib/src/components/slider/td_slider_theme.dart +++ b/tdesign-component/lib/src/components/slider/td_slider_theme.dart @@ -7,43 +7,44 @@ import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; -///刻度显示格式化 +/// 刻度显示格式化 typedef ScaleFormatter = String Function(double value); /// 修改系统主题的回调 typedef OnSliderThemeDataUpdate = SliderThemeData Function( - SliderThemeData sliderThemeData); + SliderThemeData sliderThemeData, +); -///slider显示样式配置 +/// slider显示样式配置 class TDSliderThemeData { - ///是否显示游标值 + /// 是否显示游标值 final bool showThumbValue; - ///游标上文本样式 + /// 游标上文本样式 final TextStyle? thumbTextStyle; - ///disable时游标的样式 + /// disable时游标的样式 final TextStyle disabledThumbTextStyle; - ///是否显示刻度值 + /// 是否显示刻度值 final bool showScaleValue; - ///刻度值的格式化 + /// 刻度值的格式化 final ScaleFormatter? scaleFormatter; - ///刻度值的样式 + /// 刻度值的样式 final TextStyle? scaleTextStyle; - ///disabled状态时刻度的样式 + /// disabled状态时刻度的样式 final TextStyle disabledScaleTextStyle; - ///分割几块 + /// 分割几块 final int? divisions; - ///最小值 + /// 最小值 final double min; - ///最大值 + /// 最大值 final double max; /// 运行时测量的数据,这里用于组件内部使用 @@ -81,13 +82,25 @@ class TDSliderThemeData { this.inactiveTrackColor, SliderThemeData? sliderThemeData, }) : scaleTextStyle = scaleTextStyle ?? - TextStyle(fontSize: 14, color: TDTheme.of(context).fontGyColor1), + TextStyle( + fontSize: 14, + color: TDTheme.of(context).textColorPrimary, + ), disabledScaleTextStyle = disabledScaleTextStyle ?? - TextStyle(fontSize: 14, color: TDTheme.of(context).fontGyColor4), + TextStyle( + fontSize: 14, + color: TDTheme.of(context).textColorPlaceholder, + ), thumbTextStyle = thumbTextStyle ?? - TextStyle(fontSize: 14, color: TDTheme.of(context).fontGyColor1), + TextStyle( + fontSize: 14, + color: TDTheme.of(context).textColorPrimary, + ), disabledThumbTextStyle = disabledThumbTextStyle ?? - TextStyle(fontSize: 14, color: TDTheme.of(context).fontGyColor4), + TextStyle( + fontSize: 14, + color: TDTheme.of(context).textColorPlaceholder, + ), _sliderThemeData = sliderThemeData, _capsule = false; @@ -108,13 +121,25 @@ class TDSliderThemeData { this.inactiveTrackColor, SliderThemeData? sliderThemeData, }) : scaleTextStyle = scaleTextStyle ?? - TextStyle(fontSize: 14, color: TDTheme.of(context).fontGyColor1), + TextStyle( + fontSize: 14, + color: TDTheme.of(context).textColorPrimary, + ), disabledScaleTextStyle = disabledScaleTextStyle ?? - TextStyle(fontSize: 14, color: TDTheme.of(context).fontGyColor4), + TextStyle( + fontSize: 14, + color: TDTheme.of(context).textColorPlaceholder, + ), thumbTextStyle = thumbTextStyle ?? - TextStyle(fontSize: 14, color: TDTheme.of(context).fontGyColor1), + TextStyle( + fontSize: 14, + color: TDTheme.of(context).textColorPrimary, + ), disabledThumbTextStyle = disabledThumbTextStyle ?? - TextStyle(fontSize: 14, color: TDTheme.of(context).fontGyColor4), + TextStyle( + fontSize: 14, + color: TDTheme.of(context).textColorPlaceholder, + ), _sliderThemeData = sliderThemeData, _capsule = true; @@ -135,21 +160,25 @@ class TDSliderThemeData { trackHeight: 4, activeTrackColor: activeTrackColor ?? TDTheme.of(context).brandNormalColor, - inactiveTrackColor: inactiveTrackColor ?? TDTheme.of(context).grayColor4, + inactiveTrackColor: + inactiveTrackColor ?? TDTheme.of(context).bgColorComponent, disabledActiveTrackColor: TDTheme.of(context).brandDisabledColor, - disabledInactiveTrackColor: TDTheme.of(context).grayColor2, + disabledInactiveTrackColor: TDTheme.of(context).bgColorComponentDisabled, activeTickMarkColor: TDTheme.of(context).brandNormalColor, - inactiveTickMarkColor: TDTheme.of(context).grayColor4, + inactiveTickMarkColor: TDTheme.of(context).bgColorComponent, disabledActiveTickMarkColor: TDTheme.of(context).brandDisabledColor, - disabledInactiveTickMarkColor: TDTheme.of(context).grayColor2, + disabledInactiveTickMarkColor: + TDTheme.of(context).bgColorComponentDisabled, thumbColor: Colors.white, - disabledThumbColor: Colors.white, + disabledThumbColor: TDTheme.of(context).bgColorSecondaryContainer, overlayShape: const TDNoOverlayShape(), tickMarkShape: TDRoundSliderTickMarkShape(themeData: this), - thumbShape: TDRoundSliderThumbShape(themeData: this), + thumbShape: + TDRoundSliderThumbShape(themeData: this, buildContext: context), trackShape: TDRoundedRectSliderTrackShape(themeData: this), rangeTickMarkShape: TDRoundRangeSliderTickMarkShape(themeData: this), - rangeThumbShape: TDRoundRangeSliderThumbShape(themeData: this), + rangeThumbShape: + TDRoundRangeSliderThumbShape(themeData: this, buildContext: context), rangeTrackShape: TDRoundedRectRangeSliderTrackShape(themeData: this), showValueIndicator: ShowValueIndicator.never, ); @@ -158,24 +187,31 @@ class TDSliderThemeData { /// 构建胶囊型系统主题 SliderThemeData capsule() { return SliderThemeData( - trackShape: TDCapsuleRectSliderTrackShape(themeData: this), + trackShape: TDCapsuleRectSliderTrackShape( + themeData: this, + trackColorWhenShowScale: TDTheme.of(context).bgColorContainerActive), tickMarkShape: TDCapsuleSliderTickMarkShape(themeData: this), - thumbShape: TDCapsuleSliderThumbShape(themeData: this), - rangeTrackShape: TDCapsuleRectRangeSliderTrackShape(themeData: this), + thumbShape: + TDCapsuleSliderThumbShape(themeData: this, buildContext: context), + rangeTrackShape: TDCapsuleRectRangeSliderTrackShape( + themeData: this, + trackColorWhenShowScale: TDTheme.of(context).bgColorContainerActive), rangeTickMarkShape: TDCapsuleRangeSliderTickMarkShape(themeData: this), - rangeThumbShape: TDCapsuleRangeSliderThumbShape(themeData: this), - activeTickMarkColor: TDTheme.of(context).grayColor3, - inactiveTickMarkColor: TDTheme.of(context).grayColor3, - disabledActiveTickMarkColor: TDTheme.of(context).grayColor3, - disabledInactiveTickMarkColor: TDTheme.of(context).grayColor3, + rangeThumbShape: TDCapsuleRangeSliderThumbShape( + themeData: this, buildContext: context), + activeTickMarkColor: TDTheme.of(context).bgColorContainerActive, + inactiveTickMarkColor: TDTheme.of(context).bgColorContainerActive, + disabledActiveTickMarkColor: TDTheme.of(context).bgColorContainerActive, + disabledInactiveTickMarkColor: TDTheme.of(context).bgColorContainerActive, thumbColor: Colors.white, - disabledThumbColor: Colors.white, + disabledThumbColor: TDTheme.of(context).bgColorSecondaryContainer, trackHeight: 24, activeTrackColor: activeTrackColor ?? TDTheme.of(context).brandNormalColor, - inactiveTrackColor: inactiveTrackColor ?? TDTheme.of(context).grayColor4, + inactiveTrackColor: + inactiveTrackColor ?? TDTheme.of(context).bgColorComponent, disabledActiveTrackColor: TDTheme.of(context).brandDisabledColor, - disabledInactiveTrackColor: TDTheme.of(context).grayColor2, + disabledInactiveTrackColor: TDTheme.of(context).bgColorComponentDisabled, overlayShape: const TDNoOverlayShape(), showValueIndicator: ShowValueIndicator.never, ); @@ -225,9 +261,7 @@ class SliderMeasureData { Rect? endRangeThumbTextRect; } -/// -///Slider轨道绘制 -/// +/// Slider轨道绘制 class TDRoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackShape { /// Create a slider track that draws two rectangles with rounded outer edges. @@ -293,7 +327,7 @@ class TDRoundedRectSliderTrackShape extends SliderTrackShape isEnabled: isEnabled, isDiscrete: isDiscrete, ); - //record size ,Use it when calculating thumb text position + // record size ,Use it when calculating thumb text position themeData.sliderMeasureData.trackerRect = trackRect; final trackRadius = Radius.circular(trackRect.height / 2); final activeTrackRadius = @@ -340,9 +374,7 @@ class TDRoundedRectSliderTrackShape extends SliderTrackShape } } -/// -///游标的绘制 -/// +/// 游标的绘制 class TDRoundSliderThumbShape extends SliderComponentShape { /// Create a slider thumb that draws a circle. const TDRoundSliderThumbShape({ @@ -351,6 +383,7 @@ class TDRoundSliderThumbShape extends SliderComponentShape { this.elevation = 4.0, this.pressedElevation = 4.0, required this.themeData, + required this.buildContext, }); /// The preferred radius of the round thumb shape when the slider is enabled. @@ -385,6 +418,8 @@ class TDRoundSliderThumbShape extends SliderComponentShape { final TDSliderThemeData themeData; + final BuildContext? buildContext; + @override Size getPreferredSize(bool isEnabled, bool isDiscrete) { return Size.fromRadius( @@ -488,7 +523,7 @@ class TDRoundSliderThumbShape extends SliderComponentShape { Paint() ..style = PaintingStyle.stroke ..strokeWidth = 1 - ..color = TDTheme.of().grayColor3); + ..color = TDTheme.of(buildContext).componentStrokeColor); } } @@ -853,6 +888,7 @@ class TDRoundRangeSliderThumbShape extends RangeSliderThumbShape { this.elevation = 3.0, this.pressedElevation = 3.0, required this.themeData, + required this.buildContext, }); /// The preferred radius of the round thumb shape when the slider is enabled. @@ -880,6 +916,8 @@ class TDRoundRangeSliderThumbShape extends RangeSliderThumbShape { final TDSliderThemeData themeData; + final BuildContext? buildContext; + @override Size getPreferredSize(bool isEnabled, bool isDiscrete) { return Size.fromRadius( @@ -987,6 +1025,15 @@ class TDRoundRangeSliderThumbShape extends RangeSliderThumbShape { radius, Paint()..color = color, ); + canvas.drawArc( + Rect.fromCircle(center: center, radius: radius), + 0, + 2 * math.pi, + false, + Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = 1 + ..color = TDTheme.of(buildContext).componentStrokeColor); } } @@ -1134,6 +1181,7 @@ mixin TDCapsuleTrackShape { abstract interface class TDCapsuleRectThemeData { final TDSliderThemeData themeData; + TDCapsuleRectThemeData({required this.themeData}); } @@ -1142,7 +1190,7 @@ mixin TDCapsuleRectAdjustment implements TDCapsuleRectThemeData { hasDivisions() { return themeData.divisions != null && themeData.divisions! > 0; } - + // 胶囊类型适配样式边距 trackHeight / 2,默认是 12 extraPadding({trackHeight = 24}) { if (hasDivisions()) { @@ -1163,12 +1211,13 @@ mixin TDCapsuleRectAdjustment implements TDCapsuleRectThemeData { /// ///Slider轨道绘制 /// -class TDCapsuleRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackShape, TDCapsuleTrackShape, TDCapsuleRectAdjustment { - +class TDCapsuleRectSliderTrackShape extends SliderTrackShape + with BaseSliderTrackShape, TDCapsuleTrackShape, TDCapsuleRectAdjustment { /// Create a slider track that draws two rectangles with rounded outer edges. - const TDCapsuleRectSliderTrackShape( - {this.trackColorWhenShowScale = const Color(0xFFE7E7E7), - required this.themeData}); + const TDCapsuleRectSliderTrackShape({ + required this.trackColorWhenShowScale, + required this.themeData, + }); final Color trackColorWhenShowScale; @@ -1190,7 +1239,8 @@ class TDCapsuleRectSliderTrackShape extends SliderTrackShape with BaseSliderTrac isDiscrete: isDiscrete, ); final padding = extraPadding(); - var realRect = Rect.fromLTRB(rect.left + padding, rect.top, rect.right - padding, rect.bottom); + var realRect = Rect.fromLTRB( + rect.left + padding, rect.top, rect.right - padding, rect.bottom); themeData.sliderMeasureData.trackerRect = realRect; return realRect; } @@ -1262,8 +1312,12 @@ class TDCapsuleRectSliderTrackShape extends SliderTrackShape with BaseSliderTrac final padding = extraPadding(); context.canvas.drawRRect( - RRect.fromLTRBAndCorners(trackRect.left - padding, trackRect.top, trackRect.right + padding, trackRect.bottom, - topLeft: trackRadius, bottomLeft: trackRadius, topRight: trackRadius, bottomRight: trackRadius), + RRect.fromLTRBAndCorners(trackRect.left - padding, trackRect.top, + trackRect.right + padding, trackRect.bottom, + topLeft: trackRadius, + bottomLeft: trackRadius, + topRight: trackRadius, + bottomRight: trackRadius), inactiveTrackPaint, ); context.canvas.drawRRect( @@ -1295,17 +1349,17 @@ class TDCapsuleRectSliderTrackShape extends SliderTrackShape with BaseSliderTrac } } -/// -///游标的绘制 -/// -class TDCapsuleSliderThumbShape extends SliderComponentShape with TDCapsuleRectAdjustment { +/// 胶囊型游标绘制 +class TDCapsuleSliderThumbShape extends SliderComponentShape + with TDCapsuleRectAdjustment { /// Create a slider thumb that draws a circle. const TDCapsuleSliderThumbShape({ - this.enabledThumbRadius = 10.0, + this.enabledThumbRadius = 9.0, this.disabledThumbRadius, this.elevation = 4.0, this.pressedElevation = 4.0, required this.themeData, + required this.buildContext, }); /// The preferred radius of the round thumb shape when the slider is enabled. @@ -1341,6 +1395,8 @@ class TDCapsuleSliderThumbShape extends SliderComponentShape with TDCapsuleRectA @override final TDSliderThemeData themeData; + final BuildContext? buildContext; + @override Size getPreferredSize(bool isEnabled, bool isDiscrete) { return Size.fromRadius( @@ -1401,7 +1457,8 @@ class TDCapsuleSliderThumbShape extends SliderComponentShape with TDCapsuleRectA themeData.sliderMeasureData.trackerRect != null) { var trackerRect = themeData.sliderMeasureData.trackerRect!; final padding = trackPadding(); - var ratio = (center.dx - trackerRect.left - padding) / (trackerRect.right - trackerRect.left - padding * 2); + var ratio = (center.dx - trackerRect.left - padding) / + (trackerRect.right - trackerRect.left - padding * 2); //计算滑块的值 var value = (themeData.max - themeData.min) * ratio + themeData.min; //格式化显示 @@ -1438,7 +1495,7 @@ class TDCapsuleSliderThumbShape extends SliderComponentShape with TDCapsuleRectA Paint() ..style = PaintingStyle.stroke ..strokeWidth = 1 - ..color = TDTheme.of().grayColor1); + ..color = TDTheme.of(buildContext).componentStrokeColor); } } @@ -1538,19 +1595,26 @@ class TDCapsuleSliderTickMarkShape extends SliderTickMarkShape { textAlign: TextAlign.center) ..layout(maxWidth: 100); var x = dx - painter.size.width / 2; - painter.paint(context.canvas, Offset(x, center.dy - painter.height - 16)); + painter.paint( + context.canvas, Offset(x, center.dy - painter.height - 16)); // 第一个和最后一个不展示 if (index > 0 && index < themeData.divisions!) { final isBetweenThumbs = thumbCenter.dx > center.dx; - final begin = - isBetweenThumbs ? sliderTheme.disabledActiveTickMarkColor : sliderTheme.disabledInactiveTickMarkColor; - final end = isBetweenThumbs ? sliderTheme.activeTickMarkColor : sliderTheme.inactiveTickMarkColor; + final begin = isBetweenThumbs + ? sliderTheme.disabledActiveTickMarkColor + : sliderTheme.disabledInactiveTickMarkColor; + final end = isBetweenThumbs + ? sliderTheme.activeTickMarkColor + : sliderTheme.inactiveTickMarkColor; final paint = Paint() ..strokeWidth = 2 - ..color = ColorTween(begin: begin, end: end).evaluate(enableAnimation)!; - context.canvas.drawLine(Offset(dx, themeData.sliderMeasureData.trackerRect!.top + 3), - Offset(dx, themeData.sliderMeasureData.trackerRect!.bottom - 3), paint); + ..color = + ColorTween(begin: begin, end: end).evaluate(enableAnimation)!; + context.canvas.drawLine( + Offset(dx, themeData.sliderMeasureData.trackerRect!.top + 3), + Offset(dx, themeData.sliderMeasureData.trackerRect!.bottom - 3), + paint); } } } @@ -1584,16 +1648,18 @@ class TDCapsuleSliderTickMarkShape extends SliderTickMarkShape { /// * [RangeSliderTrackShape], which can be used to create custom shapes for /// the [RangeSlider]'s track. /// * [RectangularRangeSliderTrackShape], for a similar track with sharp edges. -class TDCapsuleRectRangeSliderTrackShape extends RangeSliderTrackShape with TDBaseRangeSliderTrackShape, TDCapsuleRectAdjustment { +class TDCapsuleRectRangeSliderTrackShape extends RangeSliderTrackShape + with TDBaseRangeSliderTrackShape, TDCapsuleRectAdjustment { final Color trackColorWhenShowScale; /// Create a slider track with rounded outer edges. /// /// The middle track segment is the selected range and is active, and the two /// outer track segments are inactive. - const TDCapsuleRectRangeSliderTrackShape( - {this.trackColorWhenShowScale = const Color(0xFFE7E7E7), - required this.themeData}); + const TDCapsuleRectRangeSliderTrackShape({ + required this.trackColorWhenShowScale, + required this.themeData, + }); @override final TDSliderThemeData themeData; @@ -1613,7 +1679,8 @@ class TDCapsuleRectRangeSliderTrackShape extends RangeSliderTrackShape with TDBa isDiscrete: isDiscrete, ); final padding = extraPadding(); - return Rect.fromLTRB(rect.left + padding, rect.top, rect.right - padding, rect.bottom); + return Rect.fromLTRB( + rect.left + padding, rect.top, rect.right - padding, rect.bottom); } @override @@ -1751,14 +1818,16 @@ class TDCapsuleRectRangeSliderTrackShape extends RangeSliderTrackShape with TDBa /// * [RangeSlider], which includes thumbs defined by this shape. /// * [SliderTheme], which can be used to configure the thumb shapes of all /// range sliders in a widget subtree. -class TDCapsuleRangeSliderThumbShape extends RangeSliderThumbShape with TDCapsuleRectAdjustment { +class TDCapsuleRangeSliderThumbShape extends RangeSliderThumbShape + with TDCapsuleRectAdjustment { /// Create a slider thumb that draws a circle. const TDCapsuleRangeSliderThumbShape({ - this.enabledThumbRadius = 10.0, + this.enabledThumbRadius = 9.0, this.disabledThumbRadius, this.elevation = 3.0, this.pressedElevation = 3.0, required this.themeData, + required this.buildContext, }); /// The preferred radius of the round thumb shape when the slider is enabled. @@ -1787,6 +1856,8 @@ class TDCapsuleRangeSliderThumbShape extends RangeSliderThumbShape with TDCapsul @override final TDSliderThemeData themeData; + final BuildContext? buildContext; + @override Size getPreferredSize(bool isEnabled, bool isDiscrete) { return Size.fromRadius( @@ -1854,7 +1925,8 @@ class TDCapsuleRangeSliderThumbShape extends RangeSliderThumbShape with TDCapsul themeData.sliderMeasureData.trackerRect != null) { var trackerRect = themeData.sliderMeasureData.trackerRect!; final padding = trackPadding(); - var ratio = (center.dx - trackerRect.left - padding) / (trackerRect.right - trackerRect.left - padding * 2); + var ratio = (center.dx - trackerRect.left - padding) / + (trackerRect.right - trackerRect.left - padding * 2); //计算滑块的值 var value = (themeData.max - themeData.min) * ratio + themeData.min; //格式化显示 @@ -1864,7 +1936,10 @@ class TDCapsuleRangeSliderThumbShape extends RangeSliderThumbShape with TDCapsul //绘制数值 var painter = TextPainter( text: TextSpan( - text: '$formatterValue', style: themeData.thumbTextStyle), + text: '$formatterValue', + style: enableAnimation.value > 0 + ? themeData.thumbTextStyle + : themeData.disabledThumbTextStyle), textDirection: TextDirection.ltr, textAlign: TextAlign.center) ..layout(maxWidth: 100); @@ -1880,6 +1955,16 @@ class TDCapsuleRangeSliderThumbShape extends RangeSliderThumbShape with TDCapsul radius, Paint()..color = color, ); + + canvas.drawArc( + Rect.fromCircle(center: center, radius: radius), + 0, + 2 * math.pi, + false, + Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = 1 + ..color = TDTheme.of(buildContext).componentStrokeColor); } } @@ -1987,27 +2072,36 @@ class TDCapsuleRangeSliderTickMarkShape extends RangeSliderTickMarkShape { textAlign: TextAlign.center) ..layout(maxWidth: 100); var x = dx - painter.size.width / 2; - painter.paint(context.canvas, Offset(x, center.dy - painter.height - 16)); - + painter.paint( + context.canvas, Offset(x, center.dy - painter.height - 16)); + // 第一个和最后一个不展示 if (index > 0 && index < themeData.divisions!) { final bool isBetweenThumbs; switch (textDirection) { case TextDirection.ltr: - isBetweenThumbs = startThumbCenter.dx < center.dx && center.dx < endThumbCenter.dx; + isBetweenThumbs = startThumbCenter.dx < center.dx && + center.dx < endThumbCenter.dx; break; case TextDirection.rtl: - isBetweenThumbs = endThumbCenter.dx < center.dx && center.dx < startThumbCenter.dx; + isBetweenThumbs = endThumbCenter.dx < center.dx && + center.dx < startThumbCenter.dx; break; } - final begin = - isBetweenThumbs ? sliderTheme.disabledActiveTickMarkColor : sliderTheme.disabledInactiveTickMarkColor; - final end = isBetweenThumbs ? sliderTheme.activeTickMarkColor : sliderTheme.inactiveTickMarkColor; + final begin = isBetweenThumbs + ? sliderTheme.disabledActiveTickMarkColor + : sliderTheme.disabledInactiveTickMarkColor; + final end = isBetweenThumbs + ? sliderTheme.activeTickMarkColor + : sliderTheme.inactiveTickMarkColor; final paint = Paint() ..strokeWidth = 2 - ..color = ColorTween(begin: begin, end: end).evaluate(enableAnimation)!; - context.canvas.drawLine(Offset(dx, themeData.sliderMeasureData.trackerRect!.top + 3), - Offset(dx, themeData.sliderMeasureData.trackerRect!.bottom - 3), paint); + ..color = + ColorTween(begin: begin, end: end).evaluate(enableAnimation)!; + context.canvas.drawLine( + Offset(dx, themeData.sliderMeasureData.trackerRect!.top + 3), + Offset(dx, themeData.sliderMeasureData.trackerRect!.bottom - 3), + paint); } } } diff --git a/tdesign-component/lib/src/components/stepper/td_stepper.dart b/tdesign-component/lib/src/components/stepper/td_stepper.dart index 47f1b8030..235371ca3 100644 --- a/tdesign-component/lib/src/components/stepper/td_stepper.dart +++ b/tdesign-component/lib/src/components/stepper/td_stepper.dart @@ -22,6 +22,7 @@ class TDStepperController { _TDStepperState? _state; int _value = 0; + int get value => _value; set value(int value) { @@ -29,11 +30,9 @@ class TDStepperController { _state?.updateUI(); } - void _bindState(_TDStepperState _tdStepperState) { _state = _tdStepperState; } - } /// 步进器 @@ -82,7 +81,6 @@ class TDStepper extends StatefulWidget { final TDStepperTheme theme; /// 值 - @Deprecated('与defaultValue 功能重复,请使用defaultValue或者valueController') final int? value; /// 默认值 @@ -102,6 +100,7 @@ class TDStepper extends StatefulWidget { /// Stepper控制器 final TDStepperController? controller; + @override State createState() => _TDStepperState(); } @@ -121,14 +120,15 @@ class _TDStepperState extends State { ..value = widget.value ?? widget.defaultValue ?? 0; } _controller._bindState(this); - if(widget.eventController!=null){ - widget.eventController?.stream.listen((TDStepperEventType event){ - if(event == TDStepperEventType.cleanValue){ - cleanValue(); - } + if (widget.eventController != null) { + widget.eventController?.stream.listen((TDStepperEventType event) { + if (event == TDStepperEventType.cleanValue) { + cleanValue(); + } }); } - _textController = TextEditingController(text: _controller._value.toString()); + _textController = + TextEditingController(text: _controller._value.toString()); _focusNode.addListener(() { if (!_focusNode.hasFocus) { @@ -185,10 +185,10 @@ class _TDStepperState extends State { switch (widget.theme) { case TDStepperTheme.filled: return widget.disabled - ? TDTheme.of(context).grayColor2 - : TDTheme.of(context).grayColor1; + ? TDTheme.of(context).bgColorComponentDisabled + : TDTheme.of(context).bgColorSecondaryContainer; case TDStepperTheme.outline: - return TDTheme.of(context).whiteColor1; + return null; case TDStepperTheme.normal: default: return null; @@ -256,8 +256,9 @@ class _TDStepperState extends State { }); renderNumber(); } - cleanValue(){ - _controller._value=0; + + cleanValue() { + _controller._value = 0; _textController.value = TextEditingValue( text: _controller._value.toString(), selection: TextSelection.fromPosition(TextPosition( @@ -266,6 +267,7 @@ class _TDStepperState extends State { ))); _focusNode.unfocus(); } + void renderNumber() { _textController.value = TextEditingValue( text: _controller._value.toString(), @@ -296,10 +298,10 @@ class _TDStepperState extends State { border: widget.theme == TDStepperTheme.outline ? Border( top: BorderSide( - color: TDTheme.of(context).grayColor4, + color: TDTheme.of(context).componentBorderColor, ), bottom: BorderSide( - color: TDTheme.of(context).grayColor4, + color: TDTheme.of(context).componentBorderColor, )) : null), child: Padding( @@ -324,12 +326,12 @@ class _TDStepperState extends State { style: TextStyle( fontSize: _getFontSize(), color: widget.disabled - ? TDTheme.of(context).fontGyColor4 - : TDTheme.of(context).fontGyColor1), + ? TDTheme.of(context).textColorDisabled + : TDTheme.of(context).textColorPrimary), textAlign: TextAlign.center, textAlignVertical: TextAlignVertical.center, keyboardType: TextInputType.number, - decoration: InputDecoration( + decoration: const InputDecoration( border: InputBorder.none, isDense: true, contentPadding: EdgeInsets.zero, @@ -351,7 +353,9 @@ class _TDStepperState extends State { return newValue.copyWith( text: _controller._value.toString(), selection: TextSelection.collapsed( - offset: _controller._value.toString().length)); + offset: _controller._value + .toString() + .length)); } final newNum = int.parse(newValue.text); @@ -380,7 +384,8 @@ class _TDStepperState extends State { return newValue.copyWith( text: _controller._value.toString(), selection: TextSelection.collapsed( - offset: _controller._value.toString().length)); + offset: + _controller._value.toString().length)); } catch (e) { return oldValue; } @@ -409,28 +414,28 @@ class _TDStepperState extends State { } void updateUI() { - if(mounted){ - _textController.value = TextEditingValue( - text: _controller._value.toString(), - selection: TextSelection.fromPosition(TextPosition( - affinity: TextAffinity.downstream, - offset: _controller._value.toString().length, - ))); - } + if (mounted) { + _textController.value = TextEditingValue( + text: _controller._value.toString(), + selection: TextSelection.fromPosition(TextPosition( + affinity: TextAffinity.downstream, + offset: _controller._value.toString().length, + ))); + } } } typedef TDTapFunction = void Function(); class TDStepperIconButton extends StatelessWidget { - const TDStepperIconButton( - {Key? key, - this.onTap, - this.size = TDStepperSize.medium, - this.disabled = false, - this.theme = TDStepperTheme.normal, - required this.type}) - : super(key: key); + const TDStepperIconButton({ + Key? key, + this.onTap, + this.size = TDStepperSize.medium, + this.disabled = false, + this.theme = TDStepperTheme.normal, + required this.type, + }) : super(key: key); final TDTapFunction? onTap; final TDStepperSize size; @@ -457,18 +462,18 @@ class TDStepperIconButton extends StatelessWidget { return Icon(iconType, size: _getIconSize(), color: disabled - ? TDTheme.of(context).fontGyColor4 - : TDTheme.of(context).fontGyColor1); + ? TDTheme.of(context).textColorDisabled + : TDTheme.of(context).textColorPrimary); } Color? _getBackgroundColor(BuildContext context) { switch (theme) { case TDStepperTheme.filled: return disabled - ? TDTheme.of(context).grayColor2 - : TDTheme.of(context).grayColor1; + ? TDTheme.of(context).bgColorComponentDisabled + : TDTheme.of(context).bgColorSecondaryContainer; case TDStepperTheme.outline: - return disabled ? TDTheme.of(context).grayColor2 : null; + return disabled ? TDTheme.of(context).bgColorComponentDisabled : null; case TDStepperTheme.normal: default: return null; @@ -490,7 +495,7 @@ class TDStepperIconButton extends StatelessWidget { BoxBorder? _getBoxBorder(BuildContext context) { if (theme == TDStepperTheme.outline) { return Border.all( - color: TDTheme.of(context).grayColor4, + color: TDTheme.of(context).componentBorderColor, ); } @@ -514,4 +519,3 @@ class TDStepperIconButton extends StatelessWidget { )); } } - diff --git a/tdesign-component/lib/src/components/steps/td_steps.dart b/tdesign-component/lib/src/components/steps/td_steps.dart index 2fa4bea6b..aa236258e 100644 --- a/tdesign-component/lib/src/components/steps/td_steps.dart +++ b/tdesign-component/lib/src/components/steps/td_steps.dart @@ -1,19 +1,24 @@ import 'package:flutter/material.dart'; -import 'package:tdesign_flutter/src/components/steps/td_steps_horizontal.dart'; -import 'package:tdesign_flutter/src/components/steps/td_steps_vertical.dart'; -import '../../../tdesign_flutter.dart'; + +import 'td_steps_horizontal.dart'; +import 'td_steps_vertical.dart'; /// Steps步骤条数据类型 class TDStepsItemData { - TDStepsItemData( - {this.title, - this.content, - this.successIcon, - this.errorIcon, - this.customContent, - this.customTitle}) { - _validate(); - } + TDStepsItemData({ + this.title, + this.content, + this.successIcon, + this.errorIcon, + this.customContent, + this.customTitle, + }) : assert( + title != null || + customTitle != null || + content != null || + customContent != null, + 'title, content, customContent needs at least one non-empty value', + ); /// 标题 final String? title; @@ -32,17 +37,6 @@ class TDStepsItemData { /// 自定义标题 final Widget? customTitle; - - /// 校验参数 - void _validate() { - if (title == null && - customTitle == null && - content == null && - customContent == null) { - throw ArgumentError( - 'title, content, customContent needs at least one non-empty value'); - } - } } /// Steps步骤条方向 @@ -96,14 +90,24 @@ class TDSteps extends StatefulWidget { } class _TDStepsState extends State { + int _clampActiveIndex(int index, int length) { + if (index < 0) { + return 0; + } + if (index >= length) { + return length > 0 ? length - 1 : 0; + } + return index; + } + @override Widget build(BuildContext context) { /// 当前激活的step索引 - final currentActiveIndex = widget.activeIndex < 0 - ? 0 - : (widget.activeIndex >= widget.steps.length - ? widget.steps.length - 1 - : widget.activeIndex); + final currentActiveIndex = _clampActiveIndex( + widget.activeIndex, + widget.steps.length, + ); + return widget.direction == TDStepsDirection.horizontal ? TDStepsHorizontal( steps: widget.steps, diff --git a/tdesign-component/lib/src/components/steps/td_steps_horizontal.dart b/tdesign-component/lib/src/components/steps/td_steps_horizontal.dart index 442f76a92..a0b97e56d 100644 --- a/tdesign-component/lib/src/components/steps/td_steps_horizontal.dart +++ b/tdesign-component/lib/src/components/steps/td_steps_horizontal.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:tdesign_flutter/src/components/steps/td_steps_horizontal_item.dart'; + import '../../../tdesign_flutter.dart'; +import 'td_steps_horizontal_item.dart'; /// Steps步骤条,水平步骤 class TDStepsHorizontal extends StatelessWidget { @@ -9,6 +10,7 @@ class TDStepsHorizontal extends StatelessWidget { final TDStepsStatus status; final bool simple; final bool readOnly; + const TDStepsHorizontal({ super.key, required this.steps, @@ -21,7 +23,8 @@ class TDStepsHorizontal extends StatelessWidget { @override Widget build(BuildContext context) { final stepsCount = steps.length; - List stepsHorizontalItem = steps.asMap().entries.map((item){ + + List stepsHorizontalItem = steps.asMap().entries.map((item) { return Expanded( flex: 1, child: TDStepsHorizontalItem( @@ -41,6 +44,4 @@ class TDStepsHorizontal extends StatelessWidget { children: stepsHorizontalItem, ); } - } - diff --git a/tdesign-component/lib/src/components/steps/td_steps_horizontal_item.dart b/tdesign-component/lib/src/components/steps/td_steps_horizontal_item.dart index e1a845e6c..37a07500b 100644 --- a/tdesign-component/lib/src/components/steps/td_steps_horizontal_item.dart +++ b/tdesign-component/lib/src/components/steps/td_steps_horizontal_item.dart @@ -24,52 +24,46 @@ class TDStepsHorizontalItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = TDTheme.of(context); + /// 步骤条数字背景色 - var stepsNumberBgColor = TDTheme.of(context).brandNormalColor; + var stepsNumberBgColor = theme.brandNormalColor; /// 步骤条数字颜色 - var stepsNumberTextColor = TDTheme.of(context).whiteColor1; + var stepsNumberTextColor = theme.textColorAnti; /// 步骤条标题颜色 - var stepsTitleColor = TDTheme.of(context).brandColor7; + var stepsTitleColor = theme.brandNormalColor; /// 步骤条icon颜色 - var stepsIconColor = TDTheme.of(context).brandColor7; + var stepsIconColor = theme.brandNormalColor; /// 简略步骤条icon颜色 - var simpleStepsIconColor = TDTheme.of(context).brandColor7; + var simpleStepsIconColor = theme.brandNormalColor; /// 是否要设置步骤图标widget的Decoration - bool shouldSetIconWidgetDecoration = true; + var shouldSetIconWidgetDecoration = true; Widget? completeIconWidget; - /// 错误icon图标显示 - Widget errorIconWidget = Icon( - TDIcons.close, - color: TDTheme.of(context).errorColor6, - size: 16, - ); - - /// 激活索引大于当前索引 + /// 已完成步骤条 if (activeIndex > index) { - stepsNumberBgColor = TDTheme.of(context).brandColor1; - stepsNumberTextColor = TDTheme.of(context).brandColor7; - stepsTitleColor = TDTheme.of(context).fontGyColor1; + stepsNumberBgColor = theme.brandLightColor; + stepsNumberTextColor = theme.brandNormalColor; + stepsTitleColor = theme.textColorPrimary; - /// 已完成的用icon图标显示 completeIconWidget = Icon( TDIcons.check, - color: TDTheme.of(context).brandColor7, + color: theme.brandNormalColor, size: 16, ); } else if (activeIndex < index) { - /// 激活索引小于当前索引 - stepsNumberBgColor = TDTheme.of(context).grayColor1; - stepsNumberTextColor = TDTheme.of(context).fontGyColor3; - stepsTitleColor = TDTheme.of(context).fontGyColor3; - stepsIconColor = TDTheme.of(context).fontGyColor3; - simpleStepsIconColor = TDTheme.of(context).grayColor4; + /// 未完成步骤条 + stepsNumberBgColor = theme.bgColorComponent; + stepsNumberTextColor = theme.textColorPlaceholder; + stepsTitleColor = theme.textColorPlaceholder; + stepsIconColor = theme.textColorPlaceholder; + simpleStepsIconColor = theme.componentBorderColor; } /// 步骤条icon图标组件,默认为索引文字 @@ -99,35 +93,27 @@ class TDStepsHorizontalItem extends StatelessWidget { shouldSetIconWidgetDecoration = false; } - /// 状态是错误状态,激活索引是当前索引,只有当前激活索引才需要显示 + /// 错误状态处理 + /// 激活索引是当前索引,只有当前激活索引才需要显示 if (status == TDStepsStatus.error && activeIndex == index) { - /// 显示错误颜色 - stepsNumberBgColor = TDTheme.of(context).errorColor1; - stepsTitleColor = TDTheme.of(context).errorColor6; + stepsNumberBgColor = theme.errorLightColor; + stepsTitleColor = theme.errorNormalColor; - /// 显示错误图标 - stepsIconWidget = errorIconWidget; - if (data.errorIcon != null) { + if (simple) { + simpleStepsIconColor = theme.errorNormalColor; + } else { + shouldSetIconWidgetDecoration = data.errorIcon == null; stepsIconWidget = Icon( - data.errorIcon, - color: TDTheme.of(context).errorColor6, - size: 22, + data.errorIcon ?? TDIcons.close, + color: theme.errorNormalColor, + size: shouldSetIconWidgetDecoration ? 16 : 22, ); } - - /// 传了图标则不用设置背景色等Decoration - shouldSetIconWidgetDecoration = data.errorIcon == null; - if (simple) { - simpleStepsIconColor = TDTheme.of(context).errorColor6; - } } /// 步骤条icon图标背景和形状 - BoxDecoration? iconWidgetDecoration = shouldSetIconWidgetDecoration - ? BoxDecoration( - color: stepsNumberBgColor, - shape: BoxShape.circle, - ) + var iconWidgetDecoration = shouldSetIconWidgetDecoration + ? BoxDecoration(color: stepsNumberBgColor, shape: BoxShape.circle) : null; /// icon组件容器大小 @@ -137,8 +123,8 @@ class TDStepsHorizontalItem extends StatelessWidget { if (simple || readOnly) { /// readOnly纯展示 if (readOnly) { - simpleStepsIconColor = TDTheme.of(context).brandColor7; - stepsTitleColor = TDTheme.of(context).fontGyColor1; + simpleStepsIconColor = theme.brandNormalColor; + stepsTitleColor = theme.textColorPrimary; } iconContainerSize = 8; stepsIconWidget = null; @@ -161,6 +147,13 @@ class TDStepsHorizontalItem extends StatelessWidget { iconWidgetDecoration = simpleDecoration; } + var leftLineColor = (activeIndex >= index || readOnly) + ? theme.brandNormalColor + : theme.componentBorderColor; + var rightLineColor = (activeIndex > index || readOnly) + ? theme.brandNormalColor + : theme.componentBorderColor; + return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, @@ -168,18 +161,8 @@ class TDStepsHorizontalItem extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Expanded( - flex: 1, - child: Opacity( - opacity: index == 0 ? 0 : 1, - child: Container( - width: double.infinity, - height: 1, - color: (activeIndex >= index || readOnly) - ? TDTheme.of(context).brandColor7 - : TDTheme.of(context).grayColor4), - ), - ), + _buildLineWidget(context, + visible: index != 0, color: leftLineColor), Container( width: iconContainerSize, height: iconContainerSize, @@ -188,52 +171,72 @@ class TDStepsHorizontalItem extends StatelessWidget { decoration: iconWidgetDecoration, child: stepsIconWidget, ), - Expanded( - flex: 1, - child: Opacity( - opacity: index == stepsCount - 1 ? 0 : 1, - child: Container( - width: double.infinity, - height: 1, - color: (activeIndex > index || readOnly) - ? TDTheme.of(context).brandColor7 - : TDTheme.of(context).grayColor4, - ), - ), - ), + _buildLineWidget(context, + visible: index != stepsCount - 1, color: rightLineColor), ], ), - if (data.customTitle != null) - data.customTitle! - else if (data.title != null && data.title!.isNotEmpty) - Container( - margin: const EdgeInsets.only(top: 8), - alignment: Alignment.center, - child: TDText( - data.title!, - style: TextStyle( - fontWeight: (activeIndex == index && !readOnly) - ? FontWeight.w600 - : FontWeight.w400, - color: stepsTitleColor, - fontSize: 14, - ), + _buildTitleWidget(context, stepsTitleColor), + _buildContentWidget(context) + ], + ); + } + + /// 构建步骤条横线组件 + Widget _buildLineWidget( + BuildContext context, { + required bool visible, + required Color color, + }) { + return Expanded( + flex: 1, + child: Visibility( + visible: visible, + child: Container(width: double.infinity, height: 1, color: color), + ), + ); + } + + /// 构建标题组件 + Widget _buildTitleWidget(BuildContext context, Color stepsTitleColor) { + if (data.customTitle != null) { + return data.customTitle!; + } + + final title = data.title ?? ''; + if (title.isEmpty) { + return const SizedBox.shrink(); + } + + return Container( + margin: const EdgeInsets.only(top: 8), + alignment: Alignment.center, + child: TDText( + title, + style: TextStyle( + fontWeight: (activeIndex == index && !readOnly) + ? FontWeight.w600 + : FontWeight.w400, + color: stepsTitleColor, + fontSize: 14, + ), + ), + ); + } + + /// 构建内容组件 + Widget _buildContentWidget(BuildContext context) { + return Container( + margin: const EdgeInsets.only(top: 4), + alignment: Alignment.center, + child: data.customContent ?? + TDText( + data.content ?? '', + style: TextStyle( + fontWeight: FontWeight.w400, + color: TDTheme.of(context).textColorPlaceholder, + fontSize: 12, ), ), - Container( - margin: const EdgeInsets.only(top: 4), - alignment: Alignment.center, - child: data.customContent ?? - TDText( - data.content ?? '', - style: TextStyle( - fontWeight: FontWeight.w400, - color: TDTheme.of(context).fontGyColor3, - fontSize: 12, - ), - ), - ), - ], ); } } diff --git a/tdesign-component/lib/src/components/steps/td_steps_vertical.dart b/tdesign-component/lib/src/components/steps/td_steps_vertical.dart index 6bcb4618b..8ba247229 100644 --- a/tdesign-component/lib/src/components/steps/td_steps_vertical.dart +++ b/tdesign-component/lib/src/components/steps/td_steps_vertical.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:tdesign_flutter/src/components/steps/td_steps_vertical_item.dart'; + import '../../../tdesign_flutter.dart'; +import 'td_steps_vertical_item.dart'; /// Steps步骤条,垂直步骤 class TDStepsVertical extends StatelessWidget { @@ -10,6 +11,7 @@ class TDStepsVertical extends StatelessWidget { final bool simple; final bool readOnly; final bool verticalSelect; + const TDStepsVertical({ super.key, required this.steps, @@ -23,7 +25,7 @@ class TDStepsVertical extends StatelessWidget { @override Widget build(BuildContext context) { final stepsCount = steps.length; - List stepsVerticalItem = steps.asMap().entries.map((item){ + List stepsVerticalItem = steps.asMap().entries.map((item) { return TDStepsVerticalItem( index: item.key, data: item.value, @@ -41,6 +43,4 @@ class TDStepsVertical extends StatelessWidget { children: stepsVerticalItem, ); } - } - diff --git a/tdesign-component/lib/src/components/steps/td_steps_vertical_item.dart b/tdesign-component/lib/src/components/steps/td_steps_vertical_item.dart index 117412913..1a1e8b3b7 100644 --- a/tdesign-component/lib/src/components/steps/td_steps_vertical_item.dart +++ b/tdesign-component/lib/src/components/steps/td_steps_vertical_item.dart @@ -12,69 +12,64 @@ class TDStepsVerticalItem extends StatelessWidget { final bool readOnly; final bool verticalSelect; - ///item 标题组件插槽 + /// item 标题组件插槽 final Widget? titleWidget; - const TDStepsVerticalItem( - {super.key, - required this.data, - required this.index, - required this.stepsCount, - required this.activeIndex, - required this.status, - required this.simple, - required this.readOnly, - required this.verticalSelect, - this.titleWidget}); + const TDStepsVerticalItem({ + super.key, + required this.data, + required this.index, + required this.stepsCount, + required this.activeIndex, + required this.status, + required this.simple, + required this.readOnly, + required this.verticalSelect, + this.titleWidget, + }); @override Widget build(BuildContext context) { + final theme = TDTheme.of(context); + /// 步骤条数字背景色 - var stepsNumberBgColor = TDTheme.of(context).brandNormalColor; + var stepsNumberBgColor = theme.brandNormalColor; /// 步骤条数字颜色 - var stepsNumberTextColor = TDTheme.of(context).whiteColor1; + var stepsNumberTextColor = theme.textColorAnti; /// 步骤条标题颜色 - var stepsTitleColor = TDTheme.of(context).brandColor7; + var stepsTitleColor = theme.brandNormalColor; - /// 步骤条icon颜色 - var stepsIconColor = TDTheme.of(context).brandColor7; + /// 步骤条 icon 颜色 + var stepsIconColor = theme.brandNormalColor; - /// 简略步骤条icon颜色 - var simpleStepsIconColor = TDTheme.of(context).brandColor7; + /// 简略步骤条 icon 颜色 + var simpleStepsIconColor = theme.brandNormalColor; - /// 是否要设置步骤图标widget的Decoration - bool shouldSetIconWidgetDecoration = true; + /// 是否要设置步骤图标 widget 的 Decoration + var shouldSetIconWidgetDecoration = true; Widget? completeIconWidget; - /// 错误icon图标显示 - Widget errorIconWidget = Icon( - TDIcons.close, - color: TDTheme.of(context).errorColor6, - size: 16, - ); - - /// 激活索引大于当前索引 + /// 已完成步骤条 if (activeIndex > index) { - stepsNumberBgColor = TDTheme.of(context).brandColor1; - stepsNumberTextColor = TDTheme.of(context).brandColor7; - stepsTitleColor = TDTheme.of(context).fontGyColor1; + stepsNumberBgColor = theme.brandLightColor; + stepsNumberTextColor = theme.brandNormalColor; + stepsTitleColor = theme.textColorPrimary; - /// 已完成的用icon图标显示 completeIconWidget = Icon( TDIcons.check, - color: TDTheme.of(context).brandColor7, + color: theme.brandNormalColor, size: 16, ); } else if (activeIndex < index) { - /// 激活索引小于当前索引 - stepsNumberBgColor = TDTheme.of(context).grayColor1; - stepsNumberTextColor = TDTheme.of(context).fontGyColor3; - stepsTitleColor = TDTheme.of(context).fontGyColor3; - stepsIconColor = TDTheme.of(context).fontGyColor3; - simpleStepsIconColor = TDTheme.of(context).grayColor4; + /// 未完成步骤条 + stepsNumberBgColor = theme.bgColorComponent; + stepsNumberTextColor = theme.textColorPlaceholder; + stepsTitleColor = theme.textColorPlaceholder; + stepsIconColor = theme.textColorPlaceholder; + simpleStepsIconColor = theme.componentBorderColor; } /// 步骤条icon图标组件,默认为索引文字 @@ -87,12 +82,12 @@ class TDStepsVerticalItem extends StatelessWidget { ), ); - /// 已完成的用icon图标显示 + /// 已完成的用 icon 图标显示 if (completeIconWidget != null) { stepsIconWidget = completeIconWidget; } - /// 传递了成功的icon图标, 已完成的step都需要显示 + /// 传递了成功的 icon 图标, 已完成的 step 都需要显示 if (data.successIcon != null) { stepsIconWidget = Icon( data.successIcon, @@ -104,35 +99,27 @@ class TDStepsVerticalItem extends StatelessWidget { shouldSetIconWidgetDecoration = false; } - /// 状态是错误状态,激活索引是当前索引,只有当前激活索引才需要显示 + /// 错误状态 + /// 激活索引是当前索引,只有当前激活索引才需要显示 if (status == TDStepsStatus.error && activeIndex == index) { - /// 显示错误颜色 - stepsNumberBgColor = TDTheme.of(context).errorColor1; - stepsTitleColor = TDTheme.of(context).errorColor6; + stepsNumberBgColor = theme.errorLightColor; + stepsTitleColor = theme.errorNormalColor; - /// 显示错误图标 - stepsIconWidget = errorIconWidget; - if (data.errorIcon != null) { + if (simple) { + simpleStepsIconColor = theme.errorNormalColor; + } else { + shouldSetIconWidgetDecoration = data.errorIcon == null; stepsIconWidget = Icon( - data.errorIcon, - color: TDTheme.of(context).errorColor6, - size: 22, + data.errorIcon ?? TDIcons.close, + color: theme.errorNormalColor, + size: shouldSetIconWidgetDecoration ? 16 : 22, ); } - - /// 传了图标则不用设置背景色等Decoration - shouldSetIconWidgetDecoration = data.errorIcon == null; - if (simple) { - simpleStepsIconColor = TDTheme.of(context).errorColor6; - } } /// 步骤条icon图标背景和形状 var iconWidgetDecoration = shouldSetIconWidgetDecoration - ? BoxDecoration( - color: stepsNumberBgColor, - shape: BoxShape.circle, - ) + ? BoxDecoration(color: stepsNumberBgColor, shape: BoxShape.circle) : null; /// icon组件容器大小 @@ -145,8 +132,8 @@ class TDStepsVerticalItem extends StatelessWidget { if (simple || readOnly) { /// readOnly纯展示 if (readOnly) { - simpleStepsIconColor = TDTheme.of(context).brandColor7; - stepsTitleColor = TDTheme.of(context).fontGyColor1; + simpleStepsIconColor = theme.brandNormalColor; + stepsTitleColor = theme.textColorPrimary; } iconContainerSize = 8; iconMarginBottom = 4; @@ -170,14 +157,6 @@ class TDStepsVerticalItem extends StatelessWidget { iconWidgetDecoration = simpleDecoration; } - /// 自定义内容 - var customContent = data.customContent != null - ? Container( - margin: const EdgeInsets.only(top: 4), - child: data.customContent!, - ) - : Container(); - return Container( margin: const EdgeInsets.only(bottom: 8), child: IntrinsicHeight( @@ -185,6 +164,7 @@ class TDStepsVerticalItem extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ + // 左侧图标、线条 Container( margin: const EdgeInsets.only(right: 8), width: 22, @@ -201,23 +181,12 @@ class TDStepsVerticalItem extends StatelessWidget { decoration: iconWidgetDecoration, child: stepsIconWidget, ), - Expanded( - flex: 1, - child: Opacity( - opacity: index == stepsCount - 1 ? 0 : 1, - child: Container( - width: 1, - height: double.infinity, - color: (activeIndex > index || readOnly) - ? TDTheme.of(context).brandColor7 - : TDTheme.of(context).grayColor4, - ), - ), - ), + _buildLineWidget(context) ], ), ), ), + // 右侧 标题、内容等 Expanded( flex: 1, child: Column( @@ -250,30 +219,14 @@ class TDStepsVerticalItem extends StatelessWidget { verticalSelect ? Icon( TDIcons.chevron_right, - color: TDTheme.of(context).fontGyColor1, + color: theme.textColorPrimary, size: 16, ) : Container(), ], ), ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (data.customContent != null) - data.customContent! - else if (data.content != null && data.content!.isNotEmpty) - TDText( - data.content!, - style: TextStyle( - fontWeight: FontWeight.w400, - color: TDTheme.of(context).fontGyColor3, - fontSize: 12, - ), - ), - ], - ), + _buildContentWidget(context) ], ), ) @@ -282,4 +235,40 @@ class TDStepsVerticalItem extends StatelessWidget { ), ); } + + Widget _buildLineWidget(BuildContext context) { + return Expanded( + flex: 1, + child: Visibility( + visible: index != stepsCount - 1, + child: Container( + width: 1, + height: double.infinity, + color: (activeIndex > index || readOnly) + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).componentBorderColor, + ), + ), + ); + } + + Widget _buildContentWidget(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (data.customContent != null) + data.customContent! + else if (data.content != null && data.content!.isNotEmpty) + TDText( + data.content!, + style: TextStyle( + fontWeight: FontWeight.w400, + color: TDTheme.of(context).textColorPlaceholder, + fontSize: 12, + ), + ), + ], + ); + } } diff --git a/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell.dart b/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell.dart index dd74df820..a54ff356b 100644 --- a/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell.dart +++ b/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell.dart @@ -80,7 +80,8 @@ class TDSwipeCell extends StatefulWidget { static final Map> _controllers = {}; - static void _pushController(SlidableController controller, Object? tag, {bool del = false}) { + static void _pushController(SlidableController controller, Object? tag, + {bool del = false}) { if (tag == null) { return; } @@ -100,7 +101,7 @@ class TDSwipeCell extends StatefulWidget { } /// 根据[groupTag]关闭[TDSwipeCell] - /// + /// /// current:保留当前不关闭 static void close(Object? tag, {SlidableController? current}) { if (tag == null || !_controllers.keys.contains(tag)) { @@ -120,10 +121,10 @@ class TDSwipeCell extends StatefulWidget { @override _TDSwipeCellState createState() => _TDSwipeCellState(); - } -class _TDSwipeCellState extends State with TickerProviderStateMixin { +class _TDSwipeCellState extends State + with TickerProviderStateMixin { late final SlidableController controller; final confirmListenable = ValueNotifier(null); TDSwipeDirection? openDirection; @@ -196,7 +197,8 @@ class _TDSwipeCellState extends State with TickerProviderStateMixin final isLeft = openDirection == TDSwipeDirection.left; final panel = isLeft ? widget.left! : widget.right!; final index = panel.children.indexOf(action); - final confirm = panel.confirms?.find((element) => element.confirmIndex?.contains(index) == true); + final confirm = panel.confirms + ?.find((element) => element.confirmIndex?.contains(index) == true); confirmListenable.value = confirm; return confirm != null; }, diff --git a/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell_action.dart b/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell_action.dart index 1120ec094..4efcd5063 100644 --- a/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell_action.dart +++ b/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell_action.dart @@ -71,13 +71,14 @@ class TDSwipeCellAction extends StatelessWidget { @override Widget build(BuildContext context) { - final fontSize = TDTheme.of(context).fontMarkMedium ?? Font(size: 14, lineHeight: 22, fontWeight: FontWeight.w600); + final fontSize = TDTheme.of(context).fontMarkMedium ?? + Font(size: 14, lineHeight: 22, fontWeight: FontWeight.w600); final children = [ if (icon != null) Icon( icon, size: iconSize ?? 18, - color: labelStyle?.color ?? TDTheme.of(context).fontWhColor1, + color: labelStyle?.color ?? TDTheme.of(context).textColorAnti, ), if (icon != null && label != null) SizedBox(width: spacing ?? 2), if (label != null) @@ -86,7 +87,7 @@ class TDSwipeCellAction extends StatelessWidget { label, forceVerticalCenter: true, font: fontSize, - textColor: TDTheme.of(context).fontWhColor1, + textColor: TDTheme.of(context).textColorAnti, style: labelStyle, overflow: TextOverflow.ellipsis, maxLines: 1, diff --git a/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell_panel.dart b/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell_panel.dart index d12b47374..f01e1b6d8 100644 --- a/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell_panel.dart +++ b/tdesign-component/lib/src/components/swipe_cell/td_swipe_cell_panel.dart @@ -37,7 +37,8 @@ class TDSwipeCellPanel { confirms == null || confirms.every((item) => item.confirmIndex != null && - item.confirmIndex!.every((index) => index >= 0 && index < children.length)), + item.confirmIndex! + .every((index) => index >= 0 && index < children.length)), 'Confirms must have a confirmIndex, ' 'and each confirmIndex in confirms must be within the range of children indices.', ); @@ -81,9 +82,11 @@ class TDSwipeCellPanel { /// 移除后回调。dragDismissible为true才有效 final void Function(BuildContext context)? onDismissed; - Duration get _dismissalDuration => dismissalDuration ?? const Duration(milliseconds: 300); + Duration get _dismissalDuration => + dismissalDuration ?? const Duration(milliseconds: 300); - Duration get _resizeDuration => resizeDuration ?? const Duration(milliseconds: 300); + Duration get _resizeDuration => + resizeDuration ?? const Duration(milliseconds: 300); bool get _dragDismissible => dragDismissible ?? false; diff --git a/tdesign-component/lib/src/components/swiper/td_page_transform.dart b/tdesign-component/lib/src/components/swiper/td_page_transform.dart index 82e7633de..3a81c0a43 100644 --- a/tdesign-component/lib/src/components/swiper/td_page_transform.dart +++ b/tdesign-component/lib/src/components/swiper/td_page_transform.dart @@ -3,11 +3,12 @@ import 'package:flutter_swiper_null_safety/src/transformer_page_view/transformer /// TD默认PageTransformer class TDPageTransformer extends PageTransformer { - /// 缩放比例 final double? scale; + /// 淡化比例 final double? fade; + /// 左右间隔 final double? margin; diff --git a/tdesign-component/lib/src/components/swiper/td_swiper.dart b/tdesign-component/lib/src/components/swiper/td_swiper.dart index ea2cb3bdf..a3e028bed 100644 --- a/tdesign-component/lib/src/components/swiper/td_swiper.dart +++ b/tdesign-component/lib/src/components/swiper/td_swiper.dart @@ -1,18 +1,18 @@ import 'package:flutter/material.dart'; import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart'; -import '../../theme/td_colors.dart'; -import '../../theme/td_theme.dart'; +import '../../../tdesign_flutter.dart'; const _kAminatedDuration = 100; /// TDesign风格的Swiper指示器样式,与flutter_swiper的Swiper结合使用 class TDSwiperPagination extends SwiperPlugin { - const TDSwiperPagination( - {this.alignment, - this.key, - this.margin = const EdgeInsets.all(10.0), - this.builder = TDSwiperPagination.dots}); + const TDSwiperPagination({ + this.alignment, + this.key, + this.margin = const EdgeInsets.all(10.0), + this.builder = TDSwiperPagination.dots, + }); /// 圆点样式 static const SwiperPlugin dots = TDSwiperDotsPagination(); @@ -60,6 +60,7 @@ class TDSwiperPagination extends SwiperPlugin { } } +/// 圆点指示器 class TDSwiperDotsPagination extends SwiperPlugin { /// 当前展示的索引,如果未设置,则为Theme.of(context).primaryColor final Color? activeColor; @@ -79,7 +80,7 @@ class TDSwiperDotsPagination extends SwiperPlugin { /// 圆角矩形宽度(高度仍为activeSize) final double? roundedRectangleWidth; - // 动画效果 默认100ms,设置为0则无动画 + /// 动画效果 默认100ms,设置为 0 则无动画 final int? animationDuration; final Key? key; @@ -90,7 +91,7 @@ class TDSwiperDotsPagination extends SwiperPlugin { this.key, this.size = 6.0, this.activeSize = 6.0, - this.space = 4.0, + this.space = 8.0, this.roundedRectangleWidth, this.animationDuration, }); @@ -107,8 +108,8 @@ class TDSwiperDotsPagination extends SwiperPlugin { : TDTheme.of(context).whiteColor1); var color = this.color ?? (config.outer - ? TDTheme.of(context).grayColor3 - : TDTheme.of(context).whiteColor1.withOpacity(0.55)); + ? TDTheme.of(context).bgColorComponentHover + : TDTheme.of(context).fontWhColor2); if (config.indicatorLayout != PageIndicatorLayout.NONE && config.layout == SwiperLayout.DEFAULT) { @@ -130,12 +131,12 @@ class TDSwiperDotsPagination extends SwiperPlugin { for (var i = 0; i < itemCount; ++i) { var active = i == activeIndex; - var isActiviRectangle = + var isActivityRectangle = roundedRectangleWidth != null && roundedRectangleWidth! > 0 && active; double? scalableLen; double? fixedLen; - scalableLen = isActiviRectangle + scalableLen = isActivityRectangle ? roundedRectangleWidth : (active ? activeSize : size); fixedLen = active ? activeSize : size; @@ -146,8 +147,12 @@ class TDSwiperDotsPagination extends SwiperPlugin { child: AnimatedContainer( duration: Duration(milliseconds: animationDuration ?? _kAminatedDuration), - width: config.scrollDirection == Axis.horizontal ? scalableLen : fixedLen, - height: config.scrollDirection == Axis.horizontal ? fixedLen : scalableLen, + width: config.scrollDirection == Axis.horizontal + ? scalableLen + : fixedLen, + height: config.scrollDirection == Axis.horizontal + ? fixedLen + : scalableLen, decoration: BoxDecoration( color: active ? activeColor : color, borderRadius: BorderRadius.circular(activeSize / 2)), @@ -155,33 +160,28 @@ class TDSwiperDotsPagination extends SwiperPlugin { )); } - if (config.scrollDirection == Axis.vertical) { - return Column( - key: key, - mainAxisSize: MainAxisSize.min, - children: list, - ); - } else { - return Row( - key: key, - mainAxisSize: MainAxisSize.min, - children: list, - ); - } + return Flex( + direction: config.scrollDirection, + // spacing: space, + key: key, + mainAxisSize: MainAxisSize.min, + children: list, + ); } } +/// 数字指示器 class TDFractionPagination extends SwiperPlugin { - // container宽度 + /// container宽度 final double? width; - // container高度 + /// container高度 final double? height; - // 圆角角度 + /// 圆角角度 final double? borderRadius; - // 背景色 + /// 背景色 final Color? backgroundColor; /// 如果未设置,则为 Theme.of(context).scaffoldBackgroundColor @@ -210,76 +210,51 @@ class TDFractionPagination extends SwiperPlugin { @override Widget build(BuildContext context, SwiperPluginConfig config) { - Widget child; - if (Axis.vertical == config.scrollDirection) { - child = Column( - key: key, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - '${config.activeIndex + 1}', - style: activeTextStyle, - ), - Text( - '/', - style: textStyle, - ), - Text( - '${config.itemCount}', - style: textStyle, - ) - ], - ); - } else { - child = Row( - key: key, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - '${config.activeIndex + 1}', - style: activeTextStyle, - ), - Text( - '/${config.itemCount}', - style: textStyle, - ) - ], - ); - } return Container( width: width ?? 37, - height: height ?? 20, + height: height ?? 24, alignment: Alignment.center, decoration: BoxDecoration( - color: backgroundColor ?? const Color(0x66000000), - borderRadius: BorderRadius.circular(borderRadius ?? 10)), - child: child, + color: backgroundColor ?? TDTheme.of(context).textColorPlaceholder, + borderRadius: BorderRadius.circular( + borderRadius ?? TDTheme.of(context).radiusRound), + ), + child: Row( + key: key, + mainAxisSize: MainAxisSize.min, + children: [ + Text('${config.activeIndex + 1}', style: activeTextStyle), + Text('/${config.itemCount}', style: textStyle) + ], + ), ); } } +/// 箭头指示器 class TDSwiperArrowPagination extends SwiperPlugin { - // 当设置 loop = false时,滑动到边界是否自动隐藏边界箭头 + /// 当设置 loop = false 时,滑动到边界是否自动隐藏边界箭头 final bool? autoHideWhenAtBoundary; - // 左箭头widget + /// 左箭头widget final Widget? backArrow; - // 右箭头widget + /// 右箭头widget final Widget? forwardArrow; - // 背景圆形半径 + /// 背景圆形半径 final double? radius; - // 背景圆形颜色 + /// 背景圆形颜色 final Color? backgroundColor; - const TDSwiperArrowPagination( - {this.radius, - this.backgroundColor, - this.backArrow, - this.forwardArrow, - this.autoHideWhenAtBoundary = true}); + const TDSwiperArrowPagination({ + this.radius, + this.backgroundColor, + this.backArrow, + this.forwardArrow, + this.autoHideWhenAtBoundary = true, + }); @override Widget build(BuildContext context, SwiperPluginConfig config) { @@ -287,47 +262,44 @@ class TDSwiperArrowPagination extends SwiperPlugin { var activeIndex = config.activeIndex; return Row(children: [ - Visibility( + _buildIcon( + context, visible: config.loop || ((autoHideWhenAtBoundary ?? false) && activeIndex != 0), - child: GestureDetector( - child: CircleAvatar( - radius: radius ?? 10.0, - backgroundColor: - backgroundColor ?? TDTheme.of(context).fontGyColor3, - child: backArrow ?? - const Icon( - Icons.arrow_back_ios_outlined, - color: Colors.white, - size: 9, - ), - ), - onTap: () { - config.controller.previous(); - }, - ), + arrowWidget: backArrow, + icon: Icons.arrow_back_ios_outlined, + onTap: config.controller.previous, ), const Spacer(), - Visibility( + _buildIcon( + context, visible: config.loop || ((autoHideWhenAtBoundary ?? false) && activeIndex != itemCount - 1), - child: GestureDetector( - child: CircleAvatar( - radius: radius ?? 10.0, - backgroundColor: - backgroundColor ?? TDTheme.of(context).fontGyColor3, - child: forwardArrow ?? - const Icon( - Icons.arrow_forward_ios_outlined, - color: Colors.white, - size: 9, - ), - ), - onTap: () { - config.controller.next(); - }, - ), + arrowWidget: forwardArrow, + icon: Icons.arrow_forward_ios_outlined, + onTap: config.controller.next, ), ]); } + + Widget _buildIcon( + BuildContext context, { + Widget? arrowWidget, + required IconData icon, + required bool visible, + required Function() onTap, + }) { + return Visibility( + visible: visible, + child: GestureDetector( + child: CircleAvatar( + radius: radius ?? 10.0, + backgroundColor: + backgroundColor ?? TDTheme.of(context).textColorPlaceholder, + child: arrowWidget ?? Icon(icon, color: Colors.white, size: 10.0), + ), + onTap: onTap, + ), + ); + } } diff --git a/tdesign-component/lib/src/components/switch/td_loading_paint.dart b/tdesign-component/lib/src/components/switch/td_loading_paint.dart deleted file mode 100644 index 98c45e107..000000000 --- a/tdesign-component/lib/src/components/switch/td_loading_paint.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'dart:math'; -import 'dart:ui' as ui; - -import 'package:flutter/cupertino.dart'; - -class TDLoadingPainter extends CustomPainter { - final Color color; - final double width; - - TDLoadingPainter({required this.color, required this.width}); - - final _paint = Paint()..style = PaintingStyle.stroke; - - @override - void paint(Canvas canvas, Size size) { - var minLength = min(size.width, size.height); - _paint.strokeWidth = width; - _paint.shader = ui.Gradient.sweep(Offset(size.width / 2, size.height / 2), - [const Color(0x01ffffff), color]); - if (minLength == size.width) { - canvas.drawArc( - Rect.fromLTWH( - 0, (size.height - size.width) / 2, size.width, size.width), - 0, - pi * 2, - false, - _paint); - } else { - canvas.drawArc( - Rect.fromLTWH( - (size.width - size.height) / 2, 0, size.height, size.height), - 0, - pi * 2, - false, - _paint); - } - } - - @override - bool shouldRepaint(CustomPainter oldDelegate) { - return true; - } -} diff --git a/tdesign-component/lib/src/components/switch/td_switch.dart b/tdesign-component/lib/src/components/switch/td_switch.dart index 9bdac3b9f..8000eb8cb 100644 --- a/tdesign-component/lib/src/components/switch/td_switch.dart +++ b/tdesign-component/lib/src/components/switch/td_switch.dart @@ -95,27 +95,34 @@ class TDSwitchState extends State { Widget build(BuildContext context) { final theme = TDTheme.of(context); final switchEnable = widget.enable && widget.type != TDSwitchType.loading; - final trackOnColor = widget.trackOnColor ?? theme.brandColor7; - final trackOffColor = widget.trackOffColor ?? theme.grayColor4; + final trackOnColor = widget.trackOnColor ?? theme.brandNormalColor; + final trackOffColor = widget.trackOffColor ?? theme.textColorDisabled; final thumbContentOnColor = widget.thumbContentOnColor ?? theme.brandNormalColor; final thumbContentOffColor = - widget.thumbContentOffColor ?? theme.fontGyColor4; - final thumbContentOnFont = widget.thumbContentOnFont ?? const TextStyle(fontSize: 14); - final thumbContentOffFont = widget.thumbContentOffFont ?? const TextStyle(fontSize: 14); + widget.thumbContentOffColor ?? theme.textColorDisabled; + final thumbContentOnFont = + widget.thumbContentOnFont ?? const TextStyle(fontSize: 14); + final thumbContentOffFont = + widget.thumbContentOffFont ?? const TextStyle(fontSize: 14); Widget current = TDCupertinoSwitch( value: isOn, activeColor: trackOnColor, trackColor: trackOffColor, onChanged: (value) { var process = widget.onChanged?.call(value) ?? false; - // 如果外部未处理,才需要自定刷新开关,如果已处理则不需要刷新 + // 如果外部未处理,才需要自定刷新开关,如果已处理则不需要刷新 if (!process) { isOn = value; setState(() {}); } }, - thumbView: _getThumbView(thumbContentOnColor, thumbContentOffColor,thumbContentOnFont, thumbContentOffFont), + thumbView: _getThumbView( + thumbContentOnColor, + thumbContentOffColor, + thumbContentOnFont, + thumbContentOffFont, + ), ); if (!switchEnable) { current = Opacity( @@ -162,7 +169,12 @@ class TDSwitchState extends State { } } - Widget? _getThumbView(Color thumbContentOnColor, Color thumbContentOffColor, TextStyle thumbContentOnFont, TextStyle thumbContentOffFont) { + Widget? _getThumbView( + Color thumbContentOnColor, + Color thumbContentOffColor, + TextStyle thumbContentOnFont, + TextStyle thumbContentOffFont, + ) { switch (widget.type) { case TDSwitchType.text: return Stack( @@ -194,9 +206,11 @@ class TDSwitchState extends State { case TDSwitchType.icon: return Container( alignment: Alignment.centerLeft, - child: Icon(isOn ? TDIcons.check : TDIcons.close, - size: 16, - color: isOn ? thumbContentOnColor : thumbContentOffColor), + child: Icon( + isOn ? TDIcons.check : TDIcons.close, + size: 16, + color: isOn ? thumbContentOnColor : thumbContentOffColor, + ), ); case TDSwitchType.fill: default: diff --git a/tdesign-component/lib/src/components/tabbar/td_bottom_tab_bar.dart b/tdesign-component/lib/src/components/tabbar/td_bottom_tab_bar.dart index 5253e0b59..2399f4d51 100644 --- a/tdesign-component/lib/src/components/tabbar/td_bottom_tab_bar.dart +++ b/tdesign-component/lib/src/components/tabbar/td_bottom_tab_bar.dart @@ -65,7 +65,7 @@ class BadgeConfig { /// 是否展示消息 final bool showBadge; - /// 消息样式(未设置但showBadge为true,则默认使用红点) + /// 消息样式(未设置但 showBadge 为 true,则默认使用红点) final TDBadge? tdBadge; /// 消息顶部偏移量 @@ -75,20 +75,20 @@ class BadgeConfig { final double? badgeRightOffset; } -/// 单个tab配置 +/// 单个 tab 配置 class TDBottomTabBarTabConfig { - TDBottomTabBarTabConfig({ - required this.onTap, - this.selectedIcon, - this.unselectedIcon, - this.tabText, - this.selectTabTextStyle, - this.unselectTabTextStyle, - this.badgeConfig, - this.popUpButtonConfig, - this.onLongPress, - this.allowMultipleTaps = false - }) : assert(() { + TDBottomTabBarTabConfig( + {required this.onTap, + this.selectedIcon, + this.unselectedIcon, + this.tabText, + this.selectTabTextStyle, + this.unselectTabTextStyle, + this.badgeConfig, + this.popUpButtonConfig, + this.onLongPress, + this.allowMultipleTaps = false}) + : assert(() { if (badgeConfig?.showBadge ?? false) { if (badgeConfig?.tdBadge == null) { throw FlutterError('[NavigationTab] if set showBadge = true, ' @@ -104,7 +104,7 @@ class TDBottomTabBarTabConfig { /// 未选中时图标 final Widget? unselectedIcon; - /// tab文本 + /// tab 文本 final String? tabText; /// 文本已选择样式 basicType为text时必填 @@ -122,7 +122,7 @@ class TDBottomTabBarTabConfig { /// 弹窗配置 final TDBottomTabBarPopUpBtnConfig? popUpButtonConfig; - /// onTap方法允许点击多次 + /// onTap 方法允许点击多次 final bool allowMultipleTaps; /// 长按事件 @@ -206,7 +206,7 @@ class TDBottomTabBar extends StatefulWidget { /// tab高度 final double? barHeight; - /// 是否使用竖线分隔(如果选项样式为label则强制为false) + /// 是否使用竖线分隔(如果选项样式为 label,则强制为 false) final bool? useVerticalDivider; /// 分割线高度(可选) @@ -218,7 +218,7 @@ class TDBottomTabBar extends StatefulWidget { /// 分割线颜色(可选) final Color? dividerColor; - /// 是否展示bar上边线(设置为true 但是topBorder样式未设置,则使用默认值,非胶囊型才生效) + /// 是否展示bar上边线(设置为true 但是topBorder样式未设置,则使用默认值,非胶囊型才生效) final bool? showTopBorder; /// 上边线样式 @@ -287,14 +287,16 @@ class _TDBottomTabBarState extends State { ? const EdgeInsets.symmetric(horizontal: 16) : null, decoration: BoxDecoration( - color: widget.backgroundColor ?? Colors.white, - borderRadius: - isCapsuleOutlineType ? BorderRadius.circular(56) : null, + color: widget.backgroundColor ?? + TDTheme.of(context).bgColorContainer, + borderRadius: isCapsuleOutlineType + ? BorderRadius.circular(TDTheme.of(context).radiusCircle) + : null, border: widget.showTopBorder! && !isCapsuleOutlineType ? Border( top: widget.topBorder ?? BorderSide( - color: TDTheme.of(context).grayColor3, + color: TDTheme.of(context).componentStrokeColor, width: 0.5)) : null, boxShadow: isCapsuleOutlineType @@ -319,7 +321,8 @@ class _TDBottomTabBarState extends State { void _onTap(int index) { setState(() { - if (_selectedIndex != index || widget.navigationTabs[index].allowMultipleTaps) { + if (_selectedIndex != index || + widget.navigationTabs[index].allowMultipleTaps) { widget.navigationTabs[index].onTap?.call(); } if (_selectedIndex != index) { @@ -339,7 +342,7 @@ class _TDBottomTabBarState extends State { bottom: widget.basicType == TDBottomTabBarBasicType.iconText ? 5 : 7), child: TDBottomTabBarItemWithBadge( - basiceType: widget.basicType, + basicType: widget.basicType, componentType: widget.componentType ?? TDBottomTabBarComponentType.label, outlineType: widget.outlineType ?? TDBottomTabBarOutlineType.filled, @@ -362,7 +365,6 @@ class _TDBottomTabBarState extends State { } Widget _verticalDivider() { - if (widget.componentType == TDBottomTabBarComponentType.label) {} return Visibility( visible: widget.componentType != TDBottomTabBarComponentType.label && (widget.useVerticalDivider ?? false), @@ -373,7 +375,8 @@ class _TDBottomTabBarState extends State { width: widget.dividerThickness ?? 0.5, height: widget.dividerHeight ?? 32, child: VerticalDivider( - color: widget.dividerColor ?? TDTheme.of(context).grayColor3, + color: widget.dividerColor ?? + TDTheme.of(context).componentStrokeColor, thickness: widget.dividerThickness ?? 0.5, ), ); @@ -384,26 +387,26 @@ class _TDBottomTabBarState extends State { } class TDBottomTabBarItemWithBadge extends StatelessWidget { - const TDBottomTabBarItemWithBadge( - {Key? key, - required this.basiceType, - required this.componentType, - required this.outlineType, - required this.itemConfig, - required this.isSelected, - required this.itemHeight, - required this.itemWidth, - required this.onTap, - required this.tabsLength, - required this.selectedBgColor, - required this.unselectedBgColor, - required this.centerDistance, - this.onLongPress, - this.needInkWell = false}) - : super(key: key); + const TDBottomTabBarItemWithBadge({ + Key? key, + required this.basicType, + required this.componentType, + required this.outlineType, + required this.itemConfig, + required this.isSelected, + required this.itemHeight, + required this.itemWidth, + required this.onTap, + required this.tabsLength, + required this.selectedBgColor, + required this.unselectedBgColor, + required this.centerDistance, + this.onLongPress, + this.needInkWell = false, + }) : super(key: key); /// tab基本类型 - final TDBottomTabBarBasicType basiceType; + final TDBottomTabBarBasicType basicType; /// tab选中背景类型 final TDBottomTabBarComponentType componentType; @@ -446,10 +449,9 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { @override Widget build(BuildContext context) { - return GestureDetector( behavior: HitTestBehavior.opaque, - onTap: ()=>handleTap(context), + onTap: () => handleTap(context), onLongPress: () { onLongPress?.call(); }, @@ -466,13 +468,13 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { child: Container( /// 设计稿上 tab个数大于3时,左右边距为8,小于等于3时,左右边距为12 width: itemWidth - (tabsLength > 3 ? 16 : 24), - height: basiceType == TDBottomTabBarBasicType.text || - basiceType == TDBottomTabBarBasicType.expansionPanel + height: basicType == TDBottomTabBarBasicType.text || + basicType == TDBottomTabBarBasicType.expansionPanel ? 32 : null, decoration: BoxDecoration( color: isSelected - ? selectedBgColor ?? TDTheme.of(context).brandColor1 + ? selectedBgColor ?? TDTheme.of(context).brandLightColor : unselectedBgColor, borderRadius: const BorderRadius.all(Radius.circular(24)), ), @@ -497,11 +499,11 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { Widget _constructItem( BuildContext context, BadgeConfig? badgeConfig, bool isInOrOutCapsule) { Widget child = Container(); - if (basiceType == TDBottomTabBarBasicType.text) { + if (basicType == TDBottomTabBarBasicType.text) { child = _textItem(context, itemConfig, isSelected, TDTheme.of(context).fontTitleMedium!); } - if (basiceType == TDBottomTabBarBasicType.expansionPanel) { + if (basicType == TDBottomTabBarBasicType.expansionPanel) { if (itemConfig.popUpButtonConfig != null) { child = Row( mainAxisSize: MainAxisSize.min, @@ -511,7 +513,7 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { size: 16.0, color: isSelected ? TDTheme.of(context).brandNormalColor - : TDTheme.of(context).fontGyColor1, + : TDTheme.of(context).textColorPrimary, ), const SizedBox(width: 5), _textItem(context, itemConfig, isSelected, @@ -523,13 +525,13 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { TDTheme.of(context).fontTitleMedium!); } } - if (basiceType == TDBottomTabBarBasicType.icon) { + if (basicType == TDBottomTabBarBasicType.icon) { var selectedIcon = itemConfig.selectedIcon; var unSelectedIcon = itemConfig.unselectedIcon; child = isSelected ? selectedIcon! : unSelectedIcon!; } - if (basiceType == TDBottomTabBarBasicType.iconText) { + if (basicType == TDBottomTabBarBasicType.iconText) { var selectedIcon = itemConfig.selectedIcon; var unSelectedIcon = itemConfig.unselectedIcon; child = Column( @@ -541,12 +543,14 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { SizedBox( height: centerDistance, ), - itemConfig.tabText?.isNotEmpty ?? false ? _textItem( - context, - itemConfig, - isSelected, - TDTheme.of(context).fontBodyExtraSmall!, - ) : Container() + itemConfig.tabText?.isNotEmpty ?? false + ? _textItem( + context, + itemConfig, + isSelected, + TDTheme.of(context).fontBodyExtraSmall!, + ) + : Container() ], ); } @@ -575,7 +579,7 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { isSelected ? config.selectTabTextStyle : config.unselectTabTextStyle, textColor: isSelected ? TDTheme.of(context).brandNormalColor - : TDTheme.of(context).fontGyColor1, + : TDTheme.of(context).textColorPrimary, forceVerticalCenter: true, ); } @@ -590,7 +594,7 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { padding: EdgeInsets.only( top: isInOrOutCapsule ? 3.0 : 2.0, bottom: isInOrOutCapsule - ? (basiceType == TDBottomTabBarBasicType.iconText ? 0.0 : 1.0) + ? (basicType == TDBottomTabBarBasicType.iconText ? 0.0 : 1.0) : 0.0, ), color: Colors.transparent, @@ -606,8 +610,8 @@ class TDBottomTabBarItemWithBadge extends StatelessWidget { child: InkWell( borderRadius: isInOrOutCapsule ? BorderRadius.circular(24) : null, splashFactory: InkRipple.splashFactory, - splashColor: selectedBgColor ?? TDTheme.of(context).brandColor1, - highlightColor: selectedBgColor ?? TDTheme.of(context).brandColor1, + splashColor: selectedBgColor ?? TDTheme.of(context).brandLightColor, + highlightColor: selectedBgColor ?? TDTheme.of(context).brandLightColor, onTap: () => handleTap(context), child: child, ), @@ -668,7 +672,7 @@ class TDBottomTabBarPopUpBtnConfig { class TDBottomTabBarPopUpShapeConfig { TDBottomTabBarPopUpShapeConfig( {this.popUpWidth, - this.popUpitemHeight = _kDefaultMenuItemHeight, + this.popUpItemHeight = _kDefaultMenuItemHeight, this.backgroundColor, this.radius, this.arrowWidth, @@ -678,7 +682,7 @@ class TDBottomTabBarPopUpShapeConfig { final double? popUpWidth; /// 单个选项高度 所有选项等高 不设置则使用默认值 48 - final double? popUpitemHeight; + final double? popUpItemHeight; /// 弹窗背景颜色 final Color? backgroundColor; @@ -715,6 +719,10 @@ class PopUpMenuItem extends StatelessWidget { Widget build(BuildContext context) { return Container( constraints: const BoxConstraints(minHeight: _kMenuItemMinHeight), + decoration: BoxDecoration( + color: TDTheme.of(context).bgColorContainer, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + ), alignment: alignment, child: itemWidget ?? TDText( @@ -801,8 +809,8 @@ class PopupDialogState extends State { @override Widget build(BuildContext context) { - var popUpitemHeight = - widget.config?.popUpitemHeight ?? _kDefaultMenuItemHeight; + var popUpItemHeight = + widget.config?.popUpItemHeight ?? _kDefaultMenuItemHeight; var popUpItemWidth = widget.config?.popUpWidth ?? widget.defaultPopUpWidth; var menuItems = widget.items .map((e) => GestureDetector( @@ -812,7 +820,7 @@ class PopupDialogState extends State { Navigator.of(context).pop(); }, child: SizedBox( - height: popUpitemHeight, + height: popUpItemHeight, child: e, ))) .toList(); @@ -833,25 +841,28 @@ class PopupDialogState extends State { /// 这里 -8 是因为widget.btnContext是TDBottomTabBarItemWithBadge的,它在父widget内有8dp的padding /// -4 是设计稿上箭头和tab有4dp的距离 top: position!.top - - (popUpitemHeight * widget.items.length + + (popUpItemHeight * widget.items.length + (widget.config?.arrowHeight ?? _kArrowHeight)) - 8 - 4, right: position!.right - (popUpItemWidth + size!.width) / 2, child: Container( width: popUpItemWidth, - height: popUpitemHeight * widget.items.length + + height: popUpItemHeight * widget.items.length + (widget.config?.arrowHeight ?? _kArrowHeight), decoration: BoxDecoration(boxShadow: TDTheme.of(context).shadowsTop), child: CustomPaint( - painter: PanelWithDownArrow(config: widget.config), + painter: PanelWithDownArrow( + config: widget.config, + backgroundColor: widget.config?.backgroundColor ?? + TDTheme.of(context).bgColorContainer), child: Container( alignment: Alignment.topCenter, - height: popUpitemHeight * widget.items.length, + height: popUpItemHeight * widget.items.length, child: Container( constraints: BoxConstraints( - maxHeight: popUpitemHeight * widget.items.length), + maxHeight: popUpItemHeight * widget.items.length), child: Stack( children: [ Column(children: menuItems), @@ -865,7 +876,8 @@ class PopupDialogState extends State { child: Divider( thickness: 0.5, height: 0.5, - color: TDTheme.of(context).grayColor3, + color: TDTheme.of(context) + .componentStrokeColor, ), )), ) @@ -885,16 +897,15 @@ class PopupDialogState extends State { /// 带下箭头的展开panel class PanelWithDownArrow extends CustomPainter { TDBottomTabBarPopUpShapeConfig? config; + Color backgroundColor; - PanelWithDownArrow({ - this.config, - }); + PanelWithDownArrow({this.config, required this.backgroundColor}); @override void paint(Canvas canvas, Size size) { var paint = Paint() ..isAntiAlias = true - ..color = config?.backgroundColor ?? Colors.white + ..color = backgroundColor ..style = PaintingStyle.fill; var path = Path(); var panelWidth = size.width; diff --git a/tdesign-component/lib/src/components/table/td_table.dart b/tdesign-component/lib/src/components/table/td_table.dart index d2548fc23..49eb2eb7f 100644 --- a/tdesign-component/lib/src/components/table/td_table.dart +++ b/tdesign-component/lib/src/components/table/td_table.dart @@ -2,7 +2,7 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; import '../../../tdesign_flutter.dart'; -import 'td_table_col.dart'; +import '../../util/context_extension.dart'; typedef OnCellTap = void Function(int rowIndex, dynamic row, TDTableCol col); typedef OnScroll = void Function(ScrollController controller); @@ -172,7 +172,7 @@ class TDTableState extends State { ); } if (widget.data == null || widget.data!.isEmpty) { - return _getEmpty('暂无数据'); + return _buildEmpty(); } var cells = []; var fixedLeftCol = _getCol(TDTableColFixed.left); @@ -199,8 +199,8 @@ class TDTableState extends State { } cells.add(Container( color: (widget.stripe ?? false) && i % 2 == 0 - ? const Color(0xffF3F3F3) - : Colors.white, + ? TDTheme.of(context).bgColorSecondaryContainer + : TDTheme.of(context).bgColorContainer, child: Row(children: row), )); } @@ -217,8 +217,10 @@ class TDTableState extends State { var sortable = col.sortable ?? false; // 单元格边框 - var halfBorder = const BorderSide(width: 0.5, color: Color(0xffE7E7E7)); - var doubleBorder = const BorderSide(width: 2, color: Color(0xffE7E7E7)); + var halfBorder = + BorderSide(width: 0.5, color: TDTheme.of(context).componentStrokeColor); + var doubleBorder = + BorderSide(width: 1, color: TDTheme.of(context).componentStrokeColor); var topBorder = BorderSide.none, rightBorder = BorderSide.none, leftBorder = BorderSide.none; @@ -236,37 +238,38 @@ class TDTableState extends State { // 单元格内容 var text = _getCellText(col, title, ellipsis, isHeader, sortable, index); var content = text; - if((col.selection ?? false) && col.cellBuilder == null) { + if ((col.selection ?? false) && col.cellBuilder == null) { var checkBox; // 行选择框 - if(_notEmptyData()) { + if (_notEmptyData()) { var enable = col.selectable?.call(index, widget.data?[index]) ?? true; checkBox = TDCheckbox( id: 'index:$index', checked: _checkedList[index], enable: enable, customIconBuilder: (context, checked) { - if(checked) { - return Icon(TDIcons.check_rectangle_filled, size: 16, - color: TDTheme.of(context).brandNormalColor); + if (checked) { + return Icon(TDIcons.check_rectangle_filled, + size: 16, color: TDTheme.of(context).brandNormalColor); } - return Icon(TDIcons.rectangle, size: 16, - color: enable ? - TDTheme.of(context).fontGyColor1 : - TDTheme.of(context).fontGyColor3); + return Icon(TDIcons.rectangle, + size: 16, + color: enable + ? TDTheme.of(context).textColorPrimary + : TDTheme.of(context).textColorPlaceholder); }, onCheckBoxChanged: (checked) { setState(() { _checkedList[index] = checked; - if(checked) { + if (checked) { _hasChecked += 1; } else { _hasChecked -= 1; } _checkAll = _hasChecked == _totalSelectable; var selectList = []; - for(var i = 0; i < _checkedList.length; i++) { - if(_checkedList[i]) { + for (var i = 0; i < _checkedList.length; i++) { + if (_checkedList[i]) { selectList.add(widget.data![i]); } } @@ -278,28 +281,33 @@ class TDTableState extends State { } // 表头选择框 - if(isHeader) { + if (isHeader) { checkBox = TDCheckbox( id: 'header', checked: _checkAll, customIconBuilder: (context, checked) { - if(_hasChecked == 0 || _totalSelectable == 0) { - return Icon(TDIcons.rectangle, size: 16, color: TDTheme.of(context).fontGyColor3); + if (_hasChecked == 0) { + return Icon( + TDIcons.rectangle, + size: 16, + color: TDTheme.of(context).textColorPlaceholder, + ); } var allCheck = _hasChecked >= _totalSelectable; - var halfSelected = _hasChecked > 0 && _hasChecked < _totalSelectable; + var halfSelected = + _hasChecked > 0 && _hasChecked < _totalSelectable; return getAllIcon(allCheck, halfSelected); }, onCheckBoxChanged: (checked) { setState(() { - if(!_notEmptyData() && checked) { + if (!_notEmptyData() && checked) { _hasChecked = _totalSelectable = 1; } _checkAll = checked; _hasChecked = checked ? _totalSelectable : 0; - for (var i = 0; i < widget.data!.length; i++) { + for (var i = 0; i < widget.data!.length; i++) { // 不选中selectable == false的行 - if(_selectableCol.selectable!(i, widget.data![i])) { + if (_selectableCol.selectable!(i, widget.data![i])) { _checkedList[i] = checked; } } @@ -356,8 +364,8 @@ class TDTableState extends State { overflow: overflow, style: TextStyle( color: isHeader - ? TDTheme.of(context).fontGyColor3 - : TDTheme.of(context).fontGyColor1, + ? TDTheme.of(context).textColorPlaceholder + : TDTheme.of(context).textColorPrimary, fontSize: 14, height: 1, letterSpacing: 0, @@ -366,7 +374,7 @@ class TDTableState extends State { // 表头(需考虑排序模式) if (isHeader) { var selectColor = TDTheme.of(context).brandNormalColor; - var unSelectColor = TDTheme.of(context).fontGyColor3; + var unSelectColor = TDTheme.of(context).textColorPlaceholder; return Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, @@ -457,19 +465,19 @@ class TDTableState extends State { _hasChecked = 0; _checkedList = List.generate((widget.data?.length ?? 0), (index) => false); var cols = widget.columns.where((col) => col.selection ?? false); - if(cols.length > 1) { + if (cols.length > 1) { throw FlutterError('selectable column must be only one'); } - if(widget.data != null && cols.isNotEmpty) { + if (widget.data != null && cols.isNotEmpty) { _selectableCol = cols.first; var data = widget.data!; - for(var i = 0; i < data.length; i++) { + for (var i = 0; i < data.length; i++) { var check = _selectableCol.checked?.call(i, data[i]) ?? false; _checkedList[i] = check; - if(check) { + if (check) { _hasChecked++; } - if(_selectableCol.selectable?.call(i, data[i]) ?? false) { + if (_selectableCol.selectable?.call(i, data[i]) ?? false) { _totalSelectable++; } } @@ -503,8 +511,9 @@ class TDTableState extends State { // 固定列宽度 var fixedCellsWidth = 0.0; - for(var tableCol in widget.columns) { - if(tableCol.fixed == TDTableColFixed.left || tableCol.fixed == TDTableColFixed.right) { + for (var tableCol in widget.columns) { + if (tableCol.fixed == TDTableColFixed.left || + tableCol.fixed == TDTableColFixed.right) { fixedCellsWidth += (tableCol.width ?? cellWidth); } } @@ -518,7 +527,7 @@ class TDTableState extends State { // 非固定列宽度超过剩余宽度 需要开启滚动 if ((width - fixedCellsWidth) < fixedNonCellsWidth) { - var content = [Row(children: fixedNonCols), _getEmpty('暂无数据')]; + var content = [Row(children: fixedNonCols), _buildEmpty()]; if (widget.loading ?? false) { content = [ Row(children: fixedNonCols), @@ -534,7 +543,7 @@ class TDTableState extends State { } return Container( width: width, - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, @@ -557,7 +566,7 @@ class TDTableState extends State { } var child = Container( width: width, - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Row( children: [ ...fixedLeftCols, @@ -566,7 +575,7 @@ class TDTableState extends State { ], ), ); - var placeholder = _getEmpty('暂无数据'); + var placeholder = _buildEmpty(); if (widget.loading ?? false) { placeholder = Align( alignment: Alignment.center, @@ -578,13 +587,13 @@ class TDTableState extends State { ); } return Container( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Column(children: [child, placeholder]), ); } /// 空数据内容 - Widget _getEmpty(String defaultText) { + Widget _buildEmpty() { return Visibility( visible: widget.data == null || widget.data!.isEmpty, child: Align( @@ -594,16 +603,16 @@ class TDTableState extends State { child: TDEmpty( image: Visibility( visible: widget.empty?.assetUrl != null, - child: _getEmptyImage(), + child: _buildEmptyImage(), ), - emptyText: widget.empty?.text ?? defaultText, + emptyText: widget.empty?.text ?? context.resource.emptyData, ), ), ), ); } - TDImage _getEmptyImage() { + TDImage _buildEmptyImage() { var url = widget.empty?.assetUrl ?? ''; if (url.startsWith('http')) { return TDImage(imgUrl: url); @@ -650,10 +659,15 @@ class TDTableState extends State { /// 半选图标 Widget getAllIcon(bool checked, bool halfSelected) { return Icon( - checked ? TDIcons.check_rectangle_filled : halfSelected ? TDIcons.minus_rectangle_filled : TDIcons.check_rectangle, + checked + ? TDIcons.check_rectangle_filled + : halfSelected + ? TDIcons.minus_rectangle_filled + : TDIcons.check_rectangle, size: 16, - color: (checked || halfSelected) ? TDTheme.of(context).brandNormalColor : TDTheme.of(context).grayColor4 - ); + color: (checked || halfSelected) + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).textColorDisabled); } @override @@ -677,7 +691,7 @@ class TDTableState extends State { if (width < _getColsWidth()) { return Container( width: width, - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: SingleChildScrollView( scrollDirection: Axis.horizontal, physics: const ClampingScrollPhysics(), @@ -702,7 +716,7 @@ class TDTableState extends State { } return Container( width: width, - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, child: Column( children: [ Visibility( @@ -729,10 +743,10 @@ class ChevronPainter extends CustomPainter { required this.downColor, }); - /// 线条颜色(向上) + /// 线条颜色(向上) final Color upColor; - /// 线条颜色(向下) + /// 线条颜色(向下) final Color downColor; @override @@ -753,6 +767,7 @@ class ChevronPainter extends CustomPainter { upPath.moveTo(3.6, centerY - 1.8); upPath.lineTo(centerX, 2); upPath.lineTo(clientX - 3.6, centerY - 1.8); + upPath.close(); // 向下箭头 final downPaint = Paint() @@ -764,6 +779,7 @@ class ChevronPainter extends CustomPainter { downPath.moveTo(3.6, centerY + 1.8); downPath.lineTo(centerX, clientY - 2); downPath.lineTo(clientX - 3.6, centerY + 1.8); + downPath.close(); canvas.drawPath(upPath, upPaint); canvas.drawPath(downPath, downPaint); diff --git a/tdesign-component/lib/src/components/tabs/td_horizontal_tab_bar.dart b/tdesign-component/lib/src/components/tabs/td_horizontal_tab_bar.dart index 65e1535bd..209663b54 100644 --- a/tdesign-component/lib/src/components/tabs/td_horizontal_tab_bar.dart +++ b/tdesign-component/lib/src/components/tabs/td_horizontal_tab_bar.dart @@ -15,6 +15,7 @@ import '../../../tdesign_flutter.dart'; const double _kTabHeight = 46.0; const double _kTextAndIconTabHeight = 72.0; const double _kStartOffset = 52.0; + class _TabStyle extends AnimatedWidget { const _TabStyle({ Key? key, @@ -57,14 +58,17 @@ class _TabStyle extends AnimatedWidget { .copyWith(inherit: true); final textStyle = selected ? TextStyle.lerp(defaultStyle, defaultUnselectedStyle, animation.value)! - : TextStyle.lerp(defaultUnselectedStyle, defaultStyle, animation.value)!; + : TextStyle.lerp( + defaultUnselectedStyle, defaultStyle, animation.value)!; - final selectedColor = - labelColor ?? tabBarTheme.labelColor ?? labelStyle?.color ?? TDTheme.of(context).brandNormalColor; + final selectedColor = labelColor ?? + tabBarTheme.labelColor ?? + labelStyle?.color ?? + TDTheme.of(context).brandNormalColor; final unselectedColor = unselectedLabelColor ?? tabBarTheme.unselectedLabelColor ?? unselectedLabelStyle?.color ?? - TDTheme.of(context).fontGyColor2; // selectedColor.withAlpha(0xB2) // 70% alpha ?? + TDTheme.of(context).textColorPrimary; final color = selected ? Color.lerp(selectedColor, unselectedColor, animation.value)! @@ -125,7 +129,7 @@ class TDHorizontalTabBar extends StatefulWidget implements PreferredSizeWidget { this.backgroundColor, this.selectedBgColor, this.unSelectedBgColor, - this.tabAlignment + this.tabAlignment, }) : assert(indicator != null || (indicatorWeight > 0.0)), super(key: key); @@ -323,6 +327,7 @@ class TDHorizontalTabBar extends StatefulWidget implements PreferredSizeWidget { final Color? unSelectedBgColor; final TabAlignment? tabAlignment; + /// A size whose height depends on if the tabs have both icons and text. /// /// [AppBar] uses this size to compute its own preferred size. @@ -358,7 +363,8 @@ class TDHorizontalTabBar extends StatefulWidget implements PreferredSizeWidget { State createState() => _TDHorizontalTabBarState(); } -class _ChangeAnimation extends Animation with AnimationWithParentMixin { +class _ChangeAnimation extends Animation + with AnimationWithParentMixin { _ChangeAnimation(this.controller); final TabController controller; @@ -436,7 +442,8 @@ class _IndicatorPainter extends CustomPainter { assert(_currentTabOffsets!.isNotEmpty); assert(tabIndex >= 0); assert(tabIndex <= maxTabIndex); - return (_currentTabOffsets![tabIndex] + _currentTabOffsets![tabIndex + 1]) / 2.0; + return (_currentTabOffsets![tabIndex] + _currentTabOffsets![tabIndex + 1]) / + 2.0; } Rect indicatorRect(Size tabBarSize, int tabIndex) { @@ -465,7 +472,8 @@ class _IndicatorPainter extends CustomPainter { } final insets = indicatorPadding.resolve(_currentTextDirection); - final rect = Rect.fromLTWH(tabLeft, 0.0, tabRight - tabLeft, tabBarSize.height); + final rect = + Rect.fromLTWH(tabLeft, 0.0, tabRight - tabLeft, tabBarSize.height); if (!(rect.size >= insets.collapsedSize)) { throw FlutterError( @@ -521,7 +529,8 @@ double _indexChangeProgress(TabController controller) { } // The TabController animation's value is changing from previousIndex to currentIndex. - return (controllerValue - currentIndex).abs() / (currentIndex - previousIndex).abs(); + return (controllerValue - currentIndex).abs() / + (currentIndex - previousIndex).abs(); } class _TDHorizontalTabBarState extends State { @@ -564,7 +573,8 @@ class _TDHorizontalTabBarState extends State { // TODO(xu-baolin): Remove automatic adjustment to white color indicator // with a better long-term solution. // https://github.com/flutter/flutter/pull/68171#pullrequestreview-517753917 - if (widget.automaticIndicatorColorAdjustment && color.value == Material.of(context)?.color?.value) { + if (widget.automaticIndicatorColorAdjustment && + color.value == Material.of(context)?.color?.value) { color = Colors.white; } @@ -609,7 +619,8 @@ class _TDHorizontalTabBarState extends State { : _IndicatorPainter( controller: _controller!, indicator: _indicator, - indicatorSize: widget.indicatorSize ?? TabBarTheme.of(context).indicatorSize, + indicatorSize: + widget.indicatorSize ?? TabBarTheme.of(context).indicatorSize, indicatorPadding: widget.indicatorPadding, tabKeys: _tabKeys, old: _indicatorPainter, @@ -659,7 +670,8 @@ class _TDHorizontalTabBarState extends State { int get maxTabIndex => _indicatorPainter!.maxTabIndex; - double _tabScrollOffset(int index, double viewportWidth, double minExtent, double maxExtent) { + double _tabScrollOffset( + int index, double viewportWidth, double minExtent, double maxExtent) { if (!widget.isScrollable) { return 0.0; } @@ -676,22 +688,30 @@ class _TDHorizontalTabBarState extends State { double _tabCenteredScrollOffset(int index) { final position = _scrollController!.position; - return _tabScrollOffset(index, position.viewportDimension, position.minScrollExtent, position.maxScrollExtent); + return _tabScrollOffset(index, position.viewportDimension, + position.minScrollExtent, position.maxScrollExtent); } - double _initialScrollOffset(double viewportWidth, double minExtent, double maxExtent) { - return _tabScrollOffset(_currentIndex!, viewportWidth, minExtent, maxExtent); + double _initialScrollOffset( + double viewportWidth, double minExtent, double maxExtent) { + return _tabScrollOffset( + _currentIndex!, viewportWidth, minExtent, maxExtent); } void _scrollToCurrentIndex() { final offset = _tabCenteredScrollOffset(_currentIndex!); - _scrollController!.animateTo(offset, duration: kTabScrollDuration, curve: Curves.ease); + _scrollController! + .animateTo(offset, duration: kTabScrollDuration, curve: Curves.ease); } void _scrollToControllerValue() { - final leadingPosition = _currentIndex! > 0 ? _tabCenteredScrollOffset(_currentIndex! - 1) : null; + final leadingPosition = _currentIndex! > 0 + ? _tabCenteredScrollOffset(_currentIndex! - 1) + : null; final middlePosition = _tabCenteredScrollOffset(_currentIndex!); - final trailingPosition = _currentIndex! < maxTabIndex ? _tabCenteredScrollOffset(_currentIndex! + 1) : null; + final trailingPosition = _currentIndex! < maxTabIndex + ? _tabCenteredScrollOffset(_currentIndex! + 1) + : null; final index = _controller!.index.toDouble(); final value = _controller!.animation!.value; @@ -703,9 +723,13 @@ class _TDHorizontalTabBarState extends State { } else if (value == index) { offset = middlePosition; } else if (value < index) { - offset = leadingPosition == null ? middlePosition : lerpDouble(middlePosition, leadingPosition, index - value)!; + offset = leadingPosition == null + ? middlePosition + : lerpDouble(middlePosition, leadingPosition, index - value)!; } else { - offset = trailingPosition == null ? middlePosition : lerpDouble(middlePosition, trailingPosition, value - index)!; + offset = trailingPosition == null + ? middlePosition + : lerpDouble(middlePosition, trailingPosition, value - index)!; } _scrollController!.jumpTo(offset); @@ -734,7 +758,8 @@ class _TDHorizontalTabBarState extends State { } // Called each time layout completes. - void _saveTabOffsets(List tabOffsets, TextDirection textDirection, double width) { + void _saveTabOffsets( + List tabOffsets, TextDirection textDirection, double width) { _tabStripWidth = width; _indicatorPainter?.saveTabOffsets(tabOffsets, textDirection); } @@ -745,7 +770,8 @@ class _TDHorizontalTabBarState extends State { widget.onTap?.call(index); } - Widget _buildStyledTab(Widget child, bool selected, Animation animation) { + Widget _buildStyledTab( + Widget child, bool selected, Animation animation) { return _TabStyle( animation: animation, selected: selected, @@ -753,7 +779,7 @@ class _TDHorizontalTabBarState extends State { unselectedLabelColor: widget.unselectedLabelColor, labelStyle: widget.labelStyle, unselectedLabelStyle: widget.unselectedLabelStyle, - child:child, + child: child, ); } @@ -771,21 +797,29 @@ class _TDHorizontalTabBarState extends State { BoxDecoration? _getContentDecorateOuter(int index) { if (widget.outlineType == TDTabBarOutlineType.capsule) { return BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, ); } else if (widget.outlineType == TDTabBarOutlineType.card) { if (index == _currentIndex) { return BoxDecoration( - color: widget.backgroundColor ?? TDTheme.of(context).whiteColor1, + color: + widget.backgroundColor ?? TDTheme.of(context).bgColorContainer, borderRadius: BorderRadius.only( - topRight: Radius.circular(index + 1 < widget.tabs.length ? 9 : 0), - topLeft: Radius.circular(index > 0 ? 9 : 0))); + topRight: Radius.circular(index + 1 < widget.tabs.length + ? TDTheme.of(context).radiusLarge + : 0), + topLeft: Radius.circular( + index > 0 ? TDTheme.of(context).radiusLarge : 0))); } else { return BoxDecoration( - color: TDTheme.of(context).grayColor1, + color: TDTheme.of(context).bgColorSecondaryContainer, borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(index - 1 == _currentIndex ? 9 : 0), - bottomRight: Radius.circular(index + 1 == _currentIndex ? 9 : 0), + bottomLeft: Radius.circular(index - 1 == _currentIndex + ? TDTheme.of(context).radiusLarge + : 0), + bottomRight: Radius.circular(index + 1 == _currentIndex + ? TDTheme.of(context).radiusLarge + : 0), ), ); } @@ -796,14 +830,16 @@ class _TDHorizontalTabBarState extends State { Color? _getBackgroundColor(int index) { if (widget.outlineType == TDTabBarOutlineType.card) { if (index == _currentIndex) { - return TDTheme.of(context).grayColor1; + return TDTheme.of(context).bgColorSecondaryContainer; } } return null; } + TabAlignment get _defaults { return widget.isScrollable ? TabAlignment.start : TabAlignment.fill; } + bool _debugTabAlignmentIsValid(TabAlignment tabAlignment) { assert(() { if (widget.isScrollable && tabAlignment == TabAlignment.fill) { @@ -811,9 +847,9 @@ class _TDHorizontalTabBarState extends State { '$tabAlignment is only valid for non-scrollable tab bars.', ); } - if (!widget.isScrollable - && (tabAlignment == TabAlignment.start - || tabAlignment == TabAlignment.startOffset)) { + if (!widget.isScrollable && + (tabAlignment == TabAlignment.start || + tabAlignment == TabAlignment.startOffset)) { throw FlutterError( '$tabAlignment is only valid for scrollable tab bars.', ); @@ -822,10 +858,12 @@ class _TDHorizontalTabBarState extends State { }()); return true; } + @override Widget build(BuildContext context) { final tabBarTheme = TabBarTheme.of(context); - final TabAlignment effectiveTabAlignment = widget.tabAlignment ?? tabBarTheme.tabAlignment ?? _defaults; + final TabAlignment effectiveTabAlignment = + widget.tabAlignment ?? tabBarTheme.tabAlignment ?? _defaults; assert(_debugTabAlignmentIsValid(effectiveTabAlignment)); assert(debugCheckHasMaterialLocalizations(context)); assert(() { @@ -844,8 +882,6 @@ class _TDHorizontalTabBarState extends State { ); } - - final wrappedTabs = List.generate(widget.tabs.length, (int index) { const verticalAdjustment = (_kTextAndIconTabHeight - _kTabHeight) / 2.0; EdgeInsetsGeometry? adjustedPadding; @@ -856,7 +892,8 @@ class _TDHorizontalTabBarState extends State { adjustedPadding = (widget.labelPadding ?? tabBarTheme.labelPadding!) .add(const EdgeInsets.symmetric(vertical: verticalAdjustment)); } else { - adjustedPadding = const EdgeInsets.symmetric(vertical: verticalAdjustment, horizontal: 16.0); + adjustedPadding = const EdgeInsets.symmetric( + vertical: verticalAdjustment, horizontal: 16.0); } } // tab.size=20; @@ -899,22 +936,30 @@ class _TDHorizontalTabBarState extends State { // The user tapped on a tab, the tab controller's animation is running. assert(_currentIndex != previousIndex); final Animation animation = _ChangeAnimation(_controller!); - wrappedTabs[_currentIndex!] = _buildStyledTab(wrappedTabs[_currentIndex!], true, animation); - wrappedTabs[previousIndex] = _buildStyledTab(wrappedTabs[previousIndex], false, animation); + wrappedTabs[_currentIndex!] = + _buildStyledTab(wrappedTabs[_currentIndex!], true, animation); + wrappedTabs[previousIndex] = + _buildStyledTab(wrappedTabs[previousIndex], false, animation); } else { // The user is dragging the TDHorizontalTabBarView's PageView left or right. final tabIndex = _currentIndex!; - final Animation centerAnimation = _DragAnimation(_controller!, tabIndex); - wrappedTabs[tabIndex] = _buildStyledTab(wrappedTabs[tabIndex], true, centerAnimation); + final Animation centerAnimation = + _DragAnimation(_controller!, tabIndex); + wrappedTabs[tabIndex] = + _buildStyledTab(wrappedTabs[tabIndex], true, centerAnimation); if (_currentIndex! > 0) { final tabIndex = _currentIndex! - 1; - final Animation previousAnimation = ReverseAnimation(_DragAnimation(_controller!, tabIndex)); - wrappedTabs[tabIndex] = _buildStyledTab(wrappedTabs[tabIndex], false, previousAnimation); + final Animation previousAnimation = + ReverseAnimation(_DragAnimation(_controller!, tabIndex)); + wrappedTabs[tabIndex] = + _buildStyledTab(wrappedTabs[tabIndex], false, previousAnimation); } if (_currentIndex! < widget.tabs.length - 1) { final tabIndex = _currentIndex! + 1; - final Animation nextAnimation = ReverseAnimation(_DragAnimation(_controller!, tabIndex)); - wrappedTabs[tabIndex] = _buildStyledTab(wrappedTabs[tabIndex], false, nextAnimation); + final Animation nextAnimation = + ReverseAnimation(_DragAnimation(_controller!, tabIndex)); + wrappedTabs[tabIndex] = + _buildStyledTab(wrappedTabs[tabIndex], false, nextAnimation); } } } @@ -944,7 +989,8 @@ class _TDHorizontalTabBarState extends State { wrappedTabs[index], Semantics( selected: index == _currentIndex, - label: localizations.tabLabel(tabIndex: index + 1, tabCount: tabCount), + label: localizations.tabLabel( + tabIndex: index + 1, tabCount: tabCount), ), ], ), @@ -968,15 +1014,20 @@ class _TDHorizontalTabBarState extends State { unselectedLabelStyle: widget.unselectedLabelStyle, child: _TabLabelBar( onPerformLayout: _saveTabOffsets, - mainAxisSize: effectiveTabAlignment == TabAlignment.fill ? MainAxisSize.max : MainAxisSize.min, + mainAxisSize: effectiveTabAlignment == TabAlignment.fill + ? MainAxisSize.max + : MainAxisSize.min, children: wrappedTabs, ), ), ); if (widget.isScrollable) { - final EdgeInsetsGeometry? effectivePadding = effectiveTabAlignment == TabAlignment.startOffset - ? const EdgeInsetsDirectional.only(start: _kStartOffset).add(widget.padding ?? EdgeInsets.zero): widget.padding; + final EdgeInsetsGeometry? effectivePadding = + effectiveTabAlignment == TabAlignment.startOffset + ? const EdgeInsetsDirectional.only(start: _kStartOffset) + .add(widget.padding ?? EdgeInsets.zero) + : widget.padding; _scrollController ??= _TabBarScrollController(this); tdHorizontalTabBar = SingleChildScrollView( dragStartBehavior: widget.dragStartBehavior, @@ -997,7 +1048,8 @@ class _TDHorizontalTabBarState extends State { } } -typedef _LayoutCallback = void Function(List xOffsets, TextDirection textDirection, double width); +typedef _LayoutCallback = void Function( + List xOffsets, TextDirection textDirection, double width); // This class, and TabBarScrollPosition, only exist to handle the case // where a scrollable TabBar has a non-zero initialIndex. @@ -1007,7 +1059,8 @@ class _TabBarScrollController extends ScrollController { final _TDHorizontalTabBarState tabBar; @override - ScrollPosition createScrollPosition(ScrollPhysics physics, ScrollContext context, ScrollPosition? oldPosition) { + ScrollPosition createScrollPosition(ScrollPhysics physics, + ScrollContext context, ScrollPosition? oldPosition) { return _TabBarScrollPosition( physics: physics, context: context, @@ -1050,10 +1103,12 @@ class _TabBarScrollPosition extends ScrollPositionWithSingleContext { // effect without this guard because the super call below would starts a // ballistic scroll activity. _initialViewportDimensionWasZero = viewportDimension != 0.0; - correctPixels(tabBar._initialScrollOffset(viewportDimension, minScrollExtent, maxScrollExtent)); + correctPixels(tabBar._initialScrollOffset( + viewportDimension, minScrollExtent, maxScrollExtent)); result = false; } - return super.applyContentDimensions(minScrollExtent, maxScrollExtent) && result; + return super.applyContentDimensions(minScrollExtent, maxScrollExtent) && + result; } } @@ -1111,7 +1166,7 @@ class _TabLabelBarRenderer extends RenderFlex { // upon layout. The tab widths are only used at paint time (see _IndicatorPainter) // or in response to input. class _TabLabelBar extends Flex { - _TabLabelBar({ + const _TabLabelBar({ Key? key, List children = const [], required this.onPerformLayout, @@ -1141,13 +1196,15 @@ class _TabLabelBar extends Flex { } @override - void updateRenderObject(BuildContext context, _TabLabelBarRenderer renderObject) { + void updateRenderObject( + BuildContext context, _TabLabelBarRenderer renderObject) { super.updateRenderObject(context, renderObject); renderObject.onPerformLayout = onPerformLayout; } } -class _DragAnimation extends Animation with AnimationWithParentMixin { +class _DragAnimation extends Animation + with AnimationWithParentMixin { _DragAnimation(this.controller, this.index); final TabController controller; @@ -1174,7 +1231,8 @@ class _DragAnimation extends Animation with AnimationWithParentMixin { if ((_currentIndex! - previousIndex).abs() == 1) { _warpUnderwayCount += 1; - await _pageController.animateToPage(_currentIndex!, duration: duration, curve: Curves.ease); + await _pageController.animateToPage(_currentIndex!, + duration: duration, curve: Curves.ease); _warpUnderwayCount -= 1; return Future.value(); } assert((_currentIndex! - previousIndex).abs() > 1); - final initialPage = _currentIndex! > previousIndex ? _currentIndex! - 1 : _currentIndex! + 1; + final initialPage = _currentIndex! > previousIndex + ? _currentIndex! - 1 + : _currentIndex! + 1; final originalChildren = _childrenWithKey; setState(() { _warpUnderwayCount += 1; @@ -1358,7 +1419,8 @@ class _TDHorizontalTabBarViewState extends State { }); _pageController.jumpToPage(initialPage); - await _pageController.animateToPage(_currentIndex!, duration: duration, curve: Curves.ease); + await _pageController.animateToPage(_currentIndex!, + duration: duration, curve: Curves.ease); if (!mounted) { return Future.value(); } @@ -1383,17 +1445,20 @@ class _TDHorizontalTabBarViewState extends State { } _warpUnderwayCount += 1; - if (notification is ScrollUpdateNotification && !_controller!.indexIsChanging) { + if (notification is ScrollUpdateNotification && + !_controller!.indexIsChanging) { if ((_pageController.page! - _controller!.index).abs() > 1.0) { _controller!.index = _pageController.page!.round(); _currentIndex = _controller!.index; } - _controller!.offset = (_pageController.page! - _controller!.index).clamp(-1.0, 1.0); + _controller!.offset = + (_pageController.page! - _controller!.index).clamp(-1.0, 1.0); } else if (notification is ScrollEndNotification) { _controller!.index = _pageController.page!.round(); _currentIndex = _controller!.index; if (!_controller!.indexIsChanging) { - _controller!.offset = (_pageController.page! - _controller!.index).clamp(-1.0, 1.0); + _controller!.offset = + (_pageController.page! - _controller!.index).clamp(-1.0, 1.0); } } _warpUnderwayCount -= 1; @@ -1544,9 +1609,12 @@ class TabPageSelector extends StatelessWidget { @override Widget build(BuildContext context) { final fixColor = color ?? Colors.transparent; - final fixSelectedColor = selectedColor ?? Theme.of(context).colorScheme.secondary; - final selectedColorTween = ColorTween(begin: fixColor, end: fixSelectedColor); - final previousColorTween = ColorTween(begin: fixSelectedColor, end: fixColor); + final fixSelectedColor = + selectedColor ?? Theme.of(context).colorScheme.secondary; + final selectedColorTween = + ColorTween(begin: fixColor, end: fixSelectedColor); + final previousColorTween = + ColorTween(begin: fixSelectedColor, end: fixColor); final tabController = controller ?? DefaultTabController.of(context); final localizations = MaterialLocalizations.of(context); assert(() { @@ -1560,11 +1628,15 @@ class TabPageSelector extends StatelessWidget { animation: animation, builder: (BuildContext context, Widget? child) { return Semantics( - label: localizations.tabLabel(tabIndex: tabController.index + 1, tabCount: tabController.length), + label: localizations.tabLabel( + tabIndex: tabController.index + 1, + tabCount: tabController.length), child: Row( mainAxisSize: MainAxisSize.min, - children: List.generate(tabController.length, (int tabIndex) { - return _buildTabIndicator(tabIndex, tabController, selectedColorTween, previousColorTween); + children: + List.generate(tabController.length, (int tabIndex) { + return _buildTabIndicator(tabIndex, tabController, + selectedColorTween, previousColorTween); }).toList(), ), ); diff --git a/tdesign-component/lib/src/components/tabs/td_tab.dart b/tdesign-component/lib/src/components/tabs/td_tab.dart index 3fba9aff2..90d0a5c0f 100644 --- a/tdesign-component/lib/src/components/tabs/td_tab.dart +++ b/tdesign-component/lib/src/components/tabs/td_tab.dart @@ -5,11 +5,13 @@ import '../../../tdesign_flutter.dart'; enum TDTabSize { large, small } enum TDTabOutlineType { - // 填充样式 + /// 填充样式 filled, - // 胶囊样式 + + /// 胶囊样式 capsule, - // 卡片 + + /// 卡片 card } @@ -49,24 +51,31 @@ class TDTab extends Tab { /// 选项卡尺寸 final TDTabSize size; - ///选项卡样式 + /// 选项卡样式 final TDTabOutlineType outlineType; @override - const TDTab( - {Key? key, - this.text, - this.child, - this.icon, - this.badge, - this.height, - this.contentHeight, - this.textMargin, - this.size = TDTabSize.small, - this.outlineType = TDTabOutlineType.filled, - this.enable = true, - this.iconMargin = const EdgeInsets.only(bottom: 4.0, right: 4.0)}) - : super(key: key, text: text, child: child, icon: icon, height: height, iconMargin: iconMargin); + const TDTab({ + Key? key, + this.text, + this.child, + this.icon, + this.badge, + this.height, + this.contentHeight, + this.textMargin, + this.size = TDTabSize.small, + this.outlineType = TDTabOutlineType.filled, + this.enable = true, + this.iconMargin = const EdgeInsets.only(bottom: 4.0, right: 4.0), + }) : super( + key: key, + text: text, + child: child, + icon: icon, + height: height, + iconMargin: iconMargin, + ); final double _kTabHeight = 48.0; final double _kTextAndIconTabHeight = 72.0; @@ -109,13 +118,14 @@ class TDTab extends Tab { ], ); } - var isCapsuleOutlineType = outlineType == TDTabOutlineType.capsule; return IgnorePointer( ignoring: !enable, child: Container( alignment: Alignment.center, - margin: isCapsuleOutlineType ? const EdgeInsets.symmetric(horizontal: 16) : null, + margin: outlineType == TDTabOutlineType.capsule + ? const EdgeInsets.symmetric(horizontal: 16) + : null, height: height ?? calculatedHeight, child: Center( widthFactor: 1.0, @@ -129,7 +139,9 @@ class TDTab extends Tab { if (child != null) { return DefaultTextStyle( child: child!, - style: DefaultTextStyle.of(context).style.copyWith(fontSize: TDTheme.of(context).fontBodySmall?.size ?? 14), + style: DefaultTextStyle.of(context) + .style + .copyWith(fontSize: TDTheme.of(context).fontBodySmall?.size ?? 14), ); } return Text( diff --git a/tdesign-component/lib/src/components/tabs/td_tab_bar.dart b/tdesign-component/lib/src/components/tabs/td_tab_bar.dart index db9b9b88d..25cd26313 100644 --- a/tdesign-component/lib/src/components/tabs/td_tab_bar.dart +++ b/tdesign-component/lib/src/components/tabs/td_tab_bar.dart @@ -6,11 +6,13 @@ import '../../../tdesign_flutter.dart'; import 'td_horizontal_tab_bar.dart'; enum TDTabBarOutlineType { - // 填充样式 + /// 填充样式 filled, - // 胶囊样式 + + /// 胶囊样式 capsule, - // 卡片 + + /// 卡片 card } @@ -44,14 +46,14 @@ class TDTabBar extends StatefulWidget { this.unSelectedBgColor, this.tabAlignment, }) : assert( - backgroundColor == null || decoration == null, - 'Cannot provide both a backgroundColor and a decoration\n' - 'To provide both, use "decoration: BoxDecoration(color: color)".', - ), + backgroundColor == null || decoration == null, + 'Cannot provide both a backgroundColor and a decoration\n' + 'To provide both, use "decoration: BoxDecoration(color: color)".', + ), super(key: key); /// tab数组 - final List tabs; // + final List tabs; /// tab控制器 final TabController? controller; @@ -126,6 +128,7 @@ class TDTabBar extends StatefulWidget { final Color? unSelectedBgColor; final TabAlignment? tabAlignment; + @override State createState() => _TDTabBarState(); } @@ -141,33 +144,39 @@ class _TDTabBarState extends State { height: widget.height ?? _defaultHeight, decoration: widget.decoration ?? (widget.outlineType == TDTabBarOutlineType.card - ? BoxDecoration(color: widget.backgroundColor) + ? BoxDecoration( + color: widget.backgroundColor ?? + TDTheme.of(context).bgColorContainer) : BoxDecoration( - color: widget.backgroundColor, - border: widget.dividerHeight <= 0 - ? null - : Border( - bottom: BorderSide( - color: widget.dividerColor ?? TDTheme.of(context).grayColor3, - width: widget.dividerHeight)))), + color: widget.backgroundColor ?? + TDTheme.of(context).bgColorContainer, + border: widget.dividerHeight <= 0 + ? null + : Border( + bottom: BorderSide( + color: widget.dividerColor ?? + TDTheme.of(context).componentStrokeColor, + width: widget.dividerHeight)))), child: TDHorizontalTabBar( physics: widget.physics, isScrollable: widget.isScrollable, - indicator: widget.indicator ?? _getIndicator(context), + indicator: widget.indicator ?? _getIndicator(), indicatorColor: widget.indicatorColor, unselectedLabelColor: widget.unselectedLabelColor, - labelColor: widget.labelColor, - labelStyle: widget.labelStyle ?? _getLabelStyle(context), + labelColor: widget.labelColor ?? TDTheme.of(context).brandNormalColor, + labelStyle: widget.labelStyle ?? _getLabelStyle(), labelPadding: widget.labelPadding ?? const EdgeInsets.all(8), - unselectedLabelStyle:widget.unselectedLabelStyle ?? _getUnSelectLabelStyle(context), + unselectedLabelStyle: + widget.unselectedLabelStyle ?? _getUnSelectLabelStyle(), tabs: widget.tabs, indicatorPadding: widget.indicatorPadding ?? EdgeInsets.zero, outlineType: widget.outlineType, controller: widget.controller, backgroundColor: widget.backgroundColor, selectedBgColor: widget.selectedBgColor, - unSelectedBgColor: widget.unSelectedBgColor, - tabAlignment:widget.tabAlignment, + unSelectedBgColor: widget.unSelectedBgColor ?? + TDTheme.of(context).bgColorSecondaryContainer, + tabAlignment: widget.tabAlignment, onTap: (index) { widget.onTap?.call(index); }, @@ -175,27 +184,26 @@ class _TDTabBarState extends State { ); } - TextStyle _getUnSelectLabelStyle(BuildContext context) { + TextStyle _getUnSelectLabelStyle() { return TextStyle( fontWeight: FontWeight.w400, - // fontSize: TDTheme.of(context).fontBodySmall?.size ?? 14, - color: TDTheme.of(context).fontGyColor2); + color: TDTheme.of(context).textColorPrimary); } - TextStyle _getLabelStyle(BuildContext context) { + TextStyle _getLabelStyle() { return TextStyle( fontWeight: FontWeight.w600, - // fontSize: TDTheme.of(context).fontBodySmall?.size ?? 14, - color: TDTheme.of(context).fontGyColor2); + color: TDTheme.of(context).textColorPrimary); } - Decoration _getIndicator(BuildContext context) { + Decoration _getIndicator() { return widget.showIndicator ? TDTabBarIndicator( - context: context, - indicatorHeight: widget.indicatorHeight, - indicatorWidth: widget.indicatorWidth, - indicatorColor: widget.indicatorColor) + context: context, + indicatorHeight: widget.indicatorHeight, + indicatorWidth: widget.indicatorWidth, + indicatorColor: widget.indicatorColor, + ) : TDNoneIndicator(); } } @@ -207,10 +215,16 @@ class TDTabBarIndicator extends Decoration { final double? indicatorHeight; final Color? indicatorColor; - const TDTabBarIndicator({this.context, this.indicatorWidth, this.indicatorHeight, this.indicatorColor}); + const TDTabBarIndicator({ + this.context, + this.indicatorWidth, + this.indicatorHeight, + this.indicatorColor, + }); @override - BoxPainter createBoxPainter([VoidCallback? onChanged]) => _TDTabBarIndicatorPainter(this, onChanged!); + BoxPainter createBoxPainter([VoidCallback? onChanged]) => + _TDTabBarIndicatorPainter(this, onChanged!); } class _TDTabBarIndicatorPainter extends BoxPainter { @@ -226,7 +240,8 @@ class _TDTabBarIndicatorPainter extends BoxPainter { _TDTabBarIndicatorPainter(this.decoration, VoidCallback onChanged) { /// 下标颜色 - _paint.color = decoration.indicatorColor ?? TDTheme.of(decoration.context).brandNormalColor; + _paint.color = decoration.indicatorColor ?? + TDTheme.of(decoration.context).brandNormalColor; _paint.strokeCap = StrokeCap.round; } @@ -240,9 +255,11 @@ class _TDTabBarIndicatorPainter extends BoxPainter { _paint..strokeWidth = _indicatorHeight()); } - double _indicatorHeight() => decoration.indicatorHeight ?? _defaultIndicatorHeight; + double _indicatorHeight() => + decoration.indicatorHeight ?? _defaultIndicatorHeight; - double _indicatorWidth() => decoration.indicatorWidth ?? _defaultIndicatorWidth; + double _indicatorWidth() => + decoration.indicatorWidth ?? _defaultIndicatorWidth; } /// TDesign自定义下标 竖向 @@ -251,10 +268,15 @@ class TDTabBarVerticalIndicator extends Decoration { final double? indicatorWidth; final double? indicatorHeight; - const TDTabBarVerticalIndicator({this.context, this.indicatorWidth, this.indicatorHeight}); + const TDTabBarVerticalIndicator({ + this.context, + this.indicatorWidth, + this.indicatorHeight, + }); @override - BoxPainter createBoxPainter([VoidCallback? onChanged]) => _TDTabBarVerticalIndicatorPainter(this, onChanged!); + BoxPainter createBoxPainter([VoidCallback? onChanged]) => + _TDTabBarVerticalIndicatorPainter(this, onChanged!); } class _TDTabBarVerticalIndicatorPainter extends BoxPainter { @@ -288,15 +310,18 @@ class _TDTabBarVerticalIndicatorPainter extends BoxPainter { _paint..strokeWidth = _indicatorWidth()); } - double _indicatorHeight() => decoration.indicatorHeight ?? _defaultIndicatorHeight; + double _indicatorHeight() => + decoration.indicatorHeight ?? _defaultIndicatorHeight; - double _indicatorWidth() => decoration.indicatorWidth ?? _defaultIndicatorWidth; + double _indicatorWidth() => + decoration.indicatorWidth ?? _defaultIndicatorWidth; } /// TDesign不展示下标 class TDNoneIndicator extends Decoration { @override - BoxPainter createBoxPainter([VoidCallback? onChanged]) => _TDNoneIndicatorPainter(); + BoxPainter createBoxPainter([VoidCallback? onChanged]) => + _TDNoneIndicatorPainter(); } class _TDNoneIndicatorPainter extends BoxPainter { diff --git a/tdesign-component/lib/src/components/tag/td_select_tag.dart b/tdesign-component/lib/src/components/tag/td_select_tag.dart index da4ba62a0..c7a078e0e 100644 --- a/tdesign-component/lib/src/components/tag/td_select_tag.dart +++ b/tdesign-component/lib/src/components/tag/td_select_tag.dart @@ -5,27 +5,28 @@ import '../../../tdesign_flutter.dart'; /// 点击型标签组件,点击时内部更改自身状态 /// 支持样式:方形/圆角/半圆/带关闭图标 class TDSelectTag extends StatefulWidget { - const TDSelectTag(this.text, - {this.theme, - this.icon, - this.iconWidget, - this.selectStyle, - this.unSelectStyle, - this.disableSelectStyle, - this.onSelectChanged, - this.isSelected = false, - this.disableSelect = false, - this.size = TDTagSize.medium, - this.padding, - this.forceVerticalCenter = true, - this.isOutline = false, - this.shape = TDTagShape.square, - this.isLight = false, - this.needCloseIcon = false, - this.onCloseTap, - this.fixedWidth, - Key? key}) - : super(key: key); + const TDSelectTag( + this.text, { + this.theme, + this.icon, + this.iconWidget, + this.selectStyle, + this.unSelectStyle, + this.disableSelectStyle, + this.onSelectChanged, + this.isSelected = false, + this.disableSelect = false, + this.size = TDTagSize.medium, + this.padding, + this.forceVerticalCenter = true, + this.isOutline = false, + this.shape = TDTagShape.square, + this.isLight = false, + this.needCloseIcon = false, + this.onCloseTap, + this.fixedWidth, + Key? key, + }) : super(key: key); /// 标签内容 final String text; @@ -136,7 +137,8 @@ class _TDClickTagState extends State { if (widget.disableSelectStyle != null) { return widget.disableSelectStyle!; } - return TDTagStyle.generateDisableSelectStyle(context,widget.isOutline, widget.shape); + return TDTagStyle.generateDisableSelectStyle( + context, widget.isLight, widget.isOutline, widget.shape); } TDTagStyle _getSelectStyle() { @@ -156,9 +158,9 @@ class _TDClickTagState extends State { } return widget.isOutline ? TDTagStyle.generateOutlineStyleByTheme( - context, TDTagTheme.defaultTheme, widget.isLight, widget.shape) + context, TDTagTheme.defaultTheme, widget.isLight, widget.shape) : TDTagStyle.generateFillStyleByTheme( - context, TDTagTheme.defaultTheme, widget.isLight, widget.shape); + context, TDTagTheme.defaultTheme, widget.isLight, widget.shape); } @override diff --git a/tdesign-component/lib/src/components/tag/td_tag.dart b/tdesign-component/lib/src/components/tag/td_tag.dart index 10c5978bf..61914029a 100644 --- a/tdesign-component/lib/src/components/tag/td_tag.dart +++ b/tdesign-component/lib/src/components/tag/td_tag.dart @@ -3,30 +3,30 @@ import '../../../tdesign_flutter.dart'; /// 展示型标签组件,仅展示,内部不可更改自身状态 /// 支持样式:方形/圆角/半圆/带关闭图标 -/// class TDTag extends StatelessWidget { - const TDTag(this.text, - {this.theme, - this.icon, - this.iconWidget, - this.textColor, - this.backgroundColor, - this.font, - this.fontWeight, - this.style, - this.size = TDTagSize.medium, - this.padding, - this.forceVerticalCenter = true, - this.isOutline = false, - this.shape = TDTagShape.square, - this.isLight = false, - this.disable = false, - this.needCloseIcon = false, - this.onCloseTap, - this.overflow, - this.fixedWidth, - Key? key}) - : super(key: key); + const TDTag( + this.text, { + this.theme, + this.icon, + this.iconWidget, + this.textColor, + this.backgroundColor, + this.font, + this.fontWeight, + this.style, + this.size = TDTagSize.medium, + this.padding, + this.forceVerticalCenter = true, + this.isOutline = false, + this.shape = TDTagShape.square, + this.isLight = false, + this.disable = false, + this.needCloseIcon = false, + this.onCloseTap, + this.overflow, + this.fixedWidth, + Key? key, + }) : super(key: key); /// 标签内容 final String text; @@ -40,16 +40,16 @@ class TDTag extends StatelessWidget { /// 自定义图标内容,需自处理颜色 final Widget? iconWidget; - /// 文字颜色, 优先级高于style的textColor + /// 文字颜色,优先级高于style的textColor final Color? textColor; - /// 背景颜色, 优先级高于style的backgroundColor + /// 背景颜色,优先级高于style的backgroundColor final Color? backgroundColor; - /// 字体尺寸, 优先级高于style的font + /// 字体尺寸,优先级高于style的font final Font? font; - /// 字体粗细, 优先级高于style的fontWeight + /// 字体粗细,优先级高于style的fontWeight final FontWeight? fontWeight; /// 标签样式 @@ -114,19 +114,23 @@ class TDTag extends StatelessWidget { } children.add(child); if (needCloseIcon) { - children.add(GestureDetector( - onTap: onCloseTap, - child: Container( - margin: const EdgeInsets.only(left: 4), - child: Icon( - TDIcons.close, - color: TDTheme.of(context).fontGyColor3, - size: 14, + children.add( + GestureDetector( + onTap: onCloseTap, + child: Container( + margin: const EdgeInsets.only(left: 4), + child: Icon( + TDIcons.close, + color: innerStyle.closeIconColor ?? + TDTheme.of(context).textColorAnti, + size: 14, + ), ), ), - )); + ); } child = Row( + // spacing: TDTheme.of(context).spacer4, mainAxisSize: MainAxisSize.min, children: children, ); @@ -138,8 +142,7 @@ class TDTag extends StatelessWidget { decoration: BoxDecoration( color: backgroundColor ?? innerStyle.getBackgroundColor, border: Border.all( - width: innerStyle.border, - color: innerStyle.getBorderColor), + width: innerStyle.border, color: innerStyle.getBorderColor), borderRadius: innerStyle.getBorderRadius), child: Align( widthFactor: 1, @@ -148,19 +151,18 @@ class TDTag extends StatelessWidget { ); } - Widget? getIcon(TDTagStyle innerStyle){ - if(iconWidget != null){ + Widget? getIcon(TDTagStyle innerStyle) { + if (iconWidget != null) { return iconWidget; } - if(icon != null){ + if (icon != null) { return RichText( overflow: TextOverflow.visible, text: TextSpan( text: String.fromCharCode(icon!.codePoint), style: TextStyle( inherit: false, - color: - innerStyle.textColor, + color: innerStyle.textColor, height: 1, fontSize: _getIconSize(), fontFamily: icon!.fontFamily, @@ -176,14 +178,13 @@ class TDTag extends StatelessWidget { if (style != null) { return style!; } - if(disable){ - return TDTagStyle.generateDisableSelectStyle(context, isOutline, shape); + if (disable) { + return TDTagStyle.generateDisableSelectStyle( + context, isLight, isOutline, shape); } return isOutline - ? TDTagStyle.generateOutlineStyleByTheme( - context, theme, isLight, shape) - : TDTagStyle.generateFillStyleByTheme( - context, theme, isLight, shape); + ? TDTagStyle.generateOutlineStyleByTheme(context, theme, isLight, shape) + : TDTagStyle.generateFillStyleByTheme(context, theme, isLight, shape); } Font? _getFont(BuildContext context) { @@ -233,7 +234,12 @@ class TDTag extends StatelessWidget { } else { vPadding = 0; } - return EdgeInsets.only(left: hPadding, right: hPadding, top: vPadding, bottom: vPadding); + return EdgeInsets.only( + left: hPadding, + right: hPadding, + top: vPadding, + bottom: vPadding, + ); } double _getIconSize() { @@ -251,4 +257,3 @@ class TDTag extends StatelessWidget { } } } - diff --git a/tdesign-component/lib/src/components/tag/td_tag_styles.dart b/tdesign-component/lib/src/components/tag/td_tag_styles.dart index e15567a54..15678a659 100644 --- a/tdesign-component/lib/src/components/tag/td_tag_styles.dart +++ b/tdesign-component/lib/src/components/tag/td_tag_styles.dart @@ -27,15 +27,16 @@ enum TDTagShape { square, round, mark } /// 标签样式 class TDTagStyle { - TDTagStyle( - {this.context, - this.textColor, - this.backgroundColor, - this.font, - this.fontWeight, - this.border = 0, - this.borderColor, - this.borderRadius}); + TDTagStyle({ + this.context, + this.textColor, + this.backgroundColor, + this.font, + this.fontWeight, + this.border = 0, + this.borderColor, + this.borderRadius, + }); /// 上下文,方便获取主题内容 BuildContext? context; @@ -49,6 +50,9 @@ class TDTagStyle { /// 边框颜色 Color? borderColor; + /// 关闭图标颜色 + Color? closeIconColor; + /// 圆角 BorderRadiusGeometry? borderRadius; @@ -77,13 +81,17 @@ class TDTagStyle { /// 根据主题生成填充Tag样式 TDTagStyle.generateFillStyleByTheme( - BuildContext context, TDTagTheme? theme, bool light, TDTagShape shape) { + BuildContext context, + TDTagTheme? theme, + bool light, + TDTagShape shape, + ) { this.context = context; switch (theme) { case TDTagTheme.primary: textColor = light ? TDTheme.of(context).brandNormalColor - : TDTheme.of(context).whiteColor1; + : TDTheme.of(context).textColorAnti; backgroundColor = light ? TDTheme.of(context).brandLightColor : TDTheme.of(context).brandNormalColor; @@ -91,7 +99,7 @@ class TDTagStyle { case TDTagTheme.warning: textColor = light ? TDTheme.of(context).warningNormalColor - : TDTheme.of(context).whiteColor1; + : TDTheme.of(context).textColorAnti; backgroundColor = light ? TDTheme.of(context).warningLightColor : TDTheme.of(context).warningNormalColor; @@ -99,7 +107,7 @@ class TDTagStyle { case TDTagTheme.danger: textColor = light ? TDTheme.of(context).errorNormalColor - : TDTheme.of(context).whiteColor1; + : TDTheme.of(context).textColorAnti; backgroundColor = light ? TDTheme.of(context).errorLightColor : TDTheme.of(context).errorNormalColor; @@ -107,19 +115,19 @@ class TDTagStyle { case TDTagTheme.success: textColor = light ? TDTheme.of(context).successNormalColor - : TDTheme.of(context).whiteColor1; + : TDTheme.of(context).textColorAnti; backgroundColor = light ? TDTheme.of(context).successLightColor : TDTheme.of(context).successNormalColor; break; case TDTagTheme.defaultTheme: default: - textColor = TDTheme.of(context).fontGyColor1; + textColor = TDTheme.of(context).textColorPrimary; backgroundColor = light - ? TDTheme.of(context).grayColor1 - : TDTheme.of(context).grayColor3; + ? TDTheme.of(context).bgColorSecondaryContainer + : TDTheme.of(context).bgColorComponent; } - switch(shape){ + switch (shape) { case TDTagShape.square: borderRadius = BorderRadius.circular(TDTheme.of(context).radiusSmall); break; @@ -127,54 +135,58 @@ class TDTagStyle { borderRadius = BorderRadius.circular(TDTheme.of(context).radiusRound); break; case TDTagShape.mark: - borderRadius = BorderRadius.only(topRight:Radius.circular(TDTheme.of(context).radiusRound),bottomRight: Radius.circular(TDTheme.of(context).radiusRound)); + borderRadius = BorderRadius.only( + topRight: Radius.circular(TDTheme.of(context).radiusRound), + bottomRight: Radius.circular(TDTheme.of(context).radiusRound), + ); break; } + closeIconColor = textColor; borderColor = backgroundColor; } /// 根据主题生成描边Tag样式 TDTagStyle.generateOutlineStyleByTheme( - BuildContext context, TDTagTheme? theme, bool light, TDTagShape shape) { + BuildContext context, + TDTagTheme? theme, + bool light, + TDTagShape shape, + ) { this.context = context; switch (theme) { case TDTagTheme.primary: borderColor = TDTheme.of(context).brandNormalColor; textColor = TDTheme.of(context).brandNormalColor; - backgroundColor = light - ? TDTheme.of(context).brandLightColor - : TDTheme.of(context).whiteColor1; + backgroundColor = + light ? TDTheme.of(context).brandLightColor : Colors.transparent; break; case TDTagTheme.warning: borderColor = TDTheme.of(context).warningNormalColor; textColor = TDTheme.of(context).warningNormalColor; - backgroundColor = light - ? TDTheme.of(context).warningLightColor - : TDTheme.of(context).whiteColor1; + backgroundColor = + light ? TDTheme.of(context).warningLightColor : Colors.transparent; break; case TDTagTheme.danger: borderColor = TDTheme.of(context).errorNormalColor; textColor = TDTheme.of(context).errorNormalColor; - backgroundColor = light - ? TDTheme.of(context).errorLightColor - : TDTheme.of(context).whiteColor1; + backgroundColor = + light ? TDTheme.of(context).errorLightColor : Colors.transparent; break; case TDTagTheme.success: borderColor = TDTheme.of(context).successNormalColor; textColor = TDTheme.of(context).successNormalColor; - backgroundColor = light - ? TDTheme.of(context).successLightColor - : TDTheme.of(context).whiteColor1; + backgroundColor = + light ? TDTheme.of(context).successLightColor : Colors.transparent; break; case TDTagTheme.defaultTheme: default: - borderColor = TDTheme.of(context).fontGyColor4; - textColor = TDTheme.of(context).fontGyColor1; + borderColor = TDTheme.of(context).componentBorderColor; + textColor = TDTheme.of(context).textColorPrimary; backgroundColor = light - ? TDTheme.of(context).grayColor1 - : TDTheme.of(context).whiteColor1; + ? TDTheme.of(context).bgColorSecondaryContainer + : Colors.transparent; } - switch(shape){ + switch (shape) { case TDTagShape.square: borderRadius = BorderRadius.circular(TDTheme.of(context).radiusSmall); break; @@ -182,20 +194,28 @@ class TDTagStyle { borderRadius = BorderRadius.circular(TDTheme.of(context).radiusRound); break; case TDTagShape.mark: - borderRadius = BorderRadius.only(topRight:Radius.circular(TDTheme.of(context).radiusRound),bottomRight: Radius.circular(TDTheme.of(context).radiusRound)); + borderRadius = BorderRadius.only( + topRight: Radius.circular(TDTheme.of(context).radiusRound), + bottomRight: Radius.circular(TDTheme.of(context).radiusRound)); break; } border = 1; + closeIconColor = textColor; } /// 根据主题生成禁用Tag样式 TDTagStyle.generateDisableSelectStyle( - BuildContext context, bool isOutline , TDTagShape shape) { - - borderColor = TDTheme.of(context).grayColor4; - textColor = TDTheme.of(context).fontGyColor4; - backgroundColor = TDTheme.of(context).grayColor2; - switch(shape){ + BuildContext context, + bool isLight, + bool isOutline, + TDTagShape shape, + ) { + borderColor = TDTheme.of(context).componentBorderColor; + textColor = TDTheme.of(context).textColorDisabled; + backgroundColor = isOutline && !isLight + ? Colors.transparent + : TDTheme.of(context).bgColorComponentDisabled; + switch (shape) { case TDTagShape.square: borderRadius = BorderRadius.circular(TDTheme.of(context).radiusSmall); break; @@ -203,7 +223,9 @@ class TDTagStyle { borderRadius = BorderRadius.circular(TDTheme.of(context).radiusRound); break; case TDTagShape.mark: - borderRadius = BorderRadius.only(topRight:Radius.circular(TDTheme.of(context).radiusRound),bottomRight: Radius.circular(TDTheme.of(context).radiusRound)); + borderRadius = BorderRadius.only( + topRight: Radius.circular(TDTheme.of(context).radiusRound), + bottomRight: Radius.circular(TDTheme.of(context).radiusRound)); break; } border = isOutline ? 1 : 0; diff --git a/tdesign-component/lib/src/components/text/td_font_loader.dart b/tdesign-component/lib/src/components/text/td_font_loader.dart index 0c8840405..d27c47f85 100644 --- a/tdesign-component/lib/src/components/text/td_font_loader.dart +++ b/tdesign-component/lib/src/components/text/td_font_loader.dart @@ -1,19 +1,20 @@ - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../../tdesign_flutter.dart'; /// 线上字体加载工具 -class TDFontLoader{ - - /// 缓存字体FontLoader,防止重复加载 - static final _record = {}; +class TDFontLoader { + /// 缓存字体 FontLoader,防止重复加载 + static final _record = {}; /// 加载字体资源 - static Future load({required String name, required String fontFamilyUrl}) async { + static Future load({ + required String name, + required String fontFamilyUrl, + }) async { try { - if(!(_record[name] ?? false)) { + if (!(_record[name] ?? false)) { var fontLoader = FontLoader(name); fontLoader.addFont(Future(() async { @@ -27,19 +28,24 @@ class TDFontLoader{ } return true; } catch (e) { - print('TDFontLoader load error, name: ${name}, fontFamilyUrl: $fontFamilyUrl}, e: $e'); + print( + 'TDFontLoader load error, name: ${name}, fontFamilyUrl: $fontFamilyUrl}, e: $e'); } return false; } } -/// 懒加载FontWidget +/// 懒加载 FontWidget class TDFontLoaderWidget extends StatefulWidget { - const TDFontLoaderWidget({Key? key, required this.textWidget, required this.fontFamilyUrl}) : super(key: key); + const TDFontLoaderWidget({ + Key? key, + required this.textWidget, + required this.fontFamilyUrl, + }) : super(key: key); final TDText textWidget; - /// FontFamily的下载地址 + /// FontFamily 的下载地址 final String fontFamilyUrl; @override @@ -48,6 +54,7 @@ class TDFontLoaderWidget extends StatefulWidget { class _TDFontLoaderWidgetState extends State { bool fontFamilyLoaded = false; + @override void initState() { super.initState(); @@ -55,14 +62,17 @@ class _TDFontLoaderWidgetState extends State { } void loadFont() async { - if ((widget.textWidget.fontFamily?.fontFamily.isNotEmpty ?? false) - && widget.fontFamilyUrl.isNotEmpty) { + if ((widget.textWidget.fontFamily?.fontFamily.isNotEmpty ?? false) && + widget.fontFamilyUrl.isNotEmpty) { try { - if(await TDFontLoader.load(name: widget.textWidget.fontFamily!.fontFamily, fontFamilyUrl: widget.fontFamilyUrl)){ + if (await TDFontLoader.load( + name: widget.textWidget.fontFamily!.fontFamily, + fontFamilyUrl: widget.fontFamilyUrl)) { setState(() {}); } } catch (e) { - print('TDFontLoader loadFont error, data: ${widget.textWidget.data}, fontFamily: ${widget.textWidget.fontFamilyUrl}, e: $e'); + print( + 'TDFontLoader loadFont error, data: ${widget.textWidget.data}, fontFamily: ${widget.textWidget.fontFamilyUrl}, e: $e'); } } @@ -71,28 +81,31 @@ class _TDFontLoaderWidgetState extends State { @override Widget build(BuildContext context) { - return TDText(widget.textWidget.data, - font:widget.textWidget.font, - fontWeight:widget.textWidget.fontWeight ?? FontWeight.w400, - fontFamily:widget.textWidget.fontFamily, - textColor:widget.textWidget.textColor, - backgroundColor:widget.textWidget.backgroundColor, - isTextThrough:widget.textWidget.isTextThrough , - lineThroughColor:widget.textWidget.lineThroughColor, - package : widget.textWidget.package, - forceVerticalCenter :widget.textWidget.forceVerticalCenter, - style:widget.textWidget.style, - strutStyle:widget.textWidget.strutStyle, - textAlign:widget.textWidget.textAlign, - textDirection:widget.textWidget.textDirection, - locale:widget.textWidget.locale, - softWrap:widget.textWidget.softWrap, - overflow:widget.textWidget.overflow, - textScaleFactor:widget.textWidget.textScaleFactor, - maxLines:widget.textWidget.maxLines, - semanticsLabel:widget.textWidget.semanticsLabel, - textWidthBasis:widget.textWidget.textWidthBasis, - textHeightBehavior:widget.textWidget.textHeightBehavior, + final textWidget = widget.textWidget; + + return TDText( + textWidget.data, + font: textWidget.font, + fontWeight: textWidget.fontWeight ?? FontWeight.w400, + fontFamily: textWidget.fontFamily, + textColor: textWidget.textColor, + backgroundColor: textWidget.backgroundColor, + isTextThrough: textWidget.isTextThrough, + lineThroughColor: textWidget.lineThroughColor, + package: textWidget.package, + forceVerticalCenter: textWidget.forceVerticalCenter, + style: textWidget.style, + strutStyle: textWidget.strutStyle, + textAlign: textWidget.textAlign, + textDirection: textWidget.textDirection, + locale: textWidget.locale, + softWrap: textWidget.softWrap, + overflow: textWidget.overflow, + textScaleFactor: textWidget.textScaleFactor, + maxLines: textWidget.maxLines, + semanticsLabel: textWidget.semanticsLabel, + textWidthBasis: textWidget.textWidthBasis, + textHeightBehavior: textWidget.textHeightBehavior, isInFontLoader: true, ); } diff --git a/tdesign-component/lib/src/components/text/td_text.dart b/tdesign-component/lib/src/components/text/td_text.dart index c8f79c576..fb61fe920 100644 --- a/tdesign-component/lib/src/components/text/td_text.dart +++ b/tdesign-component/lib/src/components/text/td_text.dart @@ -16,19 +16,19 @@ var kTextNeedGlobalFontFamily = true; /// 文本控件 /// 设计原则: -/// 1.为了使用更方便,所以对系统组件进行的扩展,需兼容系统控件所有功能,不能让用户使用TDesign时,因不能满足系统功能而弃用。 -/// 2.非系统已有属性,尽量添加注释 +/// 1. 为了使用更方便,所以对系统组件进行的扩展,需兼容系统控件所有功能,不能让用户使用 TDesign 时,因不能满足系统功能而弃用。 +/// 2. 非系统已有属性,尽量添加注释 /// -/// 需求:把一部分在TextStyle中的属性扁平化,放到外层。 -/// 1.暴露系统的所有属性,支持系统所有操作 -/// 2.约束使用主题配置的几种字体 -/// 3.提供转换为系统Text的方法,以使某些系统组件指定接收系统Text时可使用。(Image组件同理) -/// 4.支持自定义TextStyle -/// 5.兼容TextSpan形式 +/// 需求:把一部分在 TextStyle 中的属性扁平化,放到外层。 +/// 1. 暴露系统的所有属性,支持系统所有操作 +/// 2. 约束使用主题配置的几种字体 +/// 3. 提供转换为系统 Text 的方法,以使某些系统组件指定接收系统 Text 时可使用。(Image 组件同理) +/// 4. 支持自定义 TextStyle +/// 5. 兼容 TextSpan 形式 /// /// 技巧: /// 命名参数替换属性的正则: -/// 第一步,把Text中的可选参数拷贝过来,变成如下格式: +/// 第一步,把 Text 中的可选参数拷贝过来,变成如下格式: /// Text(data, /// this.style, /// this.strutStyle, @@ -43,10 +43,10 @@ class TDText extends StatelessWidget { this.font, this.fontWeight, this.fontFamily, - this.textColor = Colors.black, + this.textColor, this.backgroundColor, this.isTextThrough = false, - this.lineThroughColor = Colors.white, + this.lineThroughColor, this.package, this.style, this.strutStyle, @@ -73,10 +73,10 @@ class TDText extends StatelessWidget { this.font, this.fontWeight, this.fontFamily, - this.textColor = Colors.black, + this.textColor, this.backgroundColor, this.isTextThrough = false, - this.lineThroughColor = Colors.white, + this.lineThroughColor, this.package, Key? key, this.style, @@ -97,7 +97,7 @@ class TDText extends StatelessWidget { }) : data = null, super(key: key); - /// 字体尺寸,包含大小size和行高height + /// 字体尺寸,包含 大小size 和 行高height final Font? font; /// 字体粗细 @@ -107,7 +107,7 @@ class TDText extends StatelessWidget { final FontFamily? fontFamily; /// 文本颜色 - final Color textColor; + final Color? textColor; /// 背景颜色 final Color? backgroundColor; @@ -115,16 +115,16 @@ class TDText extends StatelessWidget { /// 字体包名 final String? package; - /// 是否是横线穿过样式(删除线) + /// 是否是横线穿过样式(删除线) final bool? isTextThrough; - /// 删除线颜色,对应TestStyle的decorationColor + /// 删除线颜色,对应 TestStyle 的 decorationColor final Color? lineThroughColor; - /// 自定义的TextStyle,其中指定的属性,将覆盖扩展的外层属性 + /// 自定义的 TextStyle,其中指定的属性,将覆盖扩展的外层属性 final TextStyle? style; - /// 以下系统text属性,释义请参考系统[Text]中注释 + /// 以下系统 text 属性,释义请参考系统 [Text] 中注释 final data; final StrutStyle? strutStyle; @@ -154,16 +154,16 @@ class TDText extends StatelessWidget { /// 是否强制居中 final bool forceVerticalCenter; - /// 是否在FontLoader中使用 + /// 是否在 FontLoader 中使用 final bool isInFontLoader; - /// 是否禁用懒加载FontFamily的能力 + /// 是否禁用懒加载 FontFamily 的能力 final String? fontFamilyUrl; @override Widget build(BuildContext context) { if (fontFamilyUrl?.isNotEmpty ?? false) { - // 如果设置了Url,则使用TGFontLoader + // 如果设置了 Url,则使用 TGFontLoader return TDFontLoaderWidget( textWidget: this, fontFamilyUrl: fontFamilyUrl!, @@ -173,7 +173,9 @@ class TDText extends StatelessWidget { var config = getConfiguration(context); var paddingConfig = config?.paddingConfig; - var textFont = font ?? TDTheme.of(context).fontBodyLarge ?? Font(size: 16, lineHeight: 24); + var textFont = font ?? + TDTheme.of(context).fontBodyLarge ?? + Font(size: 16, lineHeight: 24); var fontSize = style?.fontSize ?? textFont.size; var height = style?.height ?? textFont.height; @@ -183,7 +185,9 @@ class TDText extends StatelessWidget { color: style?.backgroundColor ?? backgroundColor, height: fontSize * height, padding: paddingConfig.getPadding(data, fontSize, height), - child: _getRawText(context: context, textStyle: getTextStyle(context, height: showHeight)), + child: _getRawText( + context: context, + textStyle: getTextStyle(context, height: showHeight)), ); } var bgColor = style?.backgroundColor ?? backgroundColor; @@ -196,13 +200,16 @@ class TDText extends StatelessWidget { ); } - /// 提取成方法,允许业务定义自己的TDTextConfiguration + /// 提取成方法,允许业务定义自己的 TDTextConfiguration TDTextConfiguration? getConfiguration(BuildContext context) { return context.dependOnInheritedWidgetOfExactType(); } - TextStyle? getTextStyle(BuildContext context, {double? height, Color? backgroundColor}) { - var textFont = font ?? TDTheme.of(context).fontBodyLarge ?? Font(size: 16, lineHeight: 24); + TextStyle? getTextStyle(BuildContext context, + {double? height, Color? backgroundColor}) { + var textFont = font ?? + TDTheme.of(context).fontBodyLarge ?? + Font(size: 16, lineHeight: 24); var stylePackage = package ?? fontFamily?.package; var styleFontFamily = style?.fontFamily ?? fontFamily?.fontFamily; @@ -212,7 +219,7 @@ class TDText extends StatelessWidget { stylePackage ??= globalFontFamily?.package; } var realFontWeight = style?.fontWeight ?? fontWeight; - // Flutter 3.0之后,iOS w500之下字体不生效,需要替换字体 + // Flutter 3.0 之后,iOS w500 之下字体不生效,需要替换字体 if (PlatformUtil.isIOS && (styleFontFamily == null || styleFontFamily.isEmpty) && realFontWeight != null && @@ -220,11 +227,13 @@ class TDText extends StatelessWidget { stylePackage = null; styleFontFamily = 'PingFang SC'; } + var color = + style?.color ?? textColor ?? TDTheme.of(context).textColorPrimary; return TextStyle( inherit: style?.inherit ?? true, - color: style?.color ?? textColor, + color: color, - /// 不使用系统本身的背景色,因为系统属性存在中英文是,会导致颜色出现阶梯状 + /// 不使用系统本身的背景色,因为系统属性存在中英文时,会导致颜色出现阶梯状 backgroundColor: backgroundColor, fontSize: style?.fontSize ?? textFont.size, fontWeight: style?.fontWeight ?? fontWeight ?? textFont.fontWeight, @@ -239,30 +248,35 @@ class TDText extends StatelessWidget { background: style?.background, shadows: style?.shadows, fontFeatures: style?.fontFeatures, - decoration: style?.decoration ?? (isTextThrough! ? TextDecoration.lineThrough : TextDecoration.none), - decorationColor: style?.decorationColor ?? lineThroughColor, + decoration: style?.decoration ?? + (isTextThrough! ? TextDecoration.lineThrough : TextDecoration.none), + decorationColor: style?.decorationColor ?? lineThroughColor ?? color, decorationStyle: style?.decorationStyle, decorationThickness: style?.decorationThickness, debugLabel: style?.debugLabel, - // 如果需要字体懒加载,则清空fontFamily + // 如果需要字体懒加载,则清空 fontFamily fontFamily: styleFontFamily, fontFamilyFallback: style?.fontFamilyFallback, package: isInFontLoader ? null : stylePackage, ); } - /// 获取系统原始Text,以便使用到只能接收系统Text组件的地方 - /// 转化为系统原始Text后,将失去padding和background属性 + /// 获取系统原始 [Text],以便使用到只能接收系统 [Text] 组件的地方 + /// 转化为系统原始 [Text] 后,将失去 padding 和 background 属性 Text getRawText({required BuildContext context}) { return _getRawText(context: context, backgroundColor: backgroundColor); } - Text _getRawText({required BuildContext context, TextStyle? textStyle, Color? backgroundColor}) { + Text _getRawText( + {required BuildContext context, + TextStyle? textStyle, + Color? backgroundColor}) { return textSpan == null ? Text( data, key: key, - style: textStyle ?? getTextStyle(context, backgroundColor: backgroundColor), + style: textStyle ?? + getTextStyle(context, backgroundColor: backgroundColor), strutStyle: strutStyle, textAlign: textAlign, textDirection: textDirection, @@ -277,7 +291,8 @@ class TDText extends StatelessWidget { ) : Text.rich( textSpan!, - style: textStyle ?? getTextStyle(context, backgroundColor: backgroundColor), + style: textStyle ?? + getTextStyle(context, backgroundColor: backgroundColor), strutStyle: strutStyle, textAlign: textAlign, textDirection: textDirection, @@ -293,17 +308,18 @@ class TDText extends StatelessWidget { } } -/// TextSpan的TDesign扩展,将部分TextStyle中的参数扁平化。 +/// TextSpan 的 TDesign 扩展,将部分 TextStyle 中的参数扁平化。 class TDTextSpan extends TextSpan { /// 构造参数,扩展参数释义可参考[TDText]中字段注释 TDTextSpan({ - BuildContext? context, // 如果未设置font,且不想使用默认的fontBodyLarge尺寸时,需设置context,否则可省略 + BuildContext? + context, // 如果未设置font,且不想使用默认的 fontBodyLarge 尺寸时,需设置context,否则可省略 Font? font, FontWeight? fontWeight, FontFamily? fontFamily, - Color textColor = Colors.black, + Color? textColor, bool? isTextThrough = false, - Color? lineThroughColor = Colors.white, + Color? lineThroughColor, String? package, String? text, List? children, @@ -316,8 +332,8 @@ class TDTextSpan extends TextSpan { }) : super( text: text, children: children, - style: _getTextStyle( - context, style, font, fontWeight, fontFamily, textColor, isTextThrough, lineThroughColor, package), + style: _getTextStyle(context, style, font, fontWeight, fontFamily, + textColor, isTextThrough, lineThroughColor, package), recognizer: recognizer, mouseCursor: mouseCursor, onEnter: onEnter, @@ -331,15 +347,19 @@ class TDTextSpan extends TextSpan { Font? font, FontWeight? fontWeight, FontFamily? fontFamily, - Color textColor, + Color? textColor, bool? isTextThrough, Color? lineThroughColor, String? package, ) { - var textFont = font ?? TDTheme.of(context).fontBodyLarge ?? Font(size: 16, lineHeight: 24); + var textFont = font ?? + TDTheme.of(context).fontBodyLarge ?? + Font(size: 16, lineHeight: 24); + var color = + style?.color ?? textColor ?? TDTheme.of(context).textColorPrimary; return TextStyle( inherit: style?.inherit ?? true, - color: style?.color ?? textColor, + color: color, backgroundColor: style?.backgroundColor, fontSize: style?.fontSize ?? textFont.size, fontWeight: style?.fontWeight ?? fontWeight ?? textFont.fontWeight, @@ -354,8 +374,9 @@ class TDTextSpan extends TextSpan { background: style?.background, shadows: style?.shadows, fontFeatures: style?.fontFeatures, - decoration: style?.decoration ?? (isTextThrough! ? TextDecoration.lineThrough : TextDecoration.none), - decorationColor: style?.decorationColor ?? lineThroughColor, + decoration: style?.decoration ?? + (isTextThrough! ? TextDecoration.lineThrough : TextDecoration.none), + decorationColor: style?.decorationColor ?? lineThroughColor ?? color, decorationStyle: style?.decorationStyle, decorationThickness: style?.decorationThickness, debugLabel: style?.debugLabel, @@ -366,15 +387,19 @@ class TDTextSpan extends TextSpan { } } -/// 存储可以自定义TDText居中算法数据的内部控件 +/// 存储可以自定义 TDText 居中算法数据的内部控件 class TDTextConfiguration extends InheritedWidget { - /// forceVerticalCenter=true时,内置padding配置 + /// forceVerticalCenter=true 时,内置 padding 配置 final TDTextPaddingConfig? paddingConfig; - /// 全局字体,kTextNeedGlobalFontFamily=true时生效 + /// 全局字体,kTextNeedGlobalFontFamily=true 时生效 final FontFamily? globalFontFamily; - const TDTextConfiguration({Key? key, required Widget child, this.paddingConfig, this.globalFontFamily}) + const TDTextConfiguration( + {Key? key, + required Widget child, + this.paddingConfig, + this.globalFontFamily}) : super(key: key, child: child); @override @@ -383,10 +408,10 @@ class TDTextConfiguration extends InheritedWidget { } } -/// 通过Padding自定义TDText居中算法 +/// 通过 Padding 自定义 TDText 居中算法 class TDTextPaddingConfig { static TDTextPaddingConfig? _defaultConfig; - static final Map _cacheMap = {}; + static final Map> _cacheMap = {}; /// 获取默认配置 static TDTextPaddingConfig getDefaultConfig() { @@ -394,7 +419,7 @@ class TDTextPaddingConfig { return _defaultConfig!; } - /// 获取padding + /// 获取 padding EdgeInsetsGeometry getPadding(String? data, double fontSize, double height) { var cache = _cacheMap[fontSize]?[height]; if (cache != null) { @@ -427,17 +452,18 @@ class TDTextPaddingConfig { return padding; } - /// 以多个汉字测量计算的平均值,Android为Pixel 4模拟器,iOS为iphone 8 plus 模拟器 + /// todo 【待优化】在 web 中,顶部会有内边距(如24号字体有大小为6的内边距) + /// 以多个汉字测量计算的平均值,Android为Pixel 4 模拟器,iOS 为 iphone 8 plus 模拟器 double get paddingRate { if (VersionUtil.isAfterThen('3.2.0')) { - // Dart 3.2.0之后,文字渲染高度有改变. + // Dart 3.2.0 之后,文字渲染高度有改变。 return PlatformUtil.isWeb ? 29 / 128 : PlatformUtil.isAndroid ? -20 / 128 : PlatformUtil.isOhos - ? 43 / 128 - : -10 / 128; + ? 43 / 128 + : -10 / 128; } return PlatformUtil.isWeb ? 3 / 8 @@ -448,9 +474,9 @@ class TDTextPaddingConfig { : 0; } - /// 以多个汉字测量计算的平均值,Android为Pixel 4模拟器,iOS为iphone 8 plus 模拟器 + /// 以多个汉字测量计算的平均值,Android 为 Pixel 4 模拟器,iOS 为 iphone 8 plus 模拟器 double get paddingExtraRate => PlatformUtil.isAndroid ? 115 / 256 : 97 / 240; - /// height比率,因为设置1时,Android文字可能显示不全,默认为1.1 + /// height比 率,因为设置 1 时,Android 文字可能显示不全,默认为 1.1 double get heightRate => PlatformUtil.isAndroid ? 1.1 : 1; } diff --git a/tdesign-component/lib/src/components/textarea/td_textarea.dart b/tdesign-component/lib/src/components/textarea/td_textarea.dart index 128876a39..23f6f77d1 100644 --- a/tdesign-component/lib/src/components/textarea/td_textarea.dart +++ b/tdesign-component/lib/src/components/textarea/td_textarea.dart @@ -16,50 +16,50 @@ enum TDTextareaLayout { vertical, horizontal } /// 用于多行文本信息输入 class TDTextarea extends StatefulWidget { - const TDTextarea({ - Key? key, - this.width, - this.textStyle, - this.backgroundColor = Colors.white, - this.decoration, - this.labelStyle, - this.required, - this.readOnly = false, - this.autofocus = false, - this.onEditingComplete, - this.onSubmitted, - this.hintText, - this.inputType, - this.onChanged, - this.inputFormatters, - this.inputDecoration, - this.maxLines, - this.minLines = 4, - this.focusNode, - this.controller, - this.cursorColor, - this.hintTextStyle, - this.labelWidget, - this.textInputBackgroundColor, - this.size = TDInputSize.large, - this.maxLength, - this.maxLengthEnforcement, - this.allowInputOverMax = false, - this.additionInfo = '', - this.additionInfoColor, - this.textAlign, - this.label, - this.indicator = false, - this.layout = TDTextareaLayout.horizontal, - this.autosize, - this.labelIcon, - this.labelWidth, - this.margin, - this.padding, - this.textareaDecoration, - this.bordered, - this.showBottomDivider=true - }) : super(key: key); + const TDTextarea( + {Key? key, + this.width, + this.textStyle, + this.backgroundColor, + this.decoration, + this.labelStyle, + this.required, + this.readOnly = false, + this.autofocus = false, + this.onEditingComplete, + this.onSubmitted, + this.hintText, + this.inputType, + this.onChanged, + this.inputFormatters, + this.inputDecoration, + this.maxLines, + this.minLines = 4, + this.focusNode, + this.controller, + this.cursorColor, + this.hintTextStyle, + this.labelWidget, + this.textInputBackgroundColor, + this.size = TDInputSize.large, + this.maxLength, + this.maxLengthEnforcement, + this.allowInputOverMax = false, + this.additionInfo = '', + this.additionInfoColor, + this.textAlign, + this.label, + this.indicator = false, + this.layout = TDTextareaLayout.horizontal, + this.autosize, + this.labelIcon, + this.labelWidth, + this.margin, + this.padding, + this.textareaDecoration, + this.bordered, + this.showBottomDivider = true}) + : super(key: key); /// 输入框宽度 final double? width; @@ -183,6 +183,7 @@ class TDTextarea extends StatefulWidget { /// 边框外部下划线 final bool? showBottomDivider; + @override _TDTextareaState createState() => _TDTextareaState(); } @@ -214,24 +215,26 @@ class _TDTextareaState extends State { @override Widget build(BuildContext context) { var padding = _getInputPadding(context); - var textareaView = _getTextareaView(context, _getInputView(context), _getIndicatorView(context)); - var container = _getContainer(context, _getLabelView(context), textareaView); + var textareaView = _getTextareaView( + context, _getInputView(context), _getIndicatorView(context)); + var container = + _getContainer(context, _getLabelView(context), textareaView); if (widget.bordered == true || widget.decoration != null) { return container; } return Stack( children: [ container, - if(widget.showBottomDivider!=null && widget!.showBottomDivider==true) - Positioned( - bottom: 0, - left: padding, - right: 0, - child: Container( - height: 0.5, - color: TDTheme.of(context).grayColor3, - ), - ), + if (widget.showBottomDivider != null && + widget!.showBottomDivider == true) + Positioned( + bottom: 0, + left: padding, + right: 0, + child: Divider( + height: 0.5, + color: TDTheme.of(context).componentStrokeColor, + )), ], ); } @@ -239,13 +242,19 @@ class _TDTextareaState extends State { Widget _getLabelView(BuildContext context) { var padding = _getInputPadding(context); var isHorizontal = widget.layout == TDTextareaLayout.horizontal; - var fontSize = isHorizontal ? TDTheme.of(context).fontBodyLarge?.size : TDTheme.of(context).fontBodyMedium?.size; - if ((widget.label == null || widget.label == '') && widget.labelIcon == null && widget.labelWidget == null) { + var fontSize = isHorizontal + ? TDTheme.of(context).fontBodyLarge?.size + : TDTheme.of(context).fontBodyMedium?.size; + if ((widget.label == null || widget.label == '') && + widget.labelIcon == null && + widget.labelWidget == null) { return const SizedBox.shrink(); } return Container( width: widget.labelWidth, - padding: isHorizontal ? EdgeInsets.only(right: padding) : EdgeInsets.only(bottom: TDTheme.of(context).spacer8), + padding: isHorizontal + ? EdgeInsets.only(right: padding) + : EdgeInsets.only(bottom: TDTheme.of(context).spacer8), child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -253,7 +262,10 @@ class _TDTextareaState extends State { widget.label != null && widget.label != '' ? Flexible( child: Padding( - padding: EdgeInsets.only(left: widget.labelIcon != null ? TDTheme.of(context).spacer4 : 0), + padding: EdgeInsets.only( + left: widget.labelIcon != null + ? TDTheme.of(context).spacer4 + : 0), child: TDText( widget.label!, maxLines: isHorizontal ? 2 : 1, @@ -269,7 +281,10 @@ class _TDTextareaState extends State { padding: EdgeInsets.only(left: TDTheme.of(context).spacer4), child: TDText( '*', - style: TextStyle(color: TDTheme.of(context).errorColor6, fontSize: fontSize, height: 1.3), + style: TextStyle( + color: TDTheme.of(context).errorColor6, + fontSize: fontSize, + height: 1.3), ), ) : const SizedBox.shrink(), @@ -283,7 +298,8 @@ class _TDTextareaState extends State { child: ConstrainedBox( constraints: const BoxConstraints(minHeight: 24), // 设置最小高度为24 child: TDInputView( - textStyle: widget.textStyle ?? TextStyle(color: TDTheme.of(context).fontGyColor1), + textStyle: widget.textStyle ?? + TextStyle(color: TDTheme.of(context).textColorPrimary), readOnly: widget.readOnly ?? false, autofocus: widget.autofocus ?? false, onEditingComplete: widget.onEditingComplete, @@ -291,10 +307,9 @@ class _TDTextareaState extends State { hintText: widget.hintText, inputType: widget.inputType, textAlign: widget.textAlign, - onChanged:(val){ - setState(() { - }); - if(widget.onChanged!=null){ + onChanged: (val) { + setState(() {}); + if (widget.onChanged != null) { widget.onChanged!(val); } }, @@ -316,7 +331,9 @@ class _TDTextareaState extends State { isCollapsed: true, hintTextStyle: widget.hintTextStyle ?? TextStyle( - color: widget.readOnly == true ? TDTheme.of(context).fontGyColor4 : TDTheme.of(context).fontGyColor3), + color: widget.readOnly == true + ? TDTheme.of(context).textColorDisabled + : TDTheme.of(context).textColorPlaceholder), cursorColor: widget.cursorColor, textInputBackgroundColor: widget.textInputBackgroundColor, controller: widget.controller, @@ -328,7 +345,8 @@ class _TDTextareaState extends State { Widget _getIndicatorView(BuildContext context) { var padding = _getInputPadding(context); - var showAdditionInfo = widget.additionInfo != '' && widget.additionInfo != null; + var showAdditionInfo = + widget.additionInfo != '' && widget.additionInfo != null; var showIndicator = widget.indicator == true && widget.maxLength != null; var widgetList = []; if (showAdditionInfo) { @@ -343,7 +361,8 @@ class _TDTextareaState extends State { widget.additionInfo!, style: TextStyle( fontSize: TDTheme.of(context).fontBodySmall?.size, - color: widget.additionInfoColor ?? TDTheme.of(context).fontGyColor3, + color: widget.additionInfoColor ?? + TDTheme.of(context).textColorPlaceholder, ), ), ); @@ -358,7 +377,9 @@ class _TDTextareaState extends State { if (showIndicator) { widgetList.add(TDText( '${widget.controller?.text.length ?? 0}/${widget.maxLength}', - style: TextStyle(fontSize: TDTheme.of(context).fontBodySmall?.size, color: TDTheme.of(context).fontGyColor3), + style: TextStyle( + fontSize: TDTheme.of(context).fontBodySmall?.size, + color: TDTheme.of(context).textColorPlaceholder), )); } return Visibility( @@ -371,15 +392,21 @@ class _TDTextareaState extends State { ); } - Widget _getTextareaView(BuildContext context, Widget inputView, Widget indicatorView) { + Widget _getTextareaView( + BuildContext context, Widget inputView, Widget indicatorView) { var padding = _getInputPadding(context); return Container( decoration: widget.textareaDecoration ?? (widget.bordered == true ? BoxDecoration( - color: widget.decoration != null ? null : (widget.backgroundColor ?? Colors.white), - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), - border: Border.all(color: TDTheme.of(context).grayColor4), + color: widget.decoration != null + ? null + : (widget.backgroundColor ?? + TDTheme.of(context).bgColorContainer), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault), + border: Border.all( + color: TDTheme.of(context).componentBorderColor), ) : null), padding: widget.bordered == true ? EdgeInsets.all(padding) : null, @@ -392,7 +419,8 @@ class _TDTextareaState extends State { ); } - Widget _getContainer(BuildContext context, Widget labelView, Widget textareaView) { + Widget _getContainer( + BuildContext context, Widget labelView, Widget textareaView) { var padding = _getInputPadding(context); var isHorizontal = widget.layout == TDTextareaLayout.horizontal; return Container( diff --git a/tdesign-component/lib/src/components/time_counter/td_time_counter.dart b/tdesign-component/lib/src/components/time_counter/td_time_counter.dart index 196364113..b56bb2865 100644 --- a/tdesign-component/lib/src/components/time_counter/td_time_counter.dart +++ b/tdesign-component/lib/src/components/time_counter/td_time_counter.dart @@ -80,7 +80,8 @@ class TDTimeCounter extends StatefulWidget { _TDTimeCounterState createState() => _TDTimeCounterState(); } -class _TDTimeCounterState extends State with SingleTickerProviderStateMixin { +class _TDTimeCounterState extends State + with SingleTickerProviderStateMixin { late TDTimeCounterStyle _style; late Map timeUnitMap; Ticker? _ticker; @@ -144,9 +145,11 @@ class _TDTimeCounterState extends State with SingleTickerProvider widget.direction == TDTimeCounterDirection.up && _time < _maxTime) { setState(() { if (widget.direction == TDTimeCounterDirection.down) { - _time = max(_time - (elapsed.inMilliseconds - _tempMilliseconds), 0); + _time = + max(_time - (elapsed.inMilliseconds - _tempMilliseconds), 0); } else { - _time = min(_time + (elapsed.inMilliseconds - _tempMilliseconds), _maxTime); + _time = min( + _time + (elapsed.inMilliseconds - _tempMilliseconds), _maxTime); } }); _tempMilliseconds = elapsed.inMilliseconds; @@ -211,7 +214,8 @@ class _TDTimeCounterState extends State with SingleTickerProvider @override Widget build(BuildContext context) { if (widget.content == 'default') { - return Row(mainAxisSize: MainAxisSize.min, children: _buildTimeWidget(context)); + return Row( + mainAxisSize: MainAxisSize.min, children: _buildTimeWidget(context)); } if (widget.content is Function) { return widget.content(_time); @@ -220,7 +224,9 @@ class _TDTimeCounterState extends State with SingleTickerProvider } List _buildTimeWidget(BuildContext context) { - final format = widget.millisecond ? '${widget.format.replaceAll(RegExp(r':S+$'), '')}:SSS' : widget.format; + final format = widget.millisecond + ? '${widget.format.replaceAll(RegExp(r':S+$'), '')}:SSS' + : widget.format; final matches = _timeReg.allMatches(format); final timeMap = _getTimeMap(matches.map((e) => e.group(0) ?? '').toList()); return matches @@ -228,7 +234,9 @@ class _TDTimeCounterState extends State with SingleTickerProvider final timeType = match.group(0) ?? ''; return _buildTextWidget( timeMap[timeType] ?? '0', - widget.splitWithUnit ? timeUnitMap[timeType[0]] ?? '' : _getMark(format, timeType), + widget.splitWithUnit + ? timeUnitMap[timeType[0]] ?? '' + : _getMark(format, timeType), ); }) .expand((element) => element) diff --git a/tdesign-component/lib/src/components/time_counter/td_time_counter_style.dart b/tdesign-component/lib/src/components/time_counter/td_time_counter_style.dart index ceaedf08c..bc4155b5c 100644 --- a/tdesign-component/lib/src/components/time_counter/td_time_counter_style.dart +++ b/tdesign-component/lib/src/components/time_counter/td_time_counter_style.dart @@ -5,6 +5,7 @@ import '../../../tdesign_flutter.dart'; enum TDTimeCounterDirection { /// 倒计时 down, + /// 正向计时 up } @@ -113,7 +114,8 @@ class TDTimeCounterStyle { timeWidth = timeHeight = null; font = TDTheme.of(context).fontBodyMedium; timeFontSize = splitFontSize = font?.size ?? 14; - timeFontHeight = splitFontHeight = font?.height ?? (22 / timeFontSize!); + timeFontHeight = + splitFontHeight = font?.height ?? (22 / timeFontSize!); } else { timeWidth = timeHeight = 20; font = TDTheme.of(context).fontBodySmall; @@ -127,7 +129,8 @@ class TDTimeCounterStyle { timeWidth = timeHeight = null; font = TDTheme.of(context).fontBodyLarge; timeFontSize = splitFontSize = font?.size ?? 16; - timeFontHeight = splitFontHeight = font?.height ?? (24 / timeFontSize!); + timeFontHeight = + splitFontHeight = font?.height ?? (24 / timeFontSize!); } else { timeWidth = timeHeight = 24; font = TDTheme.of(context).fontBodyMedium; @@ -141,7 +144,8 @@ class TDTimeCounterStyle { timeWidth = timeHeight = null; font = TDTheme.of(context).fontBodyExtraLarge; timeFontSize = splitFontSize = font?.size ?? 18; - timeFontHeight = splitFontHeight = font?.height ?? (26 / timeFontSize!); + timeFontHeight = + splitFontHeight = font?.height ?? (26 / timeFontSize!); } else { timeWidth = timeHeight = 28; font = TDTheme.of(context).fontBodyLarge; @@ -155,29 +159,29 @@ class TDTimeCounterStyle { case TDTimeCounterTheme.round: timeBox = BoxDecoration( shape: BoxShape.circle, - color: TDTheme.of(context).errorColor6, + color: TDTheme.of(context).errorNormalColor, ); - timeColor = TDTheme.of(context).fontWhColor1; - splitColor = TDTheme.of(context).errorColor6; + timeColor = TDTheme.of(context).textColorAnti; + splitColor = TDTheme.of(context).errorNormalColor; break; case TDTimeCounterTheme.square: timeBox = BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(TDTheme.of(context).radiusSmall), - color: TDTheme.of(context).errorColor6, + color: TDTheme.of(context).errorNormalColor, ); - timeColor = TDTheme.of(context).fontWhColor1; - splitColor = TDTheme.of(context).errorColor6; + timeColor = TDTheme.of(context).textColorAnti; + splitColor = TDTheme.of(context).errorNormalColor; break; case TDTimeCounterTheme.defaultTheme: timeBox = null; - timeColor = splitColor = TDTheme.of(context).fontGyColor1; + timeColor = splitColor = TDTheme.of(context).textColorPrimary; timeWidth = null; timeHeight = null; } if (splitWithUnit ?? false) { - splitColor = TDTheme.of(context).fontGyColor1; + splitColor = TDTheme.of(context).textColorPrimary; } } } diff --git a/tdesign-component/lib/src/components/toast/td_toast.dart b/tdesign-component/lib/src/components/toast/td_toast.dart index 2832c5a2b..f638ed482 100644 --- a/tdesign-component/lib/src/components/toast/td_toast.dart +++ b/tdesign-component/lib/src/components/toast/td_toast.dart @@ -6,145 +6,173 @@ import '../../util/auto_size.dart'; import '../../util/context_extension.dart'; enum IconTextDirection { - horizontal, //横向 - vertical //竖向 + /// 横向 + horizontal, + + /// 竖向 + vertical } +/// todo 过于冗余,需精简封装 class TDToast { /// 普通文本Toast - static void showText(String? text, - {required BuildContext context, - Duration duration = TDToast._defaultDisPlayDuration, - int? maxLines, - BoxConstraints? constraints, - bool? preventTap, - Widget? customWidget, - Color? backgroundColor}) { + static void showText( + String? text, { + required BuildContext context, + Duration duration = TDToast._defaultDisPlayDuration, + int? maxLines, + BoxConstraints? constraints, + bool? preventTap, + Widget? customWidget, + Color? backgroundColor, + }) { _showOverlay( - _TDTextToast(text: text, maxLines: maxLines, constraints: constraints, customWidget: customWidget,), - context: context, - duration: duration, - preventTap: preventTap, - backgroundColor: backgroundColor); + _TDTextToast( + text: text, + maxLines: maxLines, + constraints: constraints, + customWidget: customWidget, + ), + context: context, + duration: duration, + preventTap: preventTap, + backgroundColor: backgroundColor, + ); } /// 带图标的Toast - static void showIconText(String? text, - {IconData? icon, - IconTextDirection direction = IconTextDirection.horizontal, - required BuildContext context, - Duration duration = TDToast._defaultDisPlayDuration, - bool? preventTap, - Color? backgroundColor, - int? maxLines}) { + static void showIconText( + String? text, { + IconData? icon, + IconTextDirection direction = IconTextDirection.horizontal, + required BuildContext context, + Duration duration = TDToast._defaultDisPlayDuration, + bool? preventTap, + Color? backgroundColor, + int? maxLines, + }) { _showOverlay( - _TDIconTextToast( - text: text, - iconData: icon, - iconTextDirection: direction, - maxLines: maxLines, - ), - context: context, - duration: duration, - preventTap: preventTap, - backgroundColor: backgroundColor); + _TDIconTextToast( + text: text, + iconData: icon, + iconTextDirection: direction, + maxLines: maxLines, + ), + context: context, + duration: duration, + preventTap: preventTap, + backgroundColor: backgroundColor, + ); } /// 成功提示Toast - static void showSuccess(String? text, - {IconTextDirection direction = IconTextDirection.horizontal, - required BuildContext context, - Duration duration = TDToast._defaultDisPlayDuration, - bool? preventTap, - Color? backgroundColor, - int? maxLines}) { + static void showSuccess( + String? text, { + IconTextDirection direction = IconTextDirection.horizontal, + required BuildContext context, + Duration duration = TDToast._defaultDisPlayDuration, + bool? preventTap, + Color? backgroundColor, + int? maxLines, + }) { _showOverlay( - _TDIconTextToast( - text: text, - iconData: TDIcons.check_circle, - iconTextDirection: direction, - maxLines: maxLines, - ), - context: context, - duration: duration, - preventTap: preventTap, - backgroundColor: backgroundColor); + _TDIconTextToast( + text: text, + iconData: TDIcons.check_circle, + iconTextDirection: direction, + maxLines: maxLines, + ), + context: context, + duration: duration, + preventTap: preventTap, + backgroundColor: backgroundColor, + ); } /// 警告Toast - static void showWarning(String? text, - {IconTextDirection direction = IconTextDirection.horizontal, - required BuildContext context, - Duration duration = TDToast._defaultDisPlayDuration, - bool? preventTap, - Color? backgroundColor, - int? maxLines}) { + static void showWarning( + String? text, { + IconTextDirection direction = IconTextDirection.horizontal, + required BuildContext context, + Duration duration = TDToast._defaultDisPlayDuration, + bool? preventTap, + Color? backgroundColor, + int? maxLines, + }) { _showOverlay( - _TDIconTextToast( - text: text, - iconData: TDIcons.error_circle, - iconTextDirection: direction, - maxLines: maxLines, - ), - context: context, - duration: duration, - preventTap: preventTap, - backgroundColor: backgroundColor); + _TDIconTextToast( + text: text, + iconData: TDIcons.error_circle, + iconTextDirection: direction, + maxLines: maxLines, + ), + context: context, + duration: duration, + preventTap: preventTap, + backgroundColor: backgroundColor, + ); } /// 失败提示Toast - static void showFail(String? text, - {IconTextDirection direction = IconTextDirection.horizontal, - required BuildContext context, - Duration duration = TDToast._defaultDisPlayDuration, - bool? preventTap, - Color? backgroundColor, - int? maxLines}) { + static void showFail( + String? text, { + IconTextDirection direction = IconTextDirection.horizontal, + required BuildContext context, + Duration duration = TDToast._defaultDisPlayDuration, + bool? preventTap, + Color? backgroundColor, + int? maxLines, + }) { _showOverlay( - _TDIconTextToast( - text: text, - iconData: TDIcons.close_circle, - iconTextDirection: direction, - maxLines: maxLines, - ), - context: context, - duration: duration, - preventTap: preventTap, - backgroundColor: backgroundColor); + _TDIconTextToast( + text: text, + iconData: TDIcons.close_circle, + iconTextDirection: direction, + maxLines: maxLines, + ), + context: context, + duration: duration, + preventTap: preventTap, + backgroundColor: backgroundColor, + ); } /// 带文案的加载Toast - static void showLoading( - {required BuildContext context, - String? text, - Duration duration = TDToast._infiniteDuration, - bool? preventTap, - Widget? customWidget, - Color? backgroundColor}) { + static void showLoading({ + required BuildContext context, + String? text, + Duration duration = TDToast._infiniteDuration, + bool? preventTap, + Widget? customWidget, + Color? backgroundColor, + }) { _showOverlay( - _TDToastLoading( - text: text, - customWidget: customWidget, - ), - context: context, - duration: duration, - preventTap: preventTap, - backgroundColor: backgroundColor); + _TDToastLoading( + text: text, + customWidget: customWidget, + ), + context: context, + duration: duration, + preventTap: preventTap, + backgroundColor: backgroundColor, + ); } /// 不带文案的加载Toast - static void showLoadingWithoutText( - {required BuildContext context, - String? text, - Duration duration = TDToast._infiniteDuration, - bool? preventTap, - Color? backgroundColor}) { + static void showLoadingWithoutText({ + required BuildContext context, + String? text, + Duration duration = TDToast._infiniteDuration, + bool? preventTap, + Color? backgroundColor, + }) { _showOverlay( - const _TDToastLoadingWithoutText(), - context: context, - duration: duration, - preventTap: preventTap, - backgroundColor: backgroundColor); + const _TDToastLoadingWithoutText(), + context: context, + duration: duration, + preventTap: preventTap, + backgroundColor: backgroundColor, + ); } /// 关闭加载Toast @@ -152,42 +180,49 @@ class TDToast { _cancel(); } - static void _showOverlay(Widget? widget, - {required BuildContext context, - Duration duration = TDToast._defaultDisPlayDuration, - bool? preventTap, - Color? backgroundColor}) { + static void _showOverlay( + Widget? widget, { + required BuildContext context, + Duration duration = TDToast._defaultDisPlayDuration, + bool? preventTap, + Color? backgroundColor, + }) { _cancel(); _showing = true; var overlayState = Overlay.of(context); _overlayEntry = OverlayEntry( - builder: (BuildContext context) => Center( - child: AnimatedOpacity( - opacity: _showing ? 1.0 : 0.0, - duration: _showing ? const Duration(milliseconds: 100) : const Duration(milliseconds: 200), - child: widget, - ), - )); + builder: (BuildContext context) => Center( + child: AnimatedOpacity( + opacity: _showing ? 1.0 : 0.0, + duration: _showing + ? const Duration(milliseconds: 100) + : const Duration(milliseconds: 200), + child: widget, + ), + ), + ); - if(preventTap ?? false) { + if (preventTap ?? false) { _overlayEntry = OverlayEntry( - builder: (BuildContext context) => Positioned( - top: 0, - right: 0, - bottom: 0, - left: 0, - child: Container( - color: backgroundColor, - child: Align( - alignment: Alignment.center, - child: AnimatedOpacity( - opacity: _showing ? 1.0 : 0.0, - duration: _showing ? const Duration(milliseconds: 100) : const Duration(milliseconds: 200), - child: widget, - ), + builder: (BuildContext context) => Positioned( + top: 0, + right: 0, + bottom: 0, + left: 0, + child: Container( + color: backgroundColor, + child: Align( + alignment: Alignment.center, + child: AnimatedOpacity( + opacity: _showing ? 1.0 : 0.0, + duration: _showing + ? const Duration(milliseconds: 100) + : const Duration(milliseconds: 200), + child: widget, ), ), ), + ), ); } if (_overlayEntry != null) { @@ -226,6 +261,9 @@ class TDToast { static Timer? _timer; static Timer? _disposeTimer; static const Duration _defaultDisPlayDuration = Duration(milliseconds: 3000); + + /// todo 魔鬼数字 + /// 建议:改为使用一个更明确的方式表示“永不自动关闭”,比如传入 null 表示永久显示。 static const Duration _infiniteDuration = Duration(seconds: 99999999); } @@ -235,7 +273,12 @@ class _TDIconTextToast extends StatelessWidget { final IconTextDirection iconTextDirection; final int? maxLines; - const _TDIconTextToast({this.text, this.iconData, this.iconTextDirection = IconTextDirection.horizontal, this.maxLines}); + const _TDIconTextToast({ + this.text, + this.iconData, + this.iconTextDirection = IconTextDirection.horizontal, + this.maxLines, + }); Widget buildHorizontalWidgets(BuildContext context) { return ConstrainedBox( @@ -244,7 +287,8 @@ class _TDIconTextToast extends StatelessWidget { padding: const EdgeInsets.fromLTRB(24, 14, 24, 14), decoration: BoxDecoration( color: TDTheme.of(context).fontGyColor1, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault), ), child: Row( mainAxisSize: MainAxisSize.min, @@ -255,9 +299,7 @@ class _TDIconTextToast extends StatelessWidget { size: 24, color: TDTheme.of(context).whiteColor1, ), - const SizedBox( - width: 8, - ), + const SizedBox(width: 8), TDText( text ?? '', font: TDTheme.of(context).fontBodyMedium, @@ -273,35 +315,37 @@ class _TDIconTextToast extends StatelessWidget { Widget buildVerticalWidgets(BuildContext context) { return ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 136), - child: Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: TDTheme.of(context).fontGyColor1, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + constraints: const BoxConstraints(maxWidth: 136), + child: Container( + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: TDTheme.of(context).fontGyColor1, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + // spacing: 8, + children: [ + Icon( + iconData, + size: 32, + color: TDTheme.of(context).whiteColor1, ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - iconData, - size: 32, - color: TDTheme.of(context).whiteColor1, - ), - const SizedBox( - height: 8, - ), - TDText( - text ?? '', - font: TDTheme.of(context).fontBodyMedium, - fontWeight: FontWeight.w400, - maxLines: maxLines ?? 1, - overflow: TextOverflow.ellipsis, - textColor: TDTheme.of(context).whiteColor1, - ) - ], - ))); + const SizedBox(height: 8), + TDText( + text ?? '', + font: TDTheme.of(context).fontBodyMedium, + fontWeight: FontWeight.w400, + maxLines: maxLines ?? 1, + overflow: TextOverflow.ellipsis, + textColor: TDTheme.of(context).whiteColor1, + ) + ], + ), + ), + ); } @override @@ -317,37 +361,42 @@ class _TDToastLoading extends StatelessWidget { final Widget? customWidget; - const _TDToastLoading({this.text, this.customWidget}); + const _TDToastLoading({ + this.text, + this.customWidget, + }); @override Widget build(BuildContext context) { return Container( height: 110, + width: 110, padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: TDTheme.of(context).fontGyColor1, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, + // spacing: 8, children: [ TDCircleIndicator( color: TDTheme.of(context).whiteColor1, - size: 26, + size: 32, lineWidth: 4, ), - const SizedBox( - height: 8, - ), - customWidget ?? TDText( - text ?? context.resource.loadingWithPoint, - font: TDTheme.of(context).fontBodyMedium, - fontWeight: FontWeight.w400, - maxLines: 1, - overflow: TextOverflow.ellipsis, - textColor: TDTheme.of(context).whiteColor1, - ) + const SizedBox(height: 8), + customWidget ?? + TDText( + text ?? context.resource.loadingWithPoint, + font: TDTheme.of(context).fontBodyMedium, + fontWeight: FontWeight.w400, + maxLines: 1, + overflow: TextOverflow.ellipsis, + textColor: TDTheme.of(context).whiteColor1, + ) ], )); } @@ -359,18 +408,19 @@ class _TDToastLoadingWithoutText extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - width: 80, - height: 80, - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: TDTheme.of(context).fontGyColor1, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), - ), - child: TDCircleIndicator( - color: TDTheme.of(context).whiteColor1, - size: 26, - lineWidth: 4, - )); + width: 80, + height: 80, + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: TDTheme.of(context).fontGyColor1, + borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), + ), + child: TDCircleIndicator( + color: TDTheme.of(context).whiteColor1, + size: 32, + lineWidth: 4, + ), + ); } } @@ -383,26 +433,34 @@ class _TDTextToast extends StatelessWidget { final Widget? customWidget; - const _TDTextToast({this.text, this.maxLines, this.constraints, this.customWidget}); + const _TDTextToast({ + this.text, + this.maxLines, + this.constraints, + this.customWidget, + }); @override Widget build(BuildContext context) { return ConstrainedBox( constraints: constraints ?? BoxConstraints(maxWidth: 191.scale), child: Container( - padding: const EdgeInsets.fromLTRB(24, 16, 24, 16), - decoration: BoxDecoration( - color: TDTheme.of(context).fontGyColor1, - borderRadius: BorderRadius.circular(TDTheme.of(context).radiusDefault), - ), - child: customWidget ?? TDText( - text ?? '', - font: TDTheme.of(context).fontBodyMedium, - fontWeight: FontWeight.w400, - maxLines: maxLines ?? 3, - overflow: TextOverflow.ellipsis, - textColor: TDTheme.of(context).whiteColor1, - )), + padding: const EdgeInsets.fromLTRB(24, 16, 24, 16), + decoration: BoxDecoration( + color: TDTheme.of(context).fontGyColor1, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault), + ), + child: customWidget ?? + TDText( + text ?? '', + font: TDTheme.of(context).fontBodyMedium, + fontWeight: FontWeight.w400, + maxLines: maxLines ?? 3, + overflow: TextOverflow.ellipsis, + textColor: TDTheme.of(context).whiteColor1, + ), + ), ); } } diff --git a/tdesign-component/lib/src/components/tree/td_tree_select.dart b/tdesign-component/lib/src/components/tree/td_tree_select.dart index 2052cf960..88f478a59 100644 --- a/tdesign-component/lib/src/components/tree/td_tree_select.dart +++ b/tdesign-component/lib/src/components/tree/td_tree_select.dart @@ -7,8 +7,14 @@ import '../../../tdesign_flutter.dart'; typedef TDTreeSelectChangeEvent = void Function(List, int level); class TDSelectOption { - TDSelectOption( - {required this.label, required this.value, this.children = const [], this.multiple = false,this.maxLines = 1,this.columnWidth,}); + TDSelectOption({ + required this.label, + required this.value, + this.children = const [], + this.multiple = false, + this.maxLines = 1, + this.columnWidth, + }) : assert(maxLines > 0, 'maxLines must be greater than 0'); /// 标签 final String label; @@ -35,15 +41,15 @@ enum TDTreeSelectStyle { } class TDTreeSelect extends StatefulWidget { - const TDTreeSelect( - {Key? key, - this.options = const [], - this.defaultValue = const [], - this.onChange, - this.multiple = false, - this.style = TDTreeSelectStyle.normal, - this.height = 336}) - : super(key: key); + const TDTreeSelect({ + Key? key, + this.options = const [], + this.defaultValue = const [], + this.onChange, + this.multiple = false, + this.style = TDTreeSelectStyle.normal, + this.height = 336, + }) : super(key: key); /// 展示的选项列表 final List options; @@ -72,24 +78,30 @@ class _TDTreeSelectState extends State { ScrollController controller3 = ScrollController(); List values = []; + int get currentLevel => values.length + 1; + int? get firstValue => values.isNotEmpty ? values[0] : null; + dynamic get secondValue => values.length >= 2 ? values[1] : null; + dynamic get thirdValue => values.length >= 3 ? values[2] : null; List get firstOptions => widget.options; + List get secondOptions => maxLevel() <= 1 || values.isEmpty ? [] : firstOptions - .firstWhere((opt) => opt.value == firstValue, - orElse: () => TDSelectOption(value: -1, label: '', children: [])) - .children; + .firstWhere((opt) => opt.value == firstValue, + orElse: () => TDSelectOption(value: -1, label: '', children: [])) + .children; + List get thirdOptions => maxLevel() <= 2 || currentLevel < 3 ? [] : secondOptions - .firstWhere((opt) => opt.value == secondValue, - orElse: () => TDSelectOption(value: -1, label: '', children: [])) - .children; + .firstWhere((opt) => opt.value == secondValue, + orElse: () => TDSelectOption(value: -1, label: '', children: [])) + .children; @override void initState() { @@ -98,10 +110,18 @@ class _TDTreeSelectState extends State { values = List.from(widget.defaultValue); if (values.isEmpty && widget.options.isNotEmpty) { final option = widget.options[0]; - values.add((widget.multiple || option.multiple) ? [option.value] : option.value); + values.add( + (widget.multiple || option.multiple) ? [option.value] : option.value); } } + @override + void dispose() { + controller2.dispose(); + controller3.dispose(); + super.dispose(); + } + int maxLevel() { if (widget.options.isEmpty) { return 1; @@ -122,106 +142,116 @@ class _TDTreeSelectState extends State { @override Widget build(BuildContext context) { - return Row( - children: [ - Container( - width: _getLevelWidth(widget.options, 1) ?? 106, - height: widget.height, - decoration: BoxDecoration( - color: widget.style == TDTreeSelectStyle.outline - ? Colors.white - : const Color(0xFFF6F6F6), - border: widget.style == TDTreeSelectStyle.outline - ? Border(right: BorderSide(color: Colors.grey.shade200)) - : null, - ), - child: ListView.builder( - itemCount: widget.options.length, - itemBuilder: (context, index) { - final option = widget.options[index]; - final isSelected = firstValue == option.value; - - return GestureDetector( - onTap: () { - setState(() { - if (values.isEmpty) { - values.add(option.value); - } else { - values = [option.value]; - if (controller2.hasClients) controller2.jumpTo(0); - } - widget.onChange?.call(values, 1); - }); - }, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - decoration: BoxDecoration( - color: isSelected ? Colors.white : null, - border: isSelected && widget.style == TDTreeSelectStyle.outline - ? Border( - left: BorderSide( - color: TDTheme.of(context).brandNormalColor, - width: 3, + return Container( + color: TDTheme.of(context).bgColorContainer, + height: widget.height, + child: Row( + children: [ + /// 一级菜单 + Container( + width: _getLevelWidth(widget.options, 1) ?? 106, + color: TDTheme.of(context).bgColorSecondaryContainer, + child: ListView.builder( + itemCount: widget.options.length, + itemBuilder: (context, index) { + final option = widget.options[index]; + final isSelected = firstValue == option.value; + + return GestureDetector( + onTap: () { + // todo 点击一级菜单时直接重置整个 values 数组可能导致二级或三级选择的数据丢失 + setState(() { + if (values.isEmpty) { + values.add(option.value); + } else { + values = [option.value]; + if (controller2.hasClients) { + controller2.jumpTo(0); + } + } + widget.onChange?.call(values, 1); + }); + }, + child: Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isSelected + ? TDTheme.of(context).bgColorContainer + : null, + border: isSelected && + widget.style == TDTreeSelectStyle.outline + ? Border( + left: BorderSide( + color: TDTheme.of(context).brandNormalColor, + width: 3, + ), + ) + : null, + + /// todo 上下 borderRadius + borderRadius: BorderRadius.only( + + /// 选中的上一个 + /*topRight: Radius.circular( + topAdjacent ? TDTheme.of(context).radiusLarge : 0),*/ + + /// 选中的下一个 + /* bottomRight: Radius.circular( + bottomAdjacent ? TDTheme.of(context).radiusLarge : 0),*/ + ), + ), + child: Text( + option.label, + maxLines: option.maxLines, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: + TDTheme.of(context).fontBodyLarge?.size ?? 16, + color: isSelected + ? TDTheme.of(context).brandNormalColor + : TDTheme.of(context).textColorPrimary, + fontWeight: + isSelected ? FontWeight.w600 : FontWeight.normal, + ), ), - ) - : null, - ), - child: Text( - option.label, - maxLines: option.maxLines, - overflow: option.maxLines == 1 - ? TextOverflow.ellipsis - : TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - color: isSelected - ? TDTheme.of(context).brandNormalColor - : const Color(0xFF333333), - fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), - ), - ), - ); - }, - ), - ), - Expanded( - child: Container( - height: widget.height, - decoration: const BoxDecoration(color: Colors.white), - child: _buildRightParts(context), - ), - ), - ], - ); + ); + }, + ), + ), + + /// 右侧 二、三级菜单 + Expanded(child: _buildRightParts(context)) + ], + )); } Widget _buildRightParts(BuildContext context) { // 判断是否应该显示三级菜单 final showThirdLevel = values.length >= 2 && - secondOptions.any((opt) => opt.value == secondValue && opt.children.isNotEmpty); + secondOptions + .any((opt) => opt.value == secondValue && opt.children.isNotEmpty); return Row( children: [ showThirdLevel ? SizedBox( - width: _getLevelWidth(secondOptions, 2) ?? 103, - child: _buildNextColumn(context, level: 2, lastColumn: false), - ) + width: _getLevelWidth(secondOptions, 2) ?? 103, + child: _buildNextColumn(context, level: 2, lastColumn: false), + ) : Expanded( - child: _buildNextColumn(context, level: 2), - ), - + child: _buildNextColumn(context, level: 2), + ), if (showThirdLevel) - // 三级菜单 + // 三级菜单 _getLevelWidth(thirdOptions, 3) != null ? SizedBox( - width: _getLevelWidth(thirdOptions, 3), - child: _buildNextColumn(context, level: 3), - ) + width: _getLevelWidth(thirdOptions, 3), + child: _buildNextColumn(context, level: 3), + ) : Expanded( - child: _buildNextColumn(context, level: 3), - ), + child: _buildNextColumn(context, level: 3), + ), ], ); } @@ -235,7 +265,8 @@ class _TDTreeSelectState extends State { return null; } - Widget _buildNextColumn(BuildContext context, {int level = 2, bool lastColumn = true}) { + Widget _buildNextColumn(BuildContext context, + {int level = 2, bool lastColumn = true}) { var displayOptions = level == 2 ? secondOptions : thirdOptions; return LayoutBuilder( @@ -249,7 +280,9 @@ class _TDTreeSelectState extends State { itemCount: displayOptions.length, itemBuilder: (BuildContext ctx, int index) { var currentValue = displayOptions[index].value; - final isMultiple = widget.multiple ? widget.multiple : displayOptions[index].multiple; + final isMultiple = widget.multiple + ? widget.multiple + : displayOptions[index].multiple; final maxLines = displayOptions[index].maxLines; var selected = false; if (isMultiple) { @@ -267,7 +300,8 @@ class _TDTreeSelectState extends State { : false; } } else { - selected = (level == 2 ? secondValue : thirdValue) == currentValue; + selected = + (level == 2 ? secondValue : thirdValue) == currentValue; } return Container( @@ -278,15 +312,18 @@ class _TDTreeSelectState extends State { child: GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { + /// todo 逻辑过于冗余,待优化 setState(() { if (level == 2) { switch (values.length) { case 1: - values.add(isMultiple ? [currentValue] : currentValue); + values.add( + isMultiple ? [currentValue] : currentValue); break; case 2: if (isMultiple) { - var hasContains = (values[1] as List).contains(currentValue); + var hasContains = (values[1] as List) + .contains(currentValue); if (hasContains) { (values[1] as List).remove(currentValue); } else { @@ -295,22 +332,28 @@ class _TDTreeSelectState extends State { } else { values[1] = currentValue; } - if (controller3.hasClients) controller3.jumpTo(0); + if (controller3.hasClients) { + controller3.jumpTo(0); + } break; default: values[1] = currentValue; values.removeLast(); - if (controller3.hasClients) controller3.jumpTo(0); + if (controller3.hasClients) { + controller3.jumpTo(0); + } } } else { switch (values.length) { case 1: case 2: - values.add(isMultiple ? [currentValue] : currentValue); + values.add( + isMultiple ? [currentValue] : currentValue); break; default: if (isMultiple) { - var hasContains = (values[2] as List).contains(currentValue); + var hasContains = (values[2] as List) + .contains(currentValue); if (hasContains) { (values[2] as List).remove(currentValue); } else { @@ -333,18 +376,17 @@ class _TDTreeSelectState extends State { children: [ Flexible( child: Padding( - padding: const EdgeInsets.only(top: 16, left: 16, bottom: 16), + padding: const EdgeInsets.only( + top: 16, left: 16, bottom: 16), child: Text( displayOptions[index].label, maxLines: maxLines, - overflow: maxLines == 1 - ? TextOverflow.ellipsis - : TextOverflow.ellipsis, + overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 16, color: (!lastColumn && selected) ? TDTheme.of(context).brandNormalColor - : const Color.fromRGBO(0, 0, 0, 0.9), + : TDTheme.of(context).textColorPrimary, fontWeight: (!lastColumn && selected) ? FontWeight.w600 : FontWeight.w400, @@ -377,5 +419,4 @@ class _TDTreeSelectState extends State { }, ); } - -} \ No newline at end of file +} diff --git a/tdesign-component/lib/src/components/upload/td_upload.dart b/tdesign-component/lib/src/components/upload/td_upload.dart index 29b8665f0..38c957ebd 100644 --- a/tdesign-component/lib/src/components/upload/td_upload.dart +++ b/tdesign-component/lib/src/components/upload/td_upload.dart @@ -61,33 +61,33 @@ class TDUploadFile { typedef TDUploadErrorEvent = void Function(Object e); typedef TDUploadClickEvent = void Function(int value); -typedef TDUploadValueChangedEvent = void Function(List files, TDUploadType type); +typedef TDUploadValueChangedEvent = void Function( + List files, TDUploadType type); typedef TDUploadValidatorEvent = void Function(TDUploadValidatorError e); class TDUpload extends StatefulWidget { - const TDUpload( - {Key? key, - this.max = 0, - this.mediaType = const [TDUploadMediaType.image, TDUploadMediaType.video], - this.sizeLimit, - this.onCancel, - this.onError, - this.onValidate, - this.onClick, - this.onMaxLimitReached, - required this.files, - this.onChange, - this.multiple = false, - this.width = 80.0, - this.height = 80.0, - this.type = TDUploadBoxType.roundedSquare, - this.disabled = false, - this.enabledReplaceType = false, - this.wrapSpacing, - this.wrapRunSpacing, - this.wrapAlignment, - }) - : super(key: key); + const TDUpload({ + Key? key, + this.max = 0, + this.mediaType = const [TDUploadMediaType.image, TDUploadMediaType.video], + this.sizeLimit, + this.onCancel, + this.onError, + this.onValidate, + this.onClick, + this.onMaxLimitReached, + required this.files, + this.onChange, + this.multiple = false, + this.width = 80.0, + this.height = 80.0, + this.type = TDUploadBoxType.roundedSquare, + this.disabled = false, + this.enabledReplaceType = false, + this.wrapSpacing, + this.wrapRunSpacing, + this.wrapAlignment, + }) : super(key: key); /// 控制展示的文件列表 final List files; @@ -153,7 +153,9 @@ class TDUpload extends StatefulWidget { class _TDUploadState extends State { List fileList = []; - bool get canUpload => widget.multiple ? (widget.max == 0 ? true : fileList.length < widget.max) : fileList.isEmpty; + bool get canUpload => widget.multiple + ? (widget.max == 0 ? true : fileList.length < widget.max) + : fileList.isEmpty; final ImagePicker _picker = ImagePicker(); // 类型映射 @@ -178,7 +180,7 @@ class _TDUploadState extends State { } else if (widget.onValidate != null) { widget.onValidate!(TDUploadValidatorError.overQuantity); } else { - throw Exception("Initial file count exceeds the maximum limit"); + throw Exception('Initial file count exceeds the maximum limit'); } } } @@ -205,7 +207,9 @@ class _TDUploadState extends State { } } - if (widget.max > 0 && isMultiple && fileList.length + medias.length > widget.max) { + if (widget.max > 0 && + isMultiple && + fileList.length + medias.length > widget.max) { if (widget.onMaxLimitReached != null) { widget.onMaxLimitReached!(); } else if (widget.onValidate != null) { @@ -241,11 +245,15 @@ class _TDUploadState extends State { return; } - var originMaxKeys = fileList.isEmpty ? 0 : fileList.map((file) => file.key).reduce(max); + var originMaxKeys = + fileList.isEmpty ? 0 : fileList.map((file) => file.key).reduce(max); var newFiles = []; for (var i = 0; i < files.length; i++) { - newFiles.add(TDUploadFile(key: originMaxKeys + i + 1, file: File(files[i].path), assetPath: files[i].path)); + newFiles.add(TDUploadFile( + key: originMaxKeys + i + 1, + file: File(files[i].path), + assetPath: files[i].path)); } if (widget.onChange != null) { @@ -268,7 +276,8 @@ class _TDUploadState extends State { return; } - var newFile = TDUploadFile(key: oldFile.key, file: File(files[0].path), assetPath: files[0].path); + var newFile = TDUploadFile( + key: oldFile.key, file: File(files[0].path), assetPath: files[0].path); if (widget.onChange != null) { widget.onChange!([newFile], TDUploadType.replace); @@ -276,7 +285,8 @@ class _TDUploadState extends State { } // 校验资源 - Future validateResources(List files, [bool? multiple]) async { + Future validateResources(List files, + [bool? multiple]) async { TDUploadValidatorError? error; // 多选逻辑,优选从参数获取 @@ -337,7 +347,8 @@ class _TDUploadState extends State { ); } - Widget _buildUploadBox(BuildContext context, {void Function()? onTap, bool shouldDisplay = true}) { + Widget _buildUploadBox(BuildContext context, + {void Function()? onTap, bool shouldDisplay = true}) { return Visibility( visible: shouldDisplay, child: GestureDetector( @@ -348,13 +359,16 @@ class _TDUploadState extends State { decoration: widget.type == TDUploadBoxType.circle ? BoxDecoration( shape: BoxShape.circle, - color: TDTheme.of(context).grayColor1, + color: TDTheme.of(context).bgColorSecondaryContainer, ) - : BoxDecoration(color: TDTheme.of(context).grayColor1, borderRadius: BorderRadius.circular(6)), - child: const Center( + : BoxDecoration( + color: TDTheme.of(context).bgColorSecondaryContainer, + borderRadius: BorderRadius.circular( + TDTheme.of(context).radiusDefault)), + child: Center( child: Icon( TDIcons.add, - color: Color.fromRGBO(0, 0, 0, 0.4), + color: TDTheme.of(context).textColorPlaceholder, size: 28, )), ))); @@ -383,7 +397,9 @@ class _TDUploadState extends State { assetUrl: file.file == null ? file.assetPath : null, type: _imageTypeMap[widget.type] ?? TDImageType.roundedSquare, ), - Visibility(visible: file.status != TDUploadFileStatus.success, child: _buildShadowBox(file)), + Visibility( + visible: file.status != TDUploadFileStatus.success, + child: _buildShadowBox(context, file)), Visibility( visible: file.canDelete, child: Positioned( @@ -397,14 +413,17 @@ class _TDUploadState extends State { width: 20, height: 20, decoration: widget.type == TDUploadBoxType.circle - ? const BoxDecoration( + ? BoxDecoration( shape: BoxShape.circle, - color: Color.fromRGBO(0, 0, 0, 0.6), + color: TDTheme.of(context).textColorDisabled, ) - : const BoxDecoration( - color: Color.fromRGBO(0, 0, 0, 0.6), - borderRadius: - BorderRadius.only(bottomLeft: Radius.circular(6), topRight: Radius.circular(6))), + : BoxDecoration( + color: TDTheme.of(context).textColorDisabled, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular( + TDTheme.of(context).radiusDefault), + topRight: Radius.circular( + TDTheme.of(context).radiusDefault))), child: const Center( child: Icon( TDIcons.close, @@ -418,11 +437,12 @@ class _TDUploadState extends State { ); } - Widget _buildShadowBox(TDUploadFile file) { + Widget _buildShadowBox(BuildContext context, TDUploadFile file) { var displayText = ''; switch (file.status) { case TDUploadFileStatus.loading: - displayText = file.progress != null ? '${file.progress!}%' : file.loadingText; + displayText = + file.progress != null ? '${file.progress!}%' : file.loadingText; break; case TDUploadFileStatus.retry: displayText = file.retryText; @@ -437,11 +457,14 @@ class _TDUploadState extends State { width: widget.width, height: widget.height, decoration: widget.type == TDUploadBoxType.circle - ? const BoxDecoration( + ? BoxDecoration( shape: BoxShape.circle, - color: Color.fromRGBO(0, 0, 0, 0.4), + color: TDTheme.of(context).fontGyColor3, ) - : BoxDecoration(color: const Color.fromRGBO(0, 0, 0, 0.4), borderRadius: BorderRadius.circular(6)), + : BoxDecoration( + color: TDTheme.of(context).fontGyColor3, + borderRadius: + BorderRadius.circular(TDTheme.of(context).radiusDefault)), child: Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: Center( @@ -457,9 +480,12 @@ class _TDUploadState extends State { ), ), Visibility( - visible: file.status == TDUploadFileStatus.retry || file.status == TDUploadFileStatus.error, + visible: file.status == TDUploadFileStatus.retry || + file.status == TDUploadFileStatus.error, child: Icon( - file.status == TDUploadFileStatus.retry ? TDIcons.refresh : TDIcons.close_circle, + file.status == TDUploadFileStatus.retry + ? TDIcons.refresh + : TDIcons.close_circle, size: 24, color: Colors.white, )), diff --git a/tdesign-component/lib/src/theme/resource_delegate.dart b/tdesign-component/lib/src/theme/resource_delegate.dart index 018820f37..fa43c9ef0 100644 --- a/tdesign-component/lib/src/theme/resource_delegate.dart +++ b/tdesign-component/lib/src/theme/resource_delegate.dart @@ -1,8 +1,10 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter/widgets.dart'; import '../../tdesign_flutter.dart'; -typedef TDTDResourceBuilder = TDResourceDelegate? Function(BuildContext context); +typedef TDTDResourceBuilder = TDResourceDelegate? Function( + BuildContext context, +); /// 资源管理器 class TDResourceManager { @@ -20,7 +22,7 @@ class TDResourceManager { return _defaultDelegate; } if (_needAlwaysBuild) { - // 每次都调用,适用于全局有多个TDResourceDelegate的情况 + // 每次都调用,适用于全局有多个TDResourceDelegate的情况 var delegate = _builder?.call(context); if (delegate != null) { return delegate; @@ -48,7 +50,7 @@ class TDResourceManager { } } -/// 资源管理器,允许外部重写,设计成抽象类,防止有新增字段时,用户没有感知 +/// 资源管理器,允许外部重写,设计成抽象类,防止有新增字段时,用户没有感知 abstract class TDResourceDelegate { /// [TDSwitch]的打开状态文案 String get open; @@ -118,7 +120,7 @@ abstract class TDResourceDelegate { /// [TDDatePicker] 周 String get weeksLabel; - + /// [TDCalendarHeader] 星期日 String get sunday; @@ -200,9 +202,12 @@ abstract class TDResourceDelegate { /// [TDBackTop] 顶部 String get top; + /// [TDTable] 空数据 + String get emptyData; } -/// 如果用户要重写,就应该全部重写,不开放只重新部分资源 +/// 如果用户要重写,就应该全部重写,不开放只重新部分资源 +/// todo 这里默认为中文,推荐使用 Material 本地化作为备用,如 MaterialLocalizations.of(context).cancelButtonLabel class _DefaultResourceDelegate extends TDResourceDelegate { @override String get open => '开'; @@ -268,11 +273,12 @@ class _DefaultResourceDelegate extends TDResourceDelegate { String get monthLabel => '月'; @override - String get dateLabel=>'日'; + String get dateLabel => '日'; + + @override + String get weeksLabel => '周'; @override - String get weeksLabel=>'周'; - String get sunday => '日'; @override @@ -352,4 +358,7 @@ class _DefaultResourceDelegate extends TDResourceDelegate { @override String get top => '顶部'; + + @override + String get emptyData => '暂无数据'; } diff --git a/tdesign-component/lib/src/theme/td_colors.dart b/tdesign-component/lib/src/theme/td_colors.dart index 2cfccd8f6..2aee87fe3 100644 --- a/tdesign-component/lib/src/theme/td_colors.dart +++ b/tdesign-component/lib/src/theme/td_colors.dart @@ -142,8 +142,7 @@ extension TDColors on TDThemeData { Color get warningColor9 => colorMap['warningColor9'] ?? const Color(0xFF532300); ///#3B1700 - Color get warningColor10 => - colorMap['warningColor10'] ?? const Color(0xFF3B1700); + Color get warningColor10 => colorMap['warningColor10'] ?? const Color(0xFF3B1700); ///#FFF1E9 Color get warningLightColor => colorMap['warningLightColor'] ?? warningColor1; @@ -152,8 +151,7 @@ extension TDColors on TDThemeData { Color get warningFocusColor => colorMap['warningFocusColor'] ?? warningColor2; ///#FFB98C - Color get warningDisabledColor => - colorMap['warningDisabledColor'] ?? warningColor3; + Color get warningDisabledColor => colorMap['warningDisabledColor'] ?? warningColor3; ///#FA9550 Color get warningHoverColor => colorMap['warningHoverColor'] ?? warningColor4; @@ -194,8 +192,7 @@ extension TDColors on TDThemeData { Color get successColor9 => colorMap['successColor9'] ?? const Color(0xFF003B23); ///#002515 - Color get successColor10 => - colorMap['successColor10'] ?? const Color(0xFF002515); + Color get successColor10 => colorMap['successColor10'] ?? const Color(0xFF002515); ///#E3F9E9 Color get successLightColor => colorMap['successLightColor'] ?? successColor1; @@ -204,8 +201,7 @@ extension TDColors on TDThemeData { Color get successFocusColor => colorMap['successFocusColor'] ?? successColor2; ///#92DAB2 - Color get successDisabledColor => - colorMap['successDisabledColor'] ?? successColor3; + Color get successDisabledColor => colorMap['successDisabledColor'] ?? successColor3; ///#56C08D Color get successHoverColor => colorMap['successHoverColor'] ?? successColor4; @@ -230,16 +226,16 @@ extension TDColors on TDThemeData { ///#42000000 Color get fontGyColor4 => colorMap['fontGyColor4'] ?? const Color(0x42000000); - ///#ff000000 + ///#FFFFFFFF Color get fontWhColor1 => colorMap['fontWhColor1'] ?? const Color(0xFFFFFFFF); - ///#8c000000 + ///#8CFFFFFF Color get fontWhColor2 => colorMap['fontWhColor2'] ?? const Color(0x8CFFFFFF); - ///#59000000 + ///#59FFFFFF Color get fontWhColor3 => colorMap['fontWhColor3'] ?? const Color(0x59FFFFFF); - ///#38000000 + ///#38FFFFFF Color get fontWhColor4 => colorMap['fontWhColor4'] ?? const Color(0x38FFFFFF); /// 中性面板色组---------------------------------------------------- @@ -288,4 +284,52 @@ extension TDColors on TDThemeData { ///#181818 Color get grayColor14 => colorMap['grayColor14'] ?? const Color(0xFF181818); + + /// 组件颜色配置---------------------------------------------------- + + Color get bgColorPage => colorMap['bgColorPage'] ?? grayColor2; + + Color get bgColorContainer => colorMap['bgColorContainer'] ?? whiteColor1; + + Color get bgColorContainerSelect => colorMap['bgColorContainerSelect'] ?? whiteColor1; + + Color get bgColorContainerHover => colorMap['bgColorContainerHover'] ?? grayColor1; + + Color get bgColorContainerActive => colorMap['bgColorContainerActive'] ?? grayColor3; + + Color get bgColorSecondaryContainer => colorMap['bgColorSecondaryContainer'] ?? grayColor1; + + Color get bgColorSecondaryContainerHover => + colorMap['bgColorSecondaryContainerHover'] ?? grayColor2; + + Color get bgColorSecondaryContainerActive => + colorMap['bgColorSecondaryContainerActive'] ?? grayColor4; + + Color get bgColorComponent => colorMap['bgColorComponent'] ?? grayColor3; + + Color get bgColorComponentHover => colorMap['bgColorComponentHover'] ?? grayColor4; + + Color get bgColorComponentActive => colorMap['bgColorComponentActive'] ?? grayColor6; + + Color get bgColorComponentDisabled => colorMap['bgColorComponentDisabled'] ?? grayColor2; + + Color get componentStrokeColor => colorMap['componentStrokeColor'] ?? grayColor3; + + Color get componentBorderColor => colorMap['componentBorderColor'] ?? grayColor4; + + /// 文字颜色配置---------------------------------------------------- + + Color get textColorPrimary => colorMap['textColorPrimary'] ?? fontGyColor1; + + Color get textColorSecondary => colorMap['textColorSecondary'] ?? fontGyColor2; + + Color get textColorPlaceholder => colorMap['textColorPlaceholder'] ?? fontGyColor3; + + Color get textColorDisabled => colorMap['textColorDisabled'] ?? fontGyColor4; + + Color get textColorAnti => colorMap['textColorAnti'] ?? whiteColor1; + + Color get textColorBrand => colorMap['textColorBrand'] ?? brandNormalColor; + + Color get textColorLink => colorMap['textColorLink'] ?? brandNormalColor; } diff --git a/tdesign-component/lib/src/util/string_util.dart b/tdesign-component/lib/src/util/string_util.dart index 8e548825a..29dc437be 100644 --- a/tdesign-component/lib/src/util/string_util.dart +++ b/tdesign-component/lib/src/util/string_util.dart @@ -5,17 +5,28 @@ import 'log.dart'; Color? toColor(String colorStr, {double alpha = 1}) { try { var hexColor = colorStr.toUpperCase().replaceAll('#', ''); - if (hexColor.length == 6) { - if (alpha < 0) { - alpha = 0; - } else if (alpha > 1) { - alpha = 1; - } - var alphaInt = (0xFF * alpha).toInt(); - var alphaString = alphaInt.toRadixString(16); - hexColor = '$alphaString$hexColor'; + if (hexColor.length == 3) { + /// 处理3位HEX颜色值,扩展为6位 + /// hexColor = hexColor.split('').map((s) => s * 2).join(''); + /// 优化:使用字符串插值替代split/map/join操作,提高性能和可读性 + hexColor = + '${hexColor[0]}${hexColor[0]}${hexColor[1]}${hexColor[1]}${hexColor[2]}${hexColor[2]}'; + } + + if (hexColor.length == 6) { + if (alpha < 0) { + alpha = 0; + } else if (alpha > 1) { + alpha = 1; } + var alphaInt = (0xFF * alpha).toInt(); + var alphaString = alphaInt.toRadixString(16); + + /// 扩展为8位的AHEX + hexColor = '$alphaString$hexColor'; + } + return Color(int.parse(hexColor, radix: 16)); } catch (e) { // Log.w('toColor', 'error: $e'); diff --git a/tdesign-site/site/plugin-tdoc/component.vue b/tdesign-site/site/plugin-tdoc/component.vue index 4c4ab3d64..044cfc0db 100644 --- a/tdesign-site/site/plugin-tdoc/component.vue +++ b/tdesign-site/site/plugin-tdoc/component.vue @@ -11,7 +11,7 @@ frameborder="0" width="100%" height="100%" - style="box-sizing: border-box; border-radius: 0 0 6px 6px; overflow: hidden; border-top: 8px solid #f8f8f8" + style="box-sizing: border-box; border-radius: 0 0 6px 6px; overflow: hidden;" >
注:web示例仅供参考,预览实际效果请阅读快速开始