在写IM(即时通讯)软件的时候,想模仿微信左右滑动来切换页面,查询HarmonyOS Next的API,发现Swiper可以在组件之间切换,于是采用Swiper这个API去操作,并实现在HarmonyOS NEXT上模仿微信滑动切换页面。
Swiper 组件的功能:
-
滑动切换内容: 通过左右滑动来切换不同的页面内容(如
OnlineUser和MyPage)。 -
指示当前页面:
index属性决定当前显示的页面索引。 -
交互响应: 通过
onChange事件监听滑动切换时的页面索引变化。 -
外观与行为:
loop(false)表示滑动不会循环(滑动到最后一页后不能返回第一页)。indicator(false)表示不显示页面指示器(通常是小圆点)。
Swiper 组件的代码解析:
1. 声明与页面内容:
Swiper(){
OnlineUser()
MyPage()
}
Swiper内部放置了两个子组件OnlineUser和MyPage,表示滑动页面的两个内容部分。- 每滑动一次,显示一个子组件的内容。
2. 事件监听:
.onChange((index: number) => {
this.currentPage = index
})
onChange是一个事件处理器,监听Swiper的页面切换事件。- 当用户滑动页面时,
onChange会被触发,参数index是滑动到的新页面索引。 - 更新
currentPage的值,使其他组件能够感知当前页面的变化。
3. 初始页面索引:
.index(this.currentPage)
index属性设置Swiper当前显示的页面索引。- 初始值通过
@Consume的currentPage获取,可以与其他组件共享。
4. 视觉样式控制:
.width('100%')
.height('90%')
.loop(false)
.indicator(false)
width('100%')和height('90%')设置Swiper的宽度和高度,决定了滑动区域的大小。loop(false)禁止循环滑动,滑动到最后一个页面时无法再滑动到第一个页面。indicator(false)隐藏页面指示器,界面更简洁。
实际效果:
Swiper的滑动功能为用户提供了一个顺滑的页面切换体验,适合用于主页面内容的分屏展示。- 例如,用户可以在 "在线用户" 和 "我的" 页面之间滑动切换,同时底部导航与之联动。
编辑
代码:
//HomePage.ets
import { HomeBottomItem } from '../components/HomeBottomItem'
import { Title } from '../components/Title'
import { initWebSocket } from '../utils/WebSocket'
import { MyPage } from './MyPage'
import { OnlineUser } from './OnlineUser'
@Entry
@Component
struct HomePage {
@Provide currentPage: number = 0
onPageShow(): void {
initWebSocket();
}
build() {
Column(){
Column(){
Title({text:"GCC-IM-DEMO"})
Divider()
.color("#FF007DFF")
HomeTopPage()
}
.width('100%')
.flexGrow(1)
HomeBottomPage()
}
}
}
@Component
struct HomeTopPage {
@Consume currentPage: number
build() {
Swiper(){
OnlineUser()
MyPage()
}
.onChange((index: number) => {
this.currentPage = index
})
.index(this.currentPage)
.loop(false)
.indicator(false)
.width('100%')
.height('90%')
}
}
@Component
struct HomeBottomPage {
@Consume currentPage: number
build() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
HomeBottomItem({
text: "在线用户",
})
Text().margin({ left: 110 })
HomeBottomItem({
text: "我的",
})
}
.backgroundColor("#f7f7f7")
.width('100%')
.height('160px')
}
}
//MyPage.ets
import { logout } from "../utils/Request";
import router from "@ohos.router";
import { AxiosResponse } from "@ohos/axios";
import { promptAction } from "@kit.ArkUI";
@Entry
@Component
export struct MyPage {
username:string = AppStorage.get("username") as string
userId:string = AppStorage.get("userId") as string
async logoutHandle(userId: string) {
try {
const res: AxiosResponse = await logout(userId);
if (res.status === 200) {
// 先清除存储
AppStorage.clear();
router.clear();
router.pushUrl({
url: "pages/Index"
});
promptAction.showToast({
message: "登出成功",
duration: 2000
});
} else {
promptAction.showToast({
message: "退出失败",
duration: 2000
});
}
} catch (error) {
console.error("退出错误: ", error);
promptAction.showToast({
message: "网络异常,请重试",
duration: 2000
});
}
}
build() {
Column() {
// 头像和用户名部分
Row() {
Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text(this.username.charAt(0))
.fontSize(20)
.fontColor("#fff")
.fontWeight(FontWeight.Bold);
}
.width(50)
.height(50)
.borderRadius(25)
.backgroundColor("#1296db")
.margin({ left: 15, right: 15 });
Column() {
Text(this.username)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor("#333")
.margin({ bottom: 5 });
Text("用户ID: " + this.userId)
.fontSize(14)
.fontColor("#888");
};
}
.width("100%")
.height(85)
.padding({ top: 15, bottom: 15 })
.backgroundColor("#fff");
Divider()
.strokeWidth(1)
// 功能区域
Scroll() {
Column() {
}.width("100%");
} // 自动填充剩余空间
Blank()
// 底部登出按钮
Row() {
Button("登出")
.backgroundColor(Color.Red)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor("#fff")
.onClick(() => {
this.logoutHandle(this.userId);
})
.width("90%")
.height(50)
.borderRadius(10)
.margin({ top: 10, bottom: 20 })
.align(Alignment.Center);
}
.height(60)
.backgroundColor("#fff");
}
.width("100%")
.height("100%")
.backgroundColor("#f5f5f5");
}
}
//OnlineUser.ets
import { UserItem } from '../components/UserItem';
import { OnlineUsers } from '../model/User';
import router from '@ohos.router';
import { getOnlineRequest } from '../utils/Request';
import { AxiosError, AxiosResponse } from '@ohos/axios';
@Entry
@Component
export struct OnlineUser {
userId: string = AppStorage.get("userId") || '';
@State userList: OnlineUsers[] = [];
aboutToAppear(): void {
// 定时同步在线用户列表
this.updateOnlineUsers();
setInterval(this.updateOnlineUsers.bind(this), 4000);
}
updateOnlineUsers(): void {
getOnlineRequest(this.userId).then((res: AxiosResponse) => {
if (res.status === 200) {
this.userList = res.data;
} else {
console.error("在线用户列表更新失败: " + JSON.stringify(res));
}
}).catch((err:AxiosError) => {
console.error("请求失败: ", err)
})
}
build() {
Column() {
Scroll() {
Column() {
if (this.userList.length === 0) {
Text("暂无用户在线")
.fontColor("#888")
.fontSize(16)
.align(Alignment.Center);
} else {
List() {
ForEach(this.userList, (item: OnlineUsers) => {
ListItem() {
UserItem({ text: item.username });
}.onClick(() => {
router.pushUrl({
url: "pages/ChatPage",
params: {
userId1: this.userId,
username: item.username,
userId2: item.userId,
isExist: false
}
});
});
});
}
}
}
}
}.alignItems(HorizontalAlign.Start)
.width('100%')
.height('100%')
.backgroundColor("#E8E8E8")
}
}