【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所 原创

卓伊凡
发布于 2025-4-1 02:00
浏览
0收藏

【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所有设置setting相关的页面-优雅草卓伊凡

项目背景

本项目渊源已久,优雅草2025年发布,PC端已经发布,将在4月完成成品发布,目前由于考虑到鸿蒙端用户使用,毕竟新一代纯血鸿蒙harmonyos next已经不再支持安卓android,因此优雅草团队必须考虑把鸿蒙端也开发上,以下实战过程完整记录了整个开发过程,优雅草卓伊凡审核代码,记录并更新,再次感谢优雅草团队所有同事们的努力,鸿蒙端为了加速鸿蒙生态已经开源地址供查看,关于优雅草星云物联网AI智控系统可以关注优雅草官网,在本文梳理的过程中发现在后面的页面中,只需要直接写出代码并且附上注释,卓伊凡相信大家应该看得懂,针对比较复杂的部分会单独做独立解释,每一个页面都可以对应查看,基本都会截图,如果没有截图的那就是真的没截图

项目开源代码地址

https://gitee.com/youyacao/axharmonyos

【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所-鸿蒙开发者社区

鸿蒙端运行环境

deveco 5.0.4版本

实战过程

接下来完成所有的设置相关页面,src/main/ets/components/settings/SettingInputWidget.ets

import { commonColor } from "@wcmzllx/common-const-library"
import { vp2 } from "../../common/NewVp"

// 定义一个设置输入小部件组件
@ComponentV2
export struct SettingInputWidget {
    // 输入框标题,默认值为"系统语言"
    @Param title: string = "系统语言"
    // 是否为必填项,默认值为true
    @Param isMust: boolean = true
    // 输入框占位符,默认为空字符串
    @Param placeholder: string = ""
    // 当输入内容变化时触发的事件
    @Event onContentChange: (value: string) => void;
    // 是否为文本域,默认为false
    @Param isTextArea: boolean = false;
    // 文本域控制器
    controller: TextAreaController = new TextAreaController()

    // 构建组件界面
    build() {
        // 创建一个行容器,用于布局标题和输入框
        Row({ space: vp2.vp2(5) }) {
            // 创建标题文本
            Text(undefined) {
                // 如果是必填项,显示红色星号
                if (this.isMust) {
                    Span("*").fontColor("#FFFD0808")
                }
                // 显示标题文本
                Span(this.title + ":")
                    .fontColor(commonColor.FONT_3333_COLOR)
            }
            .fontSize(vp2.vp2(14))
            .fontWeight(FontWeight.Regular)
            .lineHeight(vp2.vp2(16.41))

            // 创建一个行容器,用于布局输入框
            Row() {
                // 根据isTextArea参数决定使用TextArea还是TextInput
                if (this.isTextArea){
                    TextArea({
                        placeholder: this.placeholder,
                        controller: this.controller
                    })
                        .backgroundColor(Color.Transparent)
                        .placeholderColor(commonColor.FONT_9999_COLOR)
                        .placeholderFont({ size: vp2.vp2(14) })
                        .margin(0)
                        .padding(0)
                        .borderRadius(0)
                        .height(vp2.vp2(160))
                        .fontSize(vp2.vp2(14))
                        .fontWeight(FontWeight.Regular)
                        .lineHeight(vp2.vp2(16.41))
                }else {
                    TextInput({ placeholder: this.placeholder })
                        .backgroundColor(Color.Transparent)
                        .placeholderColor(commonColor.FONT_9999_COLOR)
                        .placeholderFont({ size: vp2.vp2(14) })
                        .margin(0)
                        .padding(0)
                        .borderRadius(0)
                        .fontSize(vp2.vp2(14))
                        .fontWeight(FontWeight.Regular)
                        .lineHeight(vp2.vp2(16.41))
                        .height(vp2.vp2(40))
                        .onChange(this.onContentChange)
                }
            }
            .padding(vp2.vp2(10))
            .height(this.isTextArea ? vp2.vp2(160) : vp2.vp2(40))
            .borderRadius(5)
            .layoutWeight(1)
            .borderWidth(vp2.vp2(1))
            .borderColor("#FFE6EBF0")
        }
        .alignItems(this.isTextArea ? VerticalAlign.Top : VerticalAlign.Center)
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.

新建接收对象页面,src/main/ets/components/settings/SettingMessageItem.ets

【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所-鸿蒙开发者社区

// 导入常用的常量和颜色库
import { CommonConst, commonColor } from "@wcmzllx/common-const-library"
// 导入UI窗口工具库,用于获取导航栏高度等信息
import { uiWindows } from "../../common/UIWindows"
// 导入新的视口处理库
import { vp2 } from "../../common/NewVp"
// 导入设置消息小部件,用于展示设置消息列表项
import { SettingMessageWidget } from "./SettingMessageWidget"
// 导入添加接收对象对话框组件
import { AddRecObjDialog } from "../../dialog/AddRecObjDialog"

// 定义设置消息项组件,使用ComponentV2进行结构优化
@ComponentV2
export struct SettingMessageItem {
    // 设置消息项的标题,作为参数传入,默认为"新增接收对象"
    @Param title: string = "新增接收对象"

    // 本地状态,控制对话框的显示与隐藏
    @Local isShowDialog: boolean = false;
    // 提供一个关闭对话框的方法,通过Provider注解使其可在模板中直接调用
    @Provider("cancelDialog") cancelDialog: () => void = () => {
        this.isShowDialog = false;
    };

    // 构建方法,定义组件的UI结构
    build() {
        // 创建一个滚动视图,容纳设置消息项的内容
        Scroll() {
            // 列布局,用于垂直排列子元素,设置元素之间的间距
            Column({ space: vp2.vp2(15) }) {
                // 行布局,用于水平排列子元素
                Row() {
                    // 创建一个按钮,设置其样式和事件处理程序
                    Button(this.title, { type: ButtonType.Normal })
                        .borderRadius(5)
                        .backgroundColor(commonColor.BRAND_COLOR)
                        .width(vp2.vp2(302.5))
                        .height(vp2.vp2(40))
                        .fontSize(vp2.vp2(14))
                        .onClick(()=>{
                            this.isShowDialog = true;
                        })
                        // 根据对话框的显示状态,条件渲染对话框内容
                        .bindContentCover($$this.isShowDialog, this.Dialog())

                    // 占位符,用于调整布局
                    Blank()

                    // 刷新按钮,包含图标和文本
                    Text(undefined) {
                        SymbolSpan($r("sys.symbol.arrow_clockwise"))
                            .fontColor([commonColor.BRAND_COLOR])

                        Span("刷新")
                            .fontColor(commonColor.BRAND_COLOR)
                    }
                    .fontWeight(FontWeight.Regular)
                    .fontSize(vp2.vp2(14))
                    .lineHeight(vp2.vp2(16.41))
                }
                // 设置行布局的内边距和宽度
                .padding({
                    top: vp2.vp2(15),
                    bottom: vp2.vp2(15)
                })
                .width(CommonConst.GLOBAL_FULL_SCREEN)
                // 显示数据统计信息
                Text(undefined) {
                    Span("共 ")
                    Span("3045")
                        .fontColor(commonColor.BRAND_COLOR)
                    Span(" 条数据")

                }
                .fontColor("#FF8D9094")
                .fontWeight(FontWeight.Regular)
                .fontSize(vp2.vp2(15))
                .lineHeight(vp2.vp2(11))
                .width(CommonConst.GLOBAL_FULL_SCREEN)
                .textAlign(TextAlign.Start)

                // 使用ForEach循环生成设置消息小部件
                ForEach([1, 2, 3, 4, 5], (item: number) => {
                    SettingMessageWidget()
                })
            }
            // 设置列布局的下边距和宽度,考虑到底部导航栏的高度
            .padding({
                bottom: uiWindows.getNavigationHeight() + vp2.vp2(10)
            })
            .width(CommonConst.GLOBAL_FULL_SCREEN)
        }
        // 设置滚动视图的滚动条状态、对齐方式和高度
        .scrollBar(BarState.Off)
        .align(Alignment.Top)
        .height(CommonConst.GLOBAL_FULL_SCREEN)
    }

    // 定义对话框内容构建方法
    @Builder
    Dialog(){
        // 堆叠布局,用于放置对话框组件
        Stack(){
            AddRecObjDialog()
        }
        .width(CommonConst.GLOBAL_FULL_SCREEN)
        .height(CommonConst.GLOBAL_FULL_SCREEN)
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.

系统配置页面src/main/ets/components/settings/SettingRadioWidget.ets

/*
 * Copyright (c) 2025.成都市一颗优雅草科技有限公司
 * author:卓伊凡-优雅草技术总监
 * project:优雅草星云物联网智控AI系统
 */

// 导入常用颜色常量
import { commonColor } from "@wcmzllx/common-const-library"
// 导入视觉比例转换工具
import { vp2 } from "../../common/NewVp"
// 导入自定义按钮组件
import { ButtonWidget } from "../common/ButtonWidget";

// 定义设置单选组件
@ComponentV2
export struct SettingRadioWidget {
    // 标题参数,默认值为"系统语言"
    @Param title: string = "系统语言"
    // 是否必填参数,默认值为true
    @Param isMust: boolean = true
    // 切换事件参数
    @Event onSwitchChange: (isOn: boolean) => void;
    // 选项列表参数,默认值为["选项1", "选项2"]
    @Param selectList: string[] = ["选项1", "选项2"]
    // 当前选中索引,默认值为0
    @Local selectIndex: number = 0
    // 按钮宽度参数
    @Param widthB: number = 89.83

    // 构建组件界面
    build() {
        // 使用Row组件布局,设置间距
        Row({ space: vp2.vp2(5) }) {
            // 显示标题和必填标记
            Text(undefined) {
                if (this.isMust) {
                    Span("*").fontColor("#FFFD0808")
                }
                Span(this.title + ":")
                    .fontColor(commonColor.FONT_3333_COLOR)
            }
            .fontSize(vp2.vp2(14))
            .fontWeight(FontWeight.Regular)
            .lineHeight(vp2.vp2(16.41))

            // 使用Row组件布局选项列表,设置间距
            Row({ space: vp2.vp2(4) }) {
                // 循环生成选项按钮
                ForEach(this.selectList, (item: string, index: number) => {
                    ButtonWidget({
                        title: item,
                        index: index,
                        fColor: this.selectIndex == index ? commonColor.WHITE_COLOR : commonColor.BRAND_COLOR,
                        bColor: this.selectIndex == index ? commonColor.BRAND_COLOR : Color.Transparent,
                        widthB: this.widthB,
                        onClickEvent: (selectIndex) => {
                            this.selectIndex = selectIndex;
                    } })
                        .borderRadius(vp2.vp2(5))
                        .borderWidth(vp2.vp2(1))
                        .borderColor(this.selectIndex == index ? Color.Transparent : "#FFE4E4E4")
                })
            }
            //.justifyContent(FlexAlign.End)
            // .padding(vp2.vp2(10))
            .height(vp2.vp2(40))
            .layoutWeight(1)
        }
    }
}

// 自定义单选按钮样式类
class MyRadioStyle implements ContentModifier<RadioConfiguration> {
    type: number = 0
    title: string = ""

    constructor(numberType: number, title: string) {
        this.type = numberType
        this.title = title
    }

    applyContent(): WrappedBuilder<[RadioConfiguration]> {
        return wrapBuilder(buildRadio)
    }
}

// 构建自定义单选按钮
@Builder
function buildRadio(config: RadioConfiguration) {
    Button((config.contentModifier as MyRadioStyle).title)
        .borderRadius(5)
        .borderWidth(vp2.vp2(1))
        .borderColor(config.checked ? Color.Transparent : "#FFE4E4E4")
        .fontColor(config.checked ? commonColor.WHITE_COLOR : commonColor.BRAND_COLOR)
        .padding(0)
        .fontWeight(FontWeight.Regular)
        .backgroundColor(config.checked ? commonColor.BRAND_COLOR : Color.Transparent)
        .height(vp2.vp2(40))
        .fontSize(vp2.vp2(14))
        .width(vp2.vp2(89.83))
        .type(ButtonType.Normal)
        .onClick(() => {
            if (config.checked) {
                config.triggerChange(false)
                return;
            }
            config.triggerChange(true)
        })
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.

【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所-鸿蒙开发者社区

系统配置页面对应的选择src/main/ets/components/settings/SettingSelectWidget.ets

/*
 * Copyright (c) 2025.成都市一颗优雅草科技有限公司
 * author:卓伊凡-优雅草技术总监
 * project:优雅草星云物联网智控AI系统
 */

import { commonColor, CommonConst } from "@wcmzllx/common-const-library"
import { vp2 } from "../../common/NewVp"

@Extend(Select)
function selectOption(text: string) {
    .value(text)
    .font({ size: 14, weight: FontWeight.Regular })
    .fontColor(commonColor.FONT_9999_COLOR)
    .backgroundColor(Color.Transparent)
    .padding(vp2.vp2(10))
    .margin(0)
    .borderRadius(0)
}


@ComponentV2
export struct SettingSelectWidget {
    @Param title: string = "系统语言"
    @Param data: SelectOption[] = [
        { value: 'aaa' },
        { value: 'bbb' },
        { value: 'ccc' },
        { value: 'ddd' }]
    @Param isMust: boolean = true
    @Local index: number = 0;

    @Local text: string = "";

    aboutToAppear(): void {
        try{
            this.text = this.data[0].value as string
        }catch (e) {
            this.text = "请选择";
        }
    }

    build() {
        Row({ space: vp2.vp2(5) }) {
            Text(undefined) {
                if (this.isMust) {
                    Span("*").fontColor("#FFFD0808")
                }
                Span(this.title + ":")
                    .fontColor(commonColor.FONT_3333_COLOR)
            }
            .fontSize(vp2.vp2(14))
            .fontWeight(FontWeight.Regular)
            .lineHeight(vp2.vp2(16.41))

            Stack() {
                Row() {
                    Select(this.data)
                        .selectOption(this.text)
                        .onSelect((index: number, text?: string | undefined) => {

                        })
                        .height(CommonConst.GLOBAL_FULL_SCREEN)
                        .width("200%")
                }
                .height(CommonConst.GLOBAL_FULL_SCREEN)
                .width(CommonConst.GLOBAL_FULL_SCREEN)
                .zIndex(1)

                Row() {
                    Image($r("app.media.ic_input_select"))
                        .height(vp2.vp2(16))
                        .aspectRatio(1)
                }
                .justifyContent(FlexAlign.End)
                .padding(vp2.vp2(10))
                .hitTestBehavior(HitTestMode.Transparent)
                .zIndex(2)
                .height(CommonConst.GLOBAL_FULL_SCREEN)
                .width(CommonConst.GLOBAL_FULL_SCREEN)

            }
            .clip(true)
            .height(vp2.vp2(40))
            .borderRadius(5)
            .layoutWeight(1)
            .borderWidth(vp2.vp2(1))
            .borderColor("#FFE6EBF0")
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.

系统设置 选择组件src/main/ets/components/settings/SettingSettingItem.ets

/*
 * Copyright (c) 2025.成都市一颗优雅草科技有限公司
 * author:卓伊凡-优雅草技术总监
 * project:优雅草星云物联网智控AI系统
 */

// 导入常用的常量、颜色、设置项模型和数组模型
import { CommonConst, commonColor, SettingsItemModel, SettingsArrayModel } from "@wcmzllx/common-const-library"
// 导入统一的UI窗口工具
import { uiWindows } from "../../common/UIWindows"
// 导入可视区域计算工具
import { vp2 } from "../../common/NewVp"
// 导入设置输入组件
import { SettingInputWidget } from "./SettingInputWidget"
// 导入设置选择组件
import { SettingSelectWidget } from "./SettingSelectWidget"
// 导入设置开关组件
import { SettingSwitchWidget } from "./SettingSwitchWidget"

// 定义一个设置项组件,用于展示和编辑设置
@ComponentV2
export struct SettingSettingItem {
    // 接受一个设置数组模型的参数
    @Param item: SettingsArrayModel[] = []

    // 构建UI界面
    build() {
        // 创建一个滚动视图,用于容纳可能超出屏幕的设置项
        Scroll() {
            // 创建一个垂直布局,用于排列设置项
            Column({ space: vp2.vp2(15) }) {
                // 添加一个空白视图,用于调整布局间距
                Blank().height(vp2.vp2(13))

                // 遍历设置数组,动态生成设置项
                ForEach(this.item, (item: SettingsArrayModel) => {
                    // 如果设置项有标题,则显示标题
                    if (item.title) {
                        // 创建一个水平布局,用于显示设置项的标题
                        Row({ space: vp2.vp2(5) }) {
                            // 添加一个彩色条,用于装饰标题
                            Column().width(vp2.vp2(4.5)).height(vp2.vp2(19.5)).backgroundColor(commonColor.BRAND_COLOR)

                            // 显示设置项的标题
                            Text(item.title)
                                .fontColor(commonColor.FONT_3333_COLOR)
                                .fontSize(vp2.vp2(15))
                                .fontWeight(FontWeight.Bold)
                                .lineHeight(vp2.vp2(17.58))
                        }
                        //.margin({ top: vp2.vp2(10) })
                        .justifyContent(FlexAlign.Start)
                        .width(CommonConst.GLOBAL_FULL_SCREEN)
                        .height(vp2.vp2(24))
                    }
                    // 遍历设置项,根据类型显示不同的设置组件
                    ForEach(item.item, (item: SettingsItemModel) => {
                        // 如果是开关类型设置项
                        if (item.type == "switch") {
                            // 显示开关组件
                            SettingSwitchWidget({
                                title: item.title,
                                isMust: item.isMust,
                                isOn: item.isOn,
                                onSwitchChange: item.onSwitchChange
                            })
                        } else if (item.type == "select") {
                            // 如果是选择类型设置项,显示选择组件
                            SettingSelectWidget({ title: item.title, isMust: item.isMust })// , data: item.data
                            // SettingSelectWidget()
                        } else if (item.type == "input") {
                            // 如果是输入类型设置项,显示输入组件
                            SettingInputWidget({
                                title: item.title,
                                isMust: item.isMust,
                                onContentChange: item.onInputChange
                            })
                        }
                    })
                })

                // 添加一个确认更新按钮
                Button("确认更新", { type: ButtonType.Normal })
                    .borderRadius(5)
                    .backgroundColor(commonColor.BRAND_COLOR)
                    .width(vp2.vp2(372))
                    .height(vp2.vp2(40))
                    .fontSize(vp2.vp2(14))
                    .margin({ top: vp2.vp2(35) })
            }
            // 设置滚动视图的底部填充,以适应不同设备的导航栏高度
            .padding({
                bottom: uiWindows.getNavigationHeight() + vp2.vp2(10)
            })
            .width(CommonConst.GLOBAL_FULL_SCREEN)
        }
        // 关闭滚动条,提升用户体验
        .scrollBar(BarState.Off)
        .align(Alignment.Top)
        .height(CommonConst.GLOBAL_FULL_SCREEN)
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.

定义开关 src/main/ets/components/settings/SettingSwitchWidget.ets 这块主要是针对颜色变化

/*
 * Copyright (c) 2025.成都市一颗优雅草科技有限公司
 * author:卓伊凡-优雅草技术总监
 * project:优雅草星云物联网智控AI系统
 */

// 导入常用颜色常量库
import { commonColor } from "@wcmzllx/common-const-library"
// 导入统一的视觉和布局参数库
import { vp2 } from "../../common/NewVp"

// 定义一个设置开关组件,用于在界面上展示一个带开关的设置项
@ComponentV2
export struct SettingSwitchWidget {
    // 设置项的标题,默认值为"系统语言"
    @Param title: string = "系统语言"
    // 是否为必填项,用于标记设置项的重要性
    @Param isMust: boolean = true
    // 开关的初始状态,true表示开启,false表示关闭
    @Param isOn: boolean = true;
    // 当开关状态改变时触发的事件,接收一个布尔值参数,表示新的开关状态
    @Event onSwitchChange: (isOn: boolean) => void;

    // 组件的构建方法,用于定义组件的UI结构
    build() {
        // 使用Row组件来布局设置项的标题和开关,设置它们之间的间距
        Row({ space: vp2.vp2(5) }) {
            // 使用Text组件来显示设置项的标题,如果设置项为必填,则在标题前加一个红色的星号
            Text(undefined) {
                if (this.isMust) {
                    Span("*").fontColor("#FFFD0808")
                }
                Span(this.title + ":")
                    .fontColor(commonColor.FONT_3333_COLOR)
            }
            .fontSize(vp2.vp2(14))
            .fontWeight(FontWeight.Regular)
            .lineHeight(vp2.vp2(16.41))

            // 使用Row组件来布局开关,并设置其对齐方式和样式
            Row() {
                // 使用Toggle组件来显示一个开关按钮,并设置其类型、初始状态、大小、选中颜色以及状态改变时的事件处理函数
                Toggle({ type: ToggleType.Switch, isOn: this.isOn })
                    .size({ width: vp2.vp2(44.44), height: vp2.vp2(25) })
                    .selectedColor(commonColor.BRAND_COLOR)
                    .onChange(this.onSwitchChange)
                    .borderRadius(vp2.vp2(12.5))
            }
            .justifyContent(FlexAlign.End)
            .padding(vp2.vp2(10))
            .height(vp2.vp2(40))
            //.borderRadius(5)
            .layoutWeight(1)
           // .borderWidth(vp2.vp2(1))

            // .borderColor("#FFE6EBF0")
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.

src/main/ets/components/settings/TabsBarWidget.ets

/*
 * Copyright (c) 2025.成都市一颗优雅草科技有限公司
 * author:卓伊凡-优雅草技术总监
 * project:优雅草星云物联网智控AI系统
 */

// 导入常用常量和颜色配置
import { CommonConst, commonColor } from "@wcmzllx/common-const-library"
// 导入自定义的vp2工具函数
import { vp2 } from "../../common/NewVp"

// 定义一个组件,使用ComponentV2装饰器标记
@ComponentV2
export struct TabsBarWidget {
    // 定义一个参数,表示当前选中的标签页索引
    @Param index: number = 0
    // 定义一个事件,当标签页索引发生变化时触发
    @Event $index: (index: number) => void;
    // 定义一个依赖项,需要一个TabsController实例
    @Require @Param controller: TabsController;
    // 定义一个私有成员,用于滚动列表
    private listScroller: ListScroller = new ListScroller()

    // 监视index属性变化,当index变化时,滚动列表到对应的项
    @Monitor("index")
    onIndexChange() {
        this.listScroller.scrollToIndex(this.index);
    }

    // 构建组件UI
    build() {
        // 创建一个列表,使用listScroller进行滚动,设置项之间的间距
        List({ scroller: this.listScroller, space: vp2.vp2(31) }) {
            // 遍历设置项,生成每个标签页项
            ForEach(CommonConst.SETTING_ITEM, (item: string, index: number) => {
                ListItem() {
                    Stack({ alignContent: Alignment.Center }) {
                        // 根据当前索引是否与项索引一致,决定是否显示选中状态
                        if (this.index == index) {
                            // 显示选中状态,包括下划线和文本颜色变化
                            Stack({ alignContent: Alignment.Bottom }) {
                                Divider()
                                    .width(vp2.vp2(46))
                                    .strokeWidth(vp2.vp2(1.5))
                                    .color("#FF008DF0")
                            }
                            .height(CommonConst.GLOBAL_FULL_SCREEN)

                            Text(item)
                                .fontColor(commonColor.FONT_00DFF0_COLOR)
                                .fontSize(vp2.vp2(14))
                                .fontWeight(600)
                                .lineHeight(vp2.vp2(16.41))
                                .offset({
                                    y: vp2.vp2(5.25) * -1
                                })
                        } else {
                            // 未选中状态,文本颜色不同
                            Text(item)
                                .fontColor(commonColor.FONT_6666_COLOR)
                                .fontSize(vp2.vp2(14))
                                .fontWeight(FontWeight.Regular)
                                .lineHeight(vp2.vp2(16.41))
                        }
                    }
                    .height(CommonConst.GLOBAL_FULL_SCREEN)
                    // 点击事件,改变当前索引并触发事件
                    .onClick(() => {
                        this.controller.changeIndex(index);
                        this.$index(index)
                    })
                }
            })
        }
        // 设置列表滚动方向,关闭滚动条,设置宽度和高度
        .listDirection(Axis.Horizontal)
        .scrollBar(BarState.Off)
        .width(CommonConst.GLOBAL_FULL_SCREEN)
        .height(vp2.vp2(30))
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.

【04】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-自定义一个设置输入小部件组件-完成所-鸿蒙开发者社区

ok 基本上 设置相关页面基本就完成了,

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
1
收藏
回复
举报
1


回复
    相关推荐
    社区精华内容