[Daily HarmonyOS Next Knowledge] Custom Pop-up Background, State Management V2 Practices, Bottom Safe Height, OCR Recognition Result Processing, Grid Divider
1. When using promptAction to display a custom pop-up in HarmonyOS, why is there a white background with a fixed width at the bottom?
Reference demo:
import promptAction from '@ohos.promptAction'
@Builder function HWUIToastBuilder() {
Column() {
Text('弹窗')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.padding(16)
}
.constraintSize({
minWidth: 100,
maxWidth: 200,
minHeight: 56
})
.backgroundColor(Color.Black)
.borderRadius(8)
}
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
promptAction.openCustomDialog({
builder: HWUIToastBuilder.bind(this),
// isModal: false,
alignment: DialogAlignment.Center
}).then((id: number) => {
// HWUIToast.toastId = id
})
})
}
.width('100%')
}
.height('100%')
}
}
The width of the pop-up window opened by promptAction.openCustomDialog
is fixed at 4 grid units in portrait mode and 5 grid units in landscape mode. For custom pop-up styles, it is recommended to use CustomDialogController
.
Reference link: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-methods-custom-dialog-box-V5
2. Are there any excellent practices or priority cases for HarmonyOS State Management V2?
Reference code:
@ObservedV2
class BasicPickData {
@Trace fundName: string = ''
@Trace plateName: string = ''
}
@ObservedV2
class SubPickData {
@Trace subCardData: string = ''
@Trace cell: BasicPickData[] = []
}
@ObservedV2
class MergeCellData {
@Trace title: string = ''
key: string = ''
@Trace items: SubPickData[] = []
}
@Entry
@Component
struct HomeMainPage {
@State testListData: MergeCellData[] = []
aboutToAppear() {
let mergeCellData: MergeCellData = new MergeCellData()
mergeCellData.title = 'swiper 0'
mergeCellData.key = 'swiperKey'
for (let i = 0; i < 4; i++) {
let swiperItem: SubPickData = new SubPickData()
swiperItem.subCardData = 'subCardData'+ i
for (let j = 0; j < 4;j++) {
let cellData: BasicPickData = new BasicPickData()
cellData.fundName = 'cell_' + j + '_fundName'
cellData.plateName = 'cell_' + j + '_plateName'
swiperItem.cell.push(cellData)
}
mergeCellData.items.push(swiperItem)
}
this.testListData.push(mergeCellData)
}
// Generate a random number between 1 and 100
getRandomVal() {
const min = 1;
const max = 100;
const randomInt = Math.floor(Math.random() * (max - min + 1)) + min;
return randomInt
}
build() {
Column() {
Button('refresh').onClick(() => {
setTimeout(() => {
this.testListData[0].title = 'new swiper' + this.getRandomVal()
for (let i = 0; i < this.testListData.length; i++) {
this.testListData[i].title = 'new swiper' + this.getRandomVal()
for (let j = 0; j < this.testListData[i].items.length; j++) {
this.testListData[i].items[j].subCardData = 'new subCardData'+ j + this.getRandomVal()
for (let x = 0; x < this.testListData[i].items[j].cell.length; x++) {
this.testListData[i].items[j].cell[x].fundName = 'cell_' + x + 'new fundName' + x+ this.getRandomVal()
this.testListData[i].items[j].cell[x].plateName = 'cell_' + j + 'new plateName' + j + this.getRandomVal()
}
}
}
}, 1000)
})
List() {
ForEach(this.testListData, (item: MergeCellData) => {
ListItem() {
SwiperCom({swiperData: item})
}
}, (item: MergeCellData, index: number) => item.key + index)
}
.width('100%')
.height('calc(100% - 56vp - 32vp)')
.padding({ left: 14, right: 14 })
}
.width('100%')
.height('100%')
}
}
@Component
struct ListCom {
listData?: SubPickData
build() {
Column() {
Text(this.listData?.subCardData)
List() {
ForEach(this.listData?.cell, (item: BasicPickData, index: number) => {
ListItem() {
Text(item?.fundName)
}
}, (item: BasicPickData, index: number) => index + '')
}
.width('100%')
}
}
}
@Component
struct SwiperCom {
swiperData: MergeCellData = new MergeCellData()
build() {
Column() {
Text(this.swiperData?.title)
Swiper() {
ForEach(this.swiperData?.items, (item: SubPickData, index: number) => {
ListCom({listData: item})
}, (item: SubPickData, index: number) => index + '')
}
}
}
}
3. When getting the bottom safe height in HarmonyOS, why is bottomRect.height 0?
Use the following type: windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR)
.
4. How to convert the OCR result URI to an image.PixelMap for display on the page in HarmonyOS?
Reference demo:
import { CardRecognition, CallbackParam, CardType, CardSide } from "@kit.VisionKit";
import { image } from '@kit.ImageKit'
import fs from '@ohos.file.fs';
@Entry
@Component
struct Index {
@State showOCR:boolean = false
@State src?: image.PixelMap = undefined
build() {
Stack() {
Column(){
Button('click me')
.onClick(()=>{
this.showOCR = true
})
Image(this.src)
}
if(this.showOCR) {
this.CardOCRPage()
}
}
.width('100%')
.height('100%')
}
@Builder
CardOCRPage() {
// Stack({ alignContent: Alignment.Top }) {
CardRecognition({
// Select ID card type as an example here
supportType: CardType.CARD_ID,
cardSide:CardSide.FRONT,
callback: async (params:CallbackParam)=>{
this.showOCR = false
if(params.cardInfo) {
let imageUri = params.cardInfo['front']['cardImageUri'];
let file = fs.openSync(imageUri, fs.OpenMode.READ_ONLY);
console.info('file fd:' + file.fd);
const imageSource: image.ImageSource = image.createImageSource(file.fd);
let decodingOptions: image.DecodingOptions = {
editable: true,
desiredPixelFormat: 3,
}
this.src = await imageSource.createPixelMap(decodingOptions);
}
}
})
// }
.width('100%')
.height('100%')
}
}
5. How to set dividers for a HarmonyOS Grid?
Currently, the Grid does not have a dedicated divider setting. You can achieve the divider effect by setting borders for GridItem or using the Divider component in GridItem.
Top comments (0)