鸿蒙next高仿微信来了
2024-08-15 本文已影响0人
xq9527
前言导读
各位同学大家,有段时间没有跟大家见面了,因为最近一直在更新鸿蒙的那个实战课程所以就没有去更新文章实在是不好意思, 所以今天就给大家更新一期实战案例 高仿微信案例 希望帮助到各位同学工作和学习
效果图
![](https://img.haomeiwen.com/i6865547/891c6a34dd44f71f.png)
![](https://img.haomeiwen.com/i6865547/d11f69fb25de205a.png)
![](https://img.haomeiwen.com/i6865547/96d9be5639936714.png)
![](https://img.haomeiwen.com/i6865547/7ac8f968c48d7a4f.png)
![](https://img.haomeiwen.com/i6865547/14c81061b7745a1b.png)
![](https://img.haomeiwen.com/i6865547/a6ff0aae14c5169a.png)
特点
- 高仿程度80
- 目前不支持即时通讯功能
- 支持最新的api 12
- 目前做了账号注册和登录自动登录功能入口
具体实现
-
启动页面
/**
* 创建人:xuqing
* 创建时间:2024年7月14日22:56:15
* 类说明:欢迎页面
*
*/
import router from '@ohos.router';
import { preferences } from '@kit.ArkData';
import CommonConstant from '../common/CommonConstants';
import Logger from '../utils/Logger';
import { httpRequestGet } from '../utils/OkhttpUtils';
import { LoginModel } from '../bean/LoginModel';
let dataPreferences: preferences.Preferences | null = null;
@Entry
@Component
struct Welcome {
async aboutToAppear(){
let options: preferences.Options = { name: 'myStore' };
dataPreferences = preferences.getPreferencesSync(getContext(), options);
let getusername=dataPreferences.getSync('username','');
let getpassword=dataPreferences.getSync('password','');
if(getusername===''||getpassword===''){
router.pushUrl({
url:'pages/LoginPage'
})
}else {
let username:string='username=';
let password:string='&password=';
let netloginurl=CommonConstant.LOGIN+username+getusername+password+getpassword;
httpRequestGet(netloginurl).then((data)=>{
Logger.error("请求数据--->"+ data.toString());
let loginmodel:LoginModel=JSON.parse(data.toString());
if(loginmodel.code===200){
router.pushUrl({
url:'pages/Index'
})
}else{
router.pushUrl({
url:'pages/LoginPage'
})
}
})
}
}
build() {
RelativeContainer(){
Image($r('app.media.weixinbg'))
.width('100%')
.height('100%')
}.height('100%')
.width('100%')
.backgroundColor(Color.Green)
}
}
登录页面
import CommonConstant, * as commonConst from '../common/CommonConstants';
import Logger from '../utils/Logger';
import { httpRequestGet } from '../utils/OkhttpUtils';
import { LoginData, LoginModel} from '../bean/LoginModel';
import prompt from '@ohos.promptAction';
import router from '@ohos.router';
import { preferences } from '@kit.ArkData';
let dataPreferences: preferences.Preferences | null = null;
/**
* 创建人:xuqing
* 创建时间:2024年7月14日17:00:03
* 类说明:登录页面
*
*/
//输入框样式
@Extend(TextInput) function inputStyle(){
.placeholderColor($r('app.color.placeholder_color'))
.height(45)
.fontSize(18)
.backgroundColor($r('app.color.background'))
.width('100%')
.padding({left:0})
.margin({top:12})
}
//线条样式
@Extend(Line) function lineStyle(){
.width('100%')
.height(1)
.backgroundColor($r('app.color.line_color'))
}
//黑色字体样式
@Extend(Text) function blackTextStyle(size?:number ,height?:number){
.fontColor($r('app.color.black_text_color'))
.fontSize(18)
.fontWeight(FontWeight.Medium)
}
@Entry
@Component
struct LoginPage {
@State accout:string='';
@State password:string='';
async login(){
let username:string='username=';
let password:string='&password=';
let netloginurl=CommonConstant.LOGIN+username+this.accout+password+this.password;
Logger.error("请求url"+netloginurl);
await httpRequestGet(netloginurl).then((data)=>{
Logger.error("请求结果"+data.toString());
let loginModel:LoginModel=JSON.parse(data.toString());
let msg=loginModel.msg;
let logindata:LoginData=loginModel.user;
let token=loginModel.token;
let userid=logindata.id;
let options: preferences.Options = { name: 'myStore' };
dataPreferences = preferences.getPreferencesSync(getContext(), options);
if(loginModel.code===200){
Logger.error("登录成功");
dataPreferences.putSync('token',token);
dataPreferences.putSync('id',userid);
dataPreferences.putSync('username',this.accout);
dataPreferences.putSync('password',this.password);
dataPreferences!!.flush()
router.pushUrl({
url:'pages/Index'
})
}else {
prompt.showToast({
message:msg
})
}
})
}
build() {
Column(){
Image($r('app.media.weixinicon'))
.width(48)
.height(48)
.margin({top:100,bottom:8})
.borderRadius(8)
Text('登录界面')
.fontSize(24)
.fontWeight(FontWeight.Medium)
.fontColor($r('app.color.title_text_color'))
Text('登录账号以使用更多服务')
.fontSize(16)
.fontColor($r('app.color.login_more_text_color'))
.margin({bottom:30,top:8})
Row(){
Text('账号').blackTextStyle()
TextInput({placeholder:'请输入账号'})
.maxLength(12)
.type(InputType.Number)
.inputStyle()
.onChange((value:string)=>{
this.accout=value;
}).margin({left:20})
}.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.margin({top:8})
Line().lineStyle().margin({left:80})
Row(){
Text('密码').blackTextStyle()
TextInput({placeholder:'请输入密码'})
.maxLength(12)
.type(InputType.Password)
.inputStyle()
.onChange((value:string)=>{
this.password=value;
}).margin({left:20})
}.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.margin({top:8})
Line().lineStyle().margin({left:80})
Button('登录',{type:ButtonType.Capsule})
.width('90%')
.height(40)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.login_button_color'))
.margin({top:47,bottom:12})
.onClick(()=>{
this.login()
})
Text('注册账号').onClick(()=>{
router.pushUrl({
url:'pages/RegisterPage'
})
}).fontColor($r('app.color.login_blue_text_color'))
.fontSize(12)
.fontWeight(FontWeight.Medium)
}.backgroundColor($r('app.color.background'))
.height('100%')
.width('100%')
.padding({
left:12,
right:12,
bottom:24
})
}
}
-
主页index
import home from './Home/Home'; import contacts from './Contact/Contacts'; import Discover from './Discover/Discover'; import My from './My/My'; import common from '@ohos.app.ability.common'; import prompt from '@ohos.promptAction'; @Entry @Component struct Index { @State message: string = 'Hello World'; private backTime :number=0; @State fontColor: string = '#182451' @State selectedFontColor: string = 'rgb(0,196,104)' private controller:TabsController=new TabsController(); showtoast(msg:string){ prompt.showToast({ message:msg }) } @State SelectPos:number=0; private positionClick(){ this.SelectPos=0; this.controller.changeIndex(0); } private companyClick(){ this.SelectPos=1; this.controller.changeIndex(1); } private messageClick(){ this.SelectPos=2; this.controller.changeIndex(2); } private myClick(){ this.SelectPos=3; this.controller.changeIndex(3); } onBackPress(): boolean | void { let nowtime=Date.now(); if(nowtime-this.backTime<1000){ const mContext=getContext(this) as common.UIAbilityContext; mContext.terminateSelf() }else{ this.backTime=nowtime; this.showtoast("再按一次将退出当前应用") } return true; } // ['微信','通讯录','发现','我'] build() { Flex({direction:FlexDirection.Column,alignItems:ItemAlign.Center,justifyContent:FlexAlign.Center}){ Tabs({controller:this.controller}){ TabContent(){ home(); } TabContent(){ contacts(); } TabContent(){ Discover(); } TabContent(){ My() } }.scrollable(false) .barHeight(0) .animationDuration(0) Row(){ Column(){ Image((this.SelectPos==0?$r('app.media.wetab01'):$r('app.media.wetab00'))) .width(20).height(20) .margin({top:5}) Text('微信') .size({width:'100%',height:30}).textAlign(TextAlign.Center) .fontSize(15) .fontColor((this.SelectPos==0?this.selectedFontColor:this.fontColor)) }.layoutWeight(1) .backgroundColor($r('app.color.gray2')) .height('100%') .onClick(this.positionClick.bind(this)) Column(){ Image((this.SelectPos==1?$r('app.media.wetab11'):$r('app.media.wetab10'))) .width(20).height(20) .margin({top:5}) Text('通讯录') .size({width:'100%',height:30}).textAlign(TextAlign.Center) .fontSize(15) .fontColor((this.SelectPos==1?this.selectedFontColor:this.fontColor)) }.layoutWeight(1) .backgroundColor($r('app.color.gray2')) .height('100%') .onClick(this.companyClick.bind(this)) Column(){ Image((this.SelectPos==2?$r('app.media.wetab21'):$r('app.media.wetab20'))) .width(20).height(20) .margin({top:5}) Text('发现') .size({width:'100%',height:30}).textAlign(TextAlign.Center) .fontSize(15) .fontColor((this.SelectPos==2?this.selectedFontColor:this.fontColor)) }.layoutWeight(1) .backgroundColor($r('app.color.gray2')) .height('100%') .onClick(this.messageClick.bind(this)) Column(){ Image((this.SelectPos==5?$r('app.media.wetab31'):$r('app.media.wetab30'))) .width(20).height(20) .margin({top:5}) Text('我') .size({width:'100%',height:30}).textAlign(TextAlign.Center) .fontSize(15) .fontColor((this.SelectPos==5?this.selectedFontColor:this.fontColor)) }.layoutWeight(1) .backgroundColor($r('app.color.gray2')) .height('100%') .onClick(this.myClick.bind(this)) }.alignItems(VerticalAlign.Bottom).width('100%').height(60).margin({top:0,right:0,bottom:0,left:0}) }.width('100%') .height('100%') } }
后续目标
- 微信朋友圈
- 聊天菜单(相册,拍摄...)组件栏
- 语音|视频页面
- 支持群聊头像
- 支持图片,红包等聊天内容类型(现已支持图片类型)
- 二维码扫描
最后总结:
因为篇幅有限我也不能整个项目都展开讲,有兴趣的同学能可以关注我B站课程。 后续能我会把这个项目更新到项目里面 供大家学习
B站课程地址:https://www.bilibili.com/cheese/play/ss25125
团队介绍
团队介绍:坚果派由坚果等人创建,团队由12位华为HDE以及若干热爱鸿蒙的开发者和其他领域的三十余位万粉博主运营。专注于分享 HarmonyOS/OpenHarmony,ArkUI-X,元服务,仓颉,团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,目前已开发鸿蒙 原生应用,三方库60+,欢迎进行课程,项目等合作。