一、工作的主要介绍
今天主要写的是数字键盘和一次开发多端部署 ,这次主要使用的是Grid组件支持数字输入、小数点处理和删除操作,具备格式化和数值限制功能;响应式布局系统,自动检测屏幕断点变化,实时更新应用布局状态。
二、运行效果及主要设计思路的介绍
1.数字键盘运行截图
2.数字键盘设计思路
创建一个响应式数字键盘NumberKeyboard
,通过网格布局展示数字和删除按钮。使用样式封装保持UI一致性。实现数值输入与验证逻辑,确保合理性(如限制数值范围和小数点使用)。双向绑定确保输入实时更新到关联属性。
3.一次开发多端部署运行截图
4.一次开发多端部署的设计思路
实现了一个断点系统类,用于监听屏幕大小变化并更新应用的当前断点,通过绑定事件处理屏幕断点变化。
三、在设计的过程中遇到的问题
1.数值转换和验证
parseFloat
函数在处理字符串转换为数值时,如果字符串格式不正确,可能返回NaN
。需要确保对这种情况进行处理,例如通过条件判断来避免将NaN
赋值给amount
。
2.删除键逻辑:如果输入值已经是最大值999,再次点击删除键时,逻辑会将amount
设置为0,但value
可能不会同步更新。
在clickDelete
方法中添加逻辑,确保amount
和value
同步更新,并且在删除操作后保持一致。
四、最终实验代码
1.数字键盘的代码
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct NumberKeyboard {
numbers : string[]=['1','2','3','4','5','6','7','8','9','0','.']
@Link amount : number
@Link value : string
@Styles keyBox(){
.backgroundColor(Color.White)
.borderRadius(8)
.height(60)
}
build() {
Grid(){
ForEach(this.numbers,num=>{
GridItem(){
Text(num).fontSize(20).fontWeight(CommonConstants.FONT_WEIGHT_900)
}
.onClick(()=>this.clickNumber(num))
.keyBox()
})
GridItem(){
Text('删除').fontSize(20).fontWeight(CommonConstants.FONT_WEIGHT_900)
}
.onClick(()=>this.clickDelete())
.keyBox()
}
.width('100%')
.height(280)
.backgroundColor($r('app.color.index_page_background'))
.columnsTemplate('1fr 1fr 1fr')
.columnsGap(8)
.rowsGap(8)
.padding(8)
.margin({top:10})
}
clickNumber(num:string){
//1.拼接用户输入内容
let val = this.value+num
//2.判断格式正确
let firstIndex = val.indexOf('.')
let lastIndex = val.lastIndexOf('.')
//有两个小数点、有小数点并且小数点位数超过两位
if(firstIndex!==lastIndex||(lastIndex!=-1&&lastIndex<val.length-2)){
//非法输入
return
}
//3.将字符串转为数值
let amount = this.parseFloat(val)
//4.保存
if (amount>=999.9) {
this.amount=999.0
this.value = '999'
}
else {
this.amount = amount
this.value = val
}
}
clickDelete(){
if(this.value.length<=0){
this.value = ''
this.amount = 0
return
}
this.value = this.value.substring(0,this.value.length-1)
this.amount = this.parseFloat(this.value)
}
parseFloat(str:string){
if(!str){
return 0;
}
//如果小数点以小数点结尾去掉小数点
if(str.endsWith('.')){
str = str.substring(0,str.length-1)
}
return parseFloat(str)
}
}
2.一次开发多端部署代码
import mediaQuery from '@ohos.mediaquery'
import BreakpointConstants from '../constants/BreakpointConstants'
export default class BreakpointSystem{
private smListener: mediaQuery.MediaQueryListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_SM)
private mdListener: mediaQuery.MediaQueryListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_MD)
private lgListener: mediaQuery.MediaQueryListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_LG)
smListenerCallback(result: mediaQuery.MediaQueryResult){
if(result.matches){
this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_SM)
}
}
mdListenerCallback(result: mediaQuery.MediaQueryResult){
if(result.matches){
this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_MD)
}
}
lgListenerCallback(result: mediaQuery.MediaQueryResult){
if(result.matches){
this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_LG)
}
}
updateCurrentBreakpoint(breakpoint: string){
AppStorage.SetOrCreate(BreakpointConstants.CURRENT_BREAKPOINT, breakpoint)
}
register(){
this.smListener.on('change', this.smListenerCallback.bind(this))
this.mdListener.on('change', this.mdListenerCallback.bind(this))
this.lgListener.on('change', this.lgListenerCallback.bind(this))
}
unregister(){
this.smListener.off('change', this.smListenerCallback.bind(this))
this.mdListener.off('change', this.mdListenerCallback.bind(this))
this.lgListener.off('change', this.lgListenerCallback.bind(this))
}
}
五、总结
1.状态管理与绑定
使用@Link
装饰器实现了组件内部状态(amount
和value
)与外部状态的双向绑定,组件与父组件之间同步数据。
2.事件处理与输入验证
通过onClick
事件处理器,实现了数字按键和删除功能的交互逻辑。同时,对用户输入进行了格式验证,确保了输入的合法。
3.断点监听机制
类BreakpointSystem
创建了三个媒体查询监听器,分别对应小、中、大屏幕断点,用于检测屏幕大小变化。