回复
#HarmonyOS NEXT体验官# 体验HarmonyOS开发流程,开发一个简单图册展示app(一) 原创
RandomBoolean
发布于 2024-7-27 17:15
浏览
0收藏
登录页面
设计一个简单的登录页面,包含logo、文字名称、手机输入框、验证码输入框、发送验证码按钮、登录按钮。这是一个页面包含的元素。 要实现的效果如图片所示。
以下是UI层的布局。
可以看到app.media还有app.float等变量,这些是定义在float.json文件的公共变量。可以写死也可以使用变量来进行定义使用。
如下在第一个Image和第一个Text组件没有使用变量定义属性,可以作为参考使用。$r(‘app.media.huihua’)为图片的路径,这里可以使用自己的图片。
build() {
Column() {
Image($r('app.media.huihua'))
.width('78vp')
.height('78vp')
.margin({ top: '100vp', bottom: '8vp' })
Text('彩绘工坊')
.fontSize('24vp')
.fontWeight(FontWeight.Medium)
.fontColor('#182431')
Text($r('app.string.login_more'))
.fontSize($r('app.float.normal_text_size'))
.fontColor($r('app.color.login_more_text_color'))
.margin({ bottom: $r('app.float.login_more_margin_bottom'), top: $r('app.float.login_more_margin_top') })
TextInput({ placeholder: $r('app.string.account') })
.maxLength(CommonConstants.INPUT_ACCOUNT_LENGTH)
.type(InputType.Number)
.inputStyle()
.onChange((value: string) => {
this.account = value;
})
Line().lineStyle()
Flex({ alignItems: ItemAlign.Center }) {
TextInput({ placeholder: '验证码' })
.type(InputType.Number)
.inputStyle()
.onChange((value: string) => {
this.code = value;
})
Button(this.isSendSms ? this.sendText : '获取验证码')
.onClick(() => {
this.sendSms()
})
// .width('20vp')
}
Line().lineStyle()
Button($r('app.string.login'), { type: ButtonType.Capsule })
.width(CommonConstants.BUTTON_WIDTH)
.height($r('app.float.login_button_height'))
.fontSize($r('app.float.normal_text_size'))
.fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.login_button_color'))
.margin({ top: $r('app.float.login_button_margin_top'), bottom: $r('app.float.login_button_margin_bottom') })
.clickEffect({
level: ClickEffectLevel.MIDDLE,
scale: 0.8
})
.onClick(() => {
this.login();
})
if (this.isShowProgress) {
LoadingProgress()
.color($r('app.color.loading_color'))
.width($r('app.float.login_progress_size'))
.height($r('app.float.login_progress_size'))
.margin({ top: $r('app.float.login_progress_margin_top') })
}
Blank()
}
.backgroundColor($r('app.color.background'))
.height(CommonConstants.FULL_PARENT)
.width(CommonConstants.FULL_PARENT)
.padding({
left: $r('app.float.page_padding_hor'),
right: $r('app.float.page_padding_hor'),
bottom: $r('app.float.login_page_padding_bottom')
})
}
创建公共变量
接下来是在如下的路径中创建一个公共变量CommonConstants文件
文件内代码如下
export default class CommonConstants {
/*
* 接口地址
* */
static readonly API_URL = 'https://fc-mp-fd1357e1-2f29-4c06-a2a0-ce40a5f54704.next.bspapp.com';
/**
* Input length of the account.
*/
static readonly INPUT_ACCOUNT_LENGTH = 11;
/**
* Input length of the password.
*/
static readonly INPUT_PASSWORD_LENGTH = 8;
/**
* Left padding of the input box
*/
static readonly INPUT_PADDING_LEFT = 0;
/**
* Delay time of simulated login
*/
static readonly LOGIN_DELAY_TIME = 2000;
/**
* Common Spacing of Components
*/
static readonly COMMON_SPACE = 12;
/**
* Title text of the home page
*/
static readonly HOME_TITLE = '首页';
/**
* Title text of the setting page
*/
static readonly MINE_TITLE = '我的';
/**
* Spacing of other login methods
*/
static readonly LOGIN_METHODS_SPACE = 44;
/**
* The width or height of the component is spread across the parent component.
*/
static readonly FULL_PARENT = '100%';
/**
* The width of button
*/
static readonly BUTTON_WIDTH = '90%';
/**
* The width of setting list
*/
static readonly SET_LIST_WIDTH = '45%';
/**
* Home tab index
*/
static readonly HOME_TAB_INDEX = 0;
/**
* Mine tab index
*/
static readonly MINE_TAB_INDEX = 1;
/**
* Component opacity value: 1.
*/
static readonly FULL_OPACITY: number = 1;
/**
* Component opacity value: 0.6.
*/
static readonly SIXTY_OPACITY: number = 0.6;
/**
* Component opacity value: 0.8.
*/
static readonly EIGHTY_OPACITY: number = 0.8;
/**
* Font weight value: five.
*/
static readonly FONT_WEIGHT_FIVE: number = 500;
/**
* Water flow layout weight value:1.
*/
static readonly WATER_FLOW_LAYOUT_WEIGHT: number = 1;
/**
* Water flow layout columns template.
*/
static readonly WATER_FLOW_COLUMNS_TEMPLATE: string = '1fr 1fr';
/**
* Width the percentage of the 100.
*/
static readonly FULL_WIDTH: string = '100%';
/**
* Height the percentage of the 100.
*/
static readonly FULL_HEIGHT: string = '100%';
/**
* Invalid Index.
*/
static readonly INVALID_INDEX: number = -1;
}
接着在utils目录中定义一个数据缓存的公共方法preferences
该方法用到了dataPreferences数据持久化
import dataPreferences from '@ohos.data.preferences';
import { ValueType } from '@kit.ArkData';
class Preferences {
private options: dataPreferences.Options;
private preferences: dataPreferences.Preferences | null = null;
constructor(name: string) {
this.options = {
name
}
this.preferences = dataPreferences.getPreferencesSync(getContext(), this.options)
}
get(key: string, defValue: ValueType) {
return this.preferences?.getSync(key, defValue);
}
getObj(key: string): ESObject {
const data = this.preferences?.getSync(key, '').toString()
return data ? JSON.parse(data) : {}
}
put(key: string, value: ESObject) {
return this.preferences?.putSync(key, value)
}
putObj(key: string, value: ESObject) {
let str = ''
if (value) {
str = JSON.stringify(value)
}
return this.preferences?.putSync(key, str)
}
hasSync(key: string) {
return this.preferences?.hasSync(key);
}
deleteSync(key: string) {
return this.preferences?.deleteSync(key)
}
}
export default Preferences
最后一项准备工作是定义一个接口请求方法,因篇幅限制这里暂时不做赘述。最后来看一下登录页面所包含的方法
import { promptAction, router } from '@kit.ArkUI';
import CommonConstants from '../common/constants/CommonConstants';
import Preferences from '../common/utils/preferences';
import LoginViewModel from '../viewmodel/LoginViewModel'
@Extend(TextInput)
function inputStyle() {
.placeholderColor($r('app.color.placeholder_color'))
.height($r('app.float.login_input_height'))
.fontSize($r('app.float.big_text_size'))
.backgroundColor($r('app.color.background'))
.width(CommonConstants.FULL_PARENT)
.padding({ left: CommonConstants.INPUT_PADDING_LEFT })
.margin({ top: $r('app.float.input_margin_top') })
}
@Extend(Line)
function lineStyle() {
.width(CommonConstants.FULL_PARENT)
.height($r('app.float.line_height'))
.backgroundColor($r('app.color.line_color'))
}
@Extend(Text)
function blueTextStyle() {
.fontColor($r('app.color.login_blue_text_color'))
.fontSize($r('app.float.small_text_size'))
.fontWeight(FontWeight.Medium)
}
/**
* Login page
*/
@Entry
@Component
export default struct LoginPage {
@State account: string = '';
@State code: string = '';
@State isShowProgress: boolean = false;
@State isSendSms: boolean = false;
@State second: number = 60
@State sendText: string = `${this.second}秒后再次获取验证码`
private timeOutId: number = -1;
private sendSmsInterval: number = -1
private preferences = new Preferences('app_db')
aboutToAppear(): void {
if (this.preferences.getObj('userInfo').token) {
router.replaceUrl({ url: 'pages/MainPage' });
}
}
@Builder
imageButton(src: Resource) {
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image(src)
}
.height($r('app.float.other_login_image_size'))
.width($r('app.float.other_login_image_size'))
.backgroundColor($r('app.color.background'))
}
login(): void {
if (!this.isValidate()) {
return
}
if (this.code === '') {
promptAction.showToast({
message: '请填写验证码'
})
return
}
this.isShowProgress = true;
LoginViewModel.login(this.account, this.code).then((res: ESObject) => {
this.isShowProgress = false;
if (res.code === 200) {
this.preferences.putObj('userInfo', res.data)
router.replaceUrl({ url: 'pages/MainPage' });
}
})
}
sendSms(): void {
if (this.isSendSms) {
promptAction.showToast({
message: this.sendText
})
return
}
if (this.isValidate()) {
LoginViewModel.getCode(this.account).then((res: ESObject) => {
console.log(JSON.stringify(res.data))
if (res.code === 200) {
promptAction.showToast({
message: '发送验证码'
})
this.isSendSms = true
this.sendSmsInterval = setInterval(() => {
if (this.second <= 0) {
this.isSendSms = false
this.second = 60
clearInterval(this.sendSmsInterval)
}
this.second--
this.sendText = `${this.second}秒后再次获取验证码`
}, 1000)
}
})
}
}
/*
* 验证方法
* */
isValidate(): boolean {
if (!this.account) {
promptAction.showToast({
message: '请填写手机号'
})
return false
}
const rex = /^[1][3,4,5,6.7,8,9][0-9]{9}$/
if (!rex.test(this.account)) {
promptAction.showToast({
message: '手机号格式错误'
})
return false
}
// if (!this.code) {
// promptAction.showToast({
// message: '请填写验证码'
// })
// return false
// }
return true
}
aboutToDisappear() {
clearTimeout(this.timeOutId);
this.timeOutId = -1;
clearInterval(this.sendSmsInterval)
this.sendSmsInterval = -1
}
build() {...这里是上方的ui层 }
}
其中import LoginViewModel from '../viewmodel/LoginViewModel'
为导入的接口请求,可以使用settimeout作为模拟登录接口。
输入正确的手机号,点击“获取验证码”按钮执行sendSms方法进行验证,通过之后发送验证码,按钮进入倒计时状态。
输入验证码之后,点击登录,调用接口获取到用户信息,存储到缓存中登录完成。
下一篇文章将介绍首页瀑布流列表和相册图片的展示。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
已于2024-7-27 18:11:49修改
赞
收藏
回复
相关推荐