1. Project Description
1.DEMO creativity is a card dictionary.
2. Different cards display different contents: micro card, small card, medium card, large card. Different contents of the same word are displayed according to different card characteristics. Users can choose their favorite card based on their habits.
3. Universal card refresh: Users click the card refresh button to view new content. At the same time, the card is set to refresh regularly, so that the cards users see every day are new text, making it easier for users to learn and review.
4. There is a search function in the meta-service. Users can search for corresponding words and explanations, and use the up and down sliding method similar to the current user habit to elaborate word by word.
5. Based on API9 and ArkTS language development, registration, login and other functions are realized through serverless cloud services.
2. Yuan service effect
- Universal card effect
2. Meta service inner page
3. Project Development
- Environment setup
Software requirements:
DevEco Studio version: DevEco Studio 3.1 Release and above.
HarmonyOS SDK version: API version 9 and above.
Hardware requirements:
Device type: Huawei mobile phone or Huawei mobile phone device simulator running on DevEco Studio.
HarmonyOS system: 3.1.0 Developer Release and above.
2. Interpretation of main code structure
entry/src/main/ets: file entry
common: public resource files
images: public image resources
Constants.ts: public constants
CountryViewModel.ts: Country number class
LazyFE_Class.ets: Lazy data loading class
Log.ts: log class
components: package component file
database: database encapsulation class
data_cyhz.ets: data file
entryability: application/service entry
entryformability: card service
pages: application/service pages
Auth.ets: Authentication and authorization
CloudFunction.ets: Cloud functions
CloudProject.ets: Cloud Projects
CloudStorage.ets: cloud storage
Index.ets: Home Page
User_Login.ets: Login page
User_SignUp.ets: Registration page
User_VerifyCodeLogin.ets: Verification code login page
services: background operation class
widget: service card
resources: resource file directory
3. Enter the application instructions
Since we are creating a cloud template project, there is no need to configure additional SDK dependencies. Just note that the initial integrated SDK location of the cloud template is different, so we still use context to initialize the SDK during the application initialization phase. It is recommended to do it in onCreate of entryability. .
4.Home page
We need to add a bottom menu bar to the application to switch between different application modules. Since each module is completely independent and does not need to refresh the interface every time it is switched, we use Tabs and TabContent components.
This application has a total of two modules: Home Page and Me, which correspond to the two sub-components of the Tabs component, TabContent.
The homepage contains two modules: search text and sliding browsing information. We will explain the specific code implementation in modules below.
Search text: The Search component is mainly used to jump to the corresponding text display information by searching for text. The main code is as follows:
... //Commonly used Chinese character search bar Column() { Search({ value: this.submitValue, placeholder: 'Chinese character search', controller: this.search }) .searchButton('Search') .placeholderColor(Color.Grey) .textFont({ size: 14, weight: 400 }) .margin({ left: 20, right: 20 }) .onSubmit((value: string) => { this.submitValue = value for (let i = 0; i < wz.length; i + + ) { const element: any = wz[i]; if (this.submitValue == element.zi) { this.swiperIndex = i this.submitValue = '' } } }) .onChange((value: string) => { this.changeValue = value }) }.width("100%").margin({ top: 20, bottom: 20 })</code>Copy
Browsing information module: It mainly uses the swiper component to pre-cache data through lazy loading of data and display text information by sliding the page. The main code is as follows:
... //Commonly used Chinese character carousel part Column() { Swiper(this.swiperController) { LazyForEach(this.data_wz, (item: any) => { Column() { ... }.width("100%") .height("100%") .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Start) }, item => item) } .vertical(true) .cachedCount(2) .autoPlay(false) .indicator(false) .loop(false) .duration(400) .itemSpace(0) .curve(Curve.Linear) .cachedCount(3) .index(this.swiperIndex) .disableSwipe(this.disableSwipe) .onChange((index: number) => { console.info("swiper:" + index.toString()) this.swiperIndex = index }) }.width("100%") ... </code>Copy
5.My
My page contains two modules: visitor login and user login.
Among them, the login information and some application functions are not displayed when the visitor logs in, and only some application capabilities can be used;
User login displays some user information and expands all functions of the application, which requires user registration and login;
We will explain the specific code implementation in modules below.
Guest login:
... //Visitor login status if (this.isVisitor) { //Avatar information Column() { Image($r('app.media.icon')) .width(90) .objectFit(ImageFit.Contain) .borderRadius(50) Text(this.isVisitor ? "Visitor_" : this.userName).fontSize(16).margin(20) Button(this.isLogin ? "Logout" : "Login", { type: ButtonType.Capsule }) .fontSize(14) .width('120') .height('30') .backgroundColor(0xf48fb1) .onClick(() => { router.replaceUrl({ url: "pages/User_Login" }) }) } .width('90%') .height('240') .borderRadius(12) .margin({ top: 20 }) .backgroundColor(0xFFFFFF) .shadow({ radius: 12, color: 0xCECECE, offsetX: 4, offsetY: 6 }) .justifyContent(FlexAlign.Center) } ...</code>Copy
User login:
... //Already logged in status if (!this.isVisitor) { //Avatar information Column() { ... } .width('90%') .height('240') .borderRadius(12) .margin({ top: 20 }) .backgroundColor(0xFFFFFF) .shadow({ radius: 12, color: 0xCECECE, offsetX: 4, offsetY: 6 }) .justifyContent(FlexAlign.Center) //options Column() { ... }.width('100%') .height("100%") .backgroundColor(0xF5F5F5) .justifyContent(FlexAlign.Start)</code>Copy
6.Registration login page
Allow users to register an account and fully use the application.
Core code:
... .onClick(() => { if (this.phoneNumber !== '' & amp; & amp; this.password !== '') { let verifyCodeSettings = new VerifyCodeSettingBuilder() .setAction(VerifyCodeAction.REGISTER_LOGIN) .setLang('zh_CN') .setSendInterval(60) .build(); agconnect.auth().requestPhoneVerifyCode(this.countryCode, this.phoneNumber, verifyCodeSettings) .then(verifyCodeResult => { this.startTimer() //Verification code application successful }).catch(error => { //Verification code application failed Prompt.showToast({ message: "Please enter the correct mobile phone number and password" + JSON.stringify(error) }) }); }else { Prompt.showToast({ message: "Mobile phone number and password cannot be empty" }) } }) ... ... .onClick(() => { if (this.phoneNumber !== '' & amp; & amp; this.password !== '') { let user = new PhoneUserBuilder() .setCountryCode(this.countryCode) .setPhoneNumber(this.phoneNumber) .setPassword(this.password) //You can set an initial password for the user. After filling in, you can use your password to log in later. .setVerifyCode(this.VerifyCode) .build(); agconnect.auth().createPhoneUser(user) .then(result => { //Create user successfully AppStorage.Set('phoneNumber', user.phoneNumber) AppStorage.Set('password', user.password) AppStorage.Set('isVisitor', false) AppStorage.Set('isLogin', true) AppStorage.Set('userName', user.phoneNumber) router.pushUrl({ url: "pages/Index" }) }) .catch(error => { //Failed to create user Prompt.showToast({ message: "Registration failed," + JSON.stringify(error),duration:4 }) }) } else { Prompt.showToast({ message: "Mobile phone number and password cannot be empty" }) } })</code>Copy
7. Other cloud services
Note: This is the initial business of the cloud template. If you have other business needs, you can add it yourself.
4. Card Development
Add cards as needed, or just create the card initially and modify the relevant card parameters.
- Create card
2. Initial card modification related parameters
Open the form_config.json file in the resources/base/profile directory and modify the parameters as needed
3. Card loading and data acquisition
The card loading and updating part is completed by the EntryFormAbility.ts file. You can refer to the official documentation here.
Since there is no connection to the background data part, we use custom simulation data here, and then randomly select the card content each time the card is mounted to the desktop. The code is as follows:
... aboutToAppear() { let idx = Math.floor((Math.random() * wz_arr.length)) this.zi = wz_arr[idx].zi this.pinYin = wz_arr[idx].pinYin this.buShou = wz_arr[idx].buShou this.biHua = wz_arr[idx].biHua this.fanTi = wz_arr[idx].fanTi this.near_words = wz_arr[idx].near_words this.reverse_words = wz_arr[idx].reverse_words this.explain = wz_arr[idx].explain.toString() } ...</code>Copy
4. Card master code
... Column() { //Micro card Stack() { Text(this.zi) .width("100%") .textAlign(TextAlign.Center) .fontSize(30) .fontColor('#1f1f1f') .fontWeight(600) .margin({right:20}) Row(){ Image("/common/images/R2.png") .width(18) .height(18) .margin({right:"15%"}) .objectRepeat(ImageRepeat.NoRepeat) .onClick(()=>{ this.rotateAngle = 180 this.aboutToAppear() }) .rotate({ angle: this.rotateAngle }) .animation({ duration:300, curve: Curve.Linear, playMode: PlayMode.Normal }) }.width("100%").justifyContent(FlexAlign.End) } .width("100%") .height(72) //Small card, medium card Flex({direction:FlexDirection.Column,wrap:FlexWrap.Wrap,justifyContent:FlexAlign.Start}){ Column(){ Text("Pinyin:" + this.pinYin).fontSize(14).margin({left:15}) Text("Radical:" + this.buShou).fontSize(14).margin({top:4,left:15}) Text("Stroke:" + this.biHua).fontSize(14).margin({top:4,left:15}) Text("Traditional Chinese:" + this.fanTi).fontSize(14).margin({top:4,left:15}) }.width(208) .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Start) Column(){ Text("Synonyms:" + this.near_words).fontSize(12).margin({right:15}) Text("Antonyms:" + this.reverse_words).fontSize(12).margin({top:4,right:15}) } .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Start) } .width("100%") .height(102) //Big card Column(){ Text("Explanation:").width("100%").textAlign(TextAlign.Start).fontSize(12).margin({left:15,right:15}) Text(this.explain).fontSize(14).margin({top:4,left:15,right:15}) }.width("100%") .height("100%") .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Start) } .width("100%") .alignItems(HorizontalAlign.Center) .backgroundImage("/common/images/cywz.jpg") .backgroundImageSize(ImageSize.Cover) .onClick(() => { postCardAction(this, { "action": this.ACTION_TYPE, "abilityName": this.ABILITY_NAME, "params": { "message": this.MESSAGE, } }); }) ... </code>Copy
5. Project Operation
6. Conclusion
Interested developers can click to enter the official website of Yuan Service to learn more about Yuan Service and Universal Card related information. You can also experience the meta-service – Idiom Mood, which the author and team of this article have launched and operated on the negative screen of Huawei mobile phones and the meta-service area of Huawei App Market. Use universal cards to refresh idioms according to your mood.
Click to enter Huawei’s official website to unlock more exciting content