HarmonyOS官网案例解析——保存应用数据

介绍

本篇Codelab将介绍如何使用基础组件Slider,通过拖动滑块调节应用内字体大小。要求完成以下功能:

  1. 实现两个页面的UX:主页面和字体大小调节页面。
  2. 拖动滑块改变字体大小系数,列表页和调节页面字体大小同步变化。往右拖动滑块字体变大,反之变小。
  3. 字体大小支持持久化存储,再次启动时,应用内字体仍是调节后的字体大小。

最终效果图如图所示:

https://gitee.com/runitwolf/sloop-pic-go/raw/master/image/202312212240377.gif

一、相关概念

  • 字体大小调节原理:通过组件Slider滑动,获取滑动数值,将这个值通过首选项进行持久化,页面的字体通过这个值去改变大小。
  • 首选项:首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。

二、完整实例

gitee源码地址

ps:官网的案例很简单,但是有很多地方值得我们借鉴。

官方对案例解析

<HarmonyOS第一课>保存应用数据

三、零基础实战开发

一、用数组的方法值得借鉴

  1. 现新建一个bean类
export default class SettingData{
  settingName:string
  settingImage:Resource
}
  1. 新建HomeViewModel.etx
import SettingData from './SettingData'

export class HomeViewModel {
  settingArr: SettingData[] = []

  initSettingData(): SettingData[] {
    if (this.settingArr.length === 0) {
      let settingData = new SettingData()
      settingData.settingName = '显示和亮度'
      settingData.settingImage = $r('app.media.ic_display_and_brightness')
      this.settingArr.push(settingData)

      settingData = new SettingData();
      settingData.settingName = '声音';
      settingData.settingImage = $r('app.media.ic_voice');
      this.settingArr.push(settingData);

      settingData = new SettingData();
      settingData.settingName = '应用管理';
      settingData.settingImage = $r('app.media.ic_app_management');
      this.settingArr.push(settingData);

      settingData = new SettingData();
      settingData.settingName = '存储';
      settingData.settingImage = $r('app.media.ic_storage');
      this.settingArr.push(settingData);

      settingData = new SettingData();
      settingData.settingName = '隐私';
      settingData.settingImage = $r('app.media.ic_privacy');
      this.settingArr.push(settingData);

      settingData = new SettingData();
      settingData.settingName = '设置字体大小';
      settingData.settingImage = $r('app.media.ic_setting_the_font_size');
      this.settingArr.push(settingData);

    }
    return this.settingArr
  }
}
export default new HomeViewModel()

在index.ets中直接使用即可使用方法如下

 settingArr = HomeViewModel.initSettingData();
 //settingArr[x],x为数组的索引,直接使用就可以获取设定的数据

1."标题"页面实现

import { TitleBarComponent } from '../view/TitleBarComponent'

@Entry
@Component
struct Index {
  build() {
    Column() {
      TitleBarComponent({ isBack: false, title: '设置' })
    }
    .width('100%')
    .height('100%')
  }
}
import router from '@ohos.router'
@Component
export struct TitleBarComponent {
  isBack:boolean = true
  title:string = ''

  build() {
    Row() {
      if (this.isBack){
        Image($r('app.media.ic_public_back'))
          .width(24)
          .height(24)
          .margin({ right: 4 })
          .onClick(() => {
            router.back()
          })
      }
      Text(this.title)
        .fontColor(Color.Black)
        .fontSize($r('sys.float.ohos_id_text_size_headline8'))
        .fontWeight(FontWeight.Medium)
        .margin({ left: 8 })
    }
    .width('100%')
    .height('7.2%')
    .padding({ left: 16 })
  }
}

在这里插入图片描述

2."显示和亮度"页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {
  settingArr: SettingData[] = HomeViewModel.initSettingData()
  @State changeFontSize: number = 16

  build() {
    Column() {
      ...
      //显示和亮度
      Row() {
        SettingItemComponent({
          setting: this.settingArr[0],
          changeFontSize: this.changeFontSize,
          itemClick: () => {
            //TODO
          }
        })
      }
      .blockBackground('1.5%')
    }
    .backgroundColor('#f1f3f5')
    .width('100%')
    .height('100%')
  }
}

@Extend(Row) function blockBackground (marginTop: string) {
  .backgroundColor(Color.White)
  .borderRadius(24)
  .margin({ top: marginTop })
  .width('93.3%')
  .padding({ top: 4, bottom: 4 })
}

思考题:这里的changeFontSize变量为什么需要用@State进行修饰,而settingArr又为什么不需要?

3."声音"页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {

  build() {
    Column() {
      TitleBarComponent({ isBack: false, title: '设置' })
      ...
      //声音
      Row() {
        SettingItemComponent({
          setting: this.settingArr[1],
          changeFontSize: this.changeFontSize,
          itemClick: () => {
            //TODO
          }
        })
      }
      .blockBackground('1.5%')
    }
    .backgroundColor('#f1f3f5')
    .width('100%')
    .height('100%')
  }
}

4.“应用管理”、"存储"等列表页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {
  settingArr: SettingData[] = HomeViewModel.initSettingData()
  @State changeFontSize: number = 16

  build() {
    Column() {
     ...
      Row(){
        this.SettingItems()
      }
      .blockBackground('1.5%')
    }
    ...
  }

  @Builder SettingItems(){
    List(){
      ForEach(this.settingArr.splice(2,6),(item:SettingData,index:number)=>{
        ListItem(){
          SettingItemComponent({setting:item,changeFontSize:this.changeFontSize,itemClick:()=>{
            //TODO
          }})
        }
      }, (item:SettingData,index:number)=>JSON.stringify(item)+index)
    }
  }
}

5."设置字体大小"点击事件跳转

import router from '@ohos.router'
import PreferencesUtil from '../common/database/PreferencesUtil'
import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {
  settingArr: SettingData[] = HomeViewModel.initSettingData()
  @State changeFontSize: number = 16

  onPageShow(){
    PreferencesUtil.getChangeFontSize().then((value)=>{
      this.changeFontSize = value
    })
  }

  build() {
	....
  @Builder SettingItems(){
    List(){
      ForEach(this.settingArr.splice(2,6),(item:SettingData,index:number)=>{
        ListItem(){
          SettingItemComponent({setting:item,changeFontSize:this.changeFontSize,itemClick:()=>{
            if (index === 3) {
              router.pushUrl({
                url:"pages/SetFontSizePage"
              })
            }
          }})
        }
      }, (item:SettingData,index:number)=>JSON.stringify(item)+index)
    }
  }
}

在pages目录下新建SetFontSizePage子组件

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct SetFontSizePage {

  build() {
    Column() {
      TitleBarComponent({ title: '字体大小设置' })
    }
    .width('100%')
    .height('100%')
  }
}

ps:官网的案例不太友好,我们在官网的页面基础上进行功能及界面简化

6.SetFontSizePage页面创建数据

我们之前在首页HomeViewModel模型下创建过数据,我们沿用HomeViewModel模型,继续创建想要的数据

import SettingData from './SettingData'

export class HomeViewModel {
  ...
  fontSizeArr: SettingData[] = []
  ...

  initFontSizeData():SettingData[]{
    this.fontSizeArr = new Array();
    let fontSizeArr = new SettingData()
    fontSizeArr.settingName = '11111111111111111111'
    this.fontSizeArr.push(fontSizeArr)
    fontSizeArr = new SettingData()
    fontSizeArr.settingName = '22222222222222222222'
    this.fontSizeArr.push(fontSizeArr)
    fontSizeArr = new SettingData()
    fontSizeArr.settingName = '33333333333333333333'
    this.fontSizeArr.push(fontSizeArr)
    fontSizeArr = new SettingData()
    fontSizeArr.settingName = '44444444444444444444'
    this.fontSizeArr.push(fontSizeArr)

    return this.fontSizeArr
  }
}
export default new HomeViewModel()

7.写SetFontSizePage中list页面

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct SetFontSizePage {
  contentArr: SettingData[] = HomeViewModel.initFontSizeData()
  @State changeFontSize: number = 0

  onPageShow(){
    PreferencesUtil.getChangeFontSize().then((value)=>{
      this.changeFontSize = value
    })
  }

  build() {
    Column() {
      TitleBarComponent({ title: '字体大小设置' })
      List() {
        ForEach(this.contentArr, (item: SettingData, index: number) => {
          ListItem() {
            ItemComponent({ contentArr: item, changeFontSize: this.changeFontSize })
          }

        }, (item: SettingData, index: number) => JSON.stringify(item) + index)
      }
    }
    .width('100%')
    .height('100%')
  }
}
import SettingData from '../viewmodel/SettingData'
@Component
export struct ItemComponent {

  contentArr: SettingData
  @Prop changeFontSize:number

  build() {
    Column() {
      Text(this.contentArr.settingName)
        .fontSize(this.changeFontSize)
        .fontColor('#182431')
        .fontWeight(FontWeight.Medium)
        .height(48)
        .width('100%')
        .textAlign(TextAlign.Center)
    }
  }
}

看看list的效果图:

8.写SetFontSizePage进度条

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct SetFontSizePage {
	...
  build() {
    Column() {
     ...
      List() {
        ...
      }
      SliderLayout({changeFontSize:$changeFontSize})
    }
    ...
  }
}
import PreferencesUtil from '../common/database/PreferencesUtil'
@Component
export struct SliderLayout {

  @Link changeFontSize:number

  build() {
    Column() {
      Text('文字大小')
        .fontSize(14)
        .fontColor('#182431')
        .fontWeight(FontWeight.Medium)

      Row(){
        Text('A')
          .fontColor('#182431')
          .fontSize(20)
          .fontWeight(FontWeight.Medium)
          .textAlign(TextAlign.End)
          .width('12.5%')
          .padding({right:9})

        Slider({
          value:this.changeFontSize,
          min:14,
          max:22,
          step:2,
          style:SliderStyle.InSet
        })
          .showSteps(true)
          .width('75%')
          .onChange((value:number)=>{
            this.changeFontSize = value
          })

        Text('A')
          .fontColor('#182431')
          .fontSize(20)
          .fontWeight(FontWeight.Medium)
          .width('12.5%')
          .padding({left:9})
      }

    }
  }
}

运行后效果图如下:
在这里插入图片描述

至此,我们发现滑动进度条,页面的大小变了,但是返回页面后再次进入,数据没有保存。

四、保存应用数据

<HarmonyOS第一课>保存应用数据(官网文档)

根据官网的文档,我们新建PreferencesUtil工具类

import dataPreferences from '@ohos.data.preferences';
import { GlobalContext } from '../utils/GlobalContext';
import Logger from '../utils/Logger';

const TAG = '[PreferencesUtil]';
const PREFERENCES_NAME = 'myPreferences';
const KEY_APP_FONT_SIZE = 'appFontSize';

/**
 * The PreferencesUtil provides preferences of create, save and query.
 */
export class PreferencesUtil {
  createFontPreferences(context: Context) {
    let fontPreferences: Function = (() => {
      let preferences: Promise<dataPreferences.Preferences> = dataPreferences.getPreferences(context, PREFERENCES_NAME);
      return preferences;
    });
    GlobalContext.getContext().setObject('getFontPreferences', fontPreferences);
  }

  saveDefaultFontSize(fontSize: number) {
    let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;
    getFontPreferences().then((preferences: dataPreferences.Preferences) => {
      preferences.has(KEY_APP_FONT_SIZE).then(async (isExist: boolean) => {
        Logger.info(TAG, 'preferences has changeFontSize is ' + isExist);
        if (!isExist) {
          await preferences.put(KEY_APP_FONT_SIZE, fontSize);
          preferences.flush();
        }
      }).catch((err: Error) => {
        Logger.error(TAG, 'Has the value failed with err: ' + err);
      });
    }).catch((err: Error) => {
      Logger.error(TAG, 'Get the preferences failed, err: ' + err);
    });
  }

  saveChangeFontSize(fontSize: number) {
    let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;
    getFontPreferences().then(async (preferences: dataPreferences.Preferences) => {
      await preferences.put(KEY_APP_FONT_SIZE, fontSize);
      preferences.flush();
    }).catch((err: Error) => {
      Logger.error(TAG, 'put the preferences failed, err: ' + err);
    });
  }

  async getChangeFontSize() {
    let fontSize: number = 0;
    let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;
    fontSize = await (await getFontPreferences()).get(KEY_APP_FONT_SIZE, fontSize);
    return fontSize;
  }

  async deleteChangeFontSize() {
    let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;
    const preferences: dataPreferences.Preferences = await getFontPreferences();
    let deleteValue = preferences.delete(KEY_APP_FONT_SIZE);
    deleteValue.then(() => {
      Logger.info(TAG, 'Succeeded in deleting the key appFontSize.');
    }).catch((err: Error) => {
      Logger.error(TAG, 'Failed to delete the key appFontSize. Cause: ' + err);
    });
  }
}

export default new PreferencesUtil();
export class GlobalContext {
  private constructor() { }
  private static instance: GlobalContext;
  private _objects = new Map<string, Object>();

  public static getContext(): GlobalContext {
    if (!GlobalContext.instance) {
      GlobalContext.instance = new GlobalContext();
    }
    return GlobalContext.instance;
  }

  getObject(value: string): Object | undefined {
    return this._objects.get(value);
  }

  setObject(key: string, objectClass: Object): void {
    this._objects.set(key, objectClass);
  }
}

1.使用前提

需要在entryAbility的onCreate方法获取首选项实例

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Logger from '../common/utils/Logger';
import { GlobalContext } from '../common/utils/GlobalContext';
import PreferencesUtil from '../common/database/PreferencesUtil'

export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
 
    PreferencesUtil.createFontPreferences(this.context);
  }
	...
}

2.保存数据

在应用刚启动时,设置字体默认大小

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Logger from '../common/utils/Logger';
import { GlobalContext } from '../common/utils/GlobalContext';
import PreferencesUtil from '../common/database/PreferencesUtil'

export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
    ...
    // 设置字体默认大小
    PreferencesUtil.saveDefaultFontSize(16);
  }
	...
}

在滑动进度条后,保存进度条设置的字体大小

import PreferencesUtil from '../common/database/PreferencesUtil'
@Component
export struct SliderLayout {

  @Link changeFontSize:number

  build() {
    ...
        Slider({
         ...
          .onChange((value:number)=>{
            this.changeFontSize = value
            PreferencesUtil.saveChangeFontSize(this.changeFontSize)
          })
        ...
      }
    }
  }
}

3.获取保存的数据

数据都保存了,我们怎么去使用保存的数据呢?

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct SetFontSizePage {
 ...
  @State changeFontSize: number = 0

  onPageShow(){
    PreferencesUtil.getChangeFontSize().then((value)=>{
      this.changeFontSize = value
    })
  }

}
import router from '@ohos.router'
import PreferencesUtil from '../common/database/PreferencesUtil'
import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'

@Entry
@Component
struct Index {
  ...
  @State changeFontSize: number = 16

  onPageShow(){
    PreferencesUtil.getChangeFontSize().then((value)=>{
      this.changeFontSize = value
    })
  }
  ...
}
...

效果图:
在这里插入图片描述

至此,大功告成~~~撒花

至此,所有功能已全部完成。

代码链接:https://gitee.com/runitwolf/set-app-font-size

typora笔记链接:https://gitee.com/runitwolf/set-app-font-size/blob/master/%E5%BA%94%E7%94%A8%E5%86%85%E5%AD%97%E4%BD%93%E5%A4%A7%E5%B0%8F%E8%B0%83%E8%8A%82.md

CSDN typora笔记链接 :https://download.csdn.net/download/qq_36067302/88671288

  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一起学鸿蒙呀~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值