[ArkUI]Swiper实现滑动切换页面

334 阅读4分钟

在写IM(即时通讯)软件的时候,想模仿微信左右滑动来切换页面,查询HarmonyOS Next的API,发现Swiper可以在组件之间切换,于是采用Swiper这个API去操作,并实现在HarmonyOS NEXT上模仿微信滑动切换页面。

Swiper 组件的功能:

  1. 滑动切换内容: 通过左右滑动来切换不同的页面内容(如 OnlineUserMyPage)。

  2. 指示当前页面: index 属性决定当前显示的页面索引。

  3. 交互响应: 通过 onChange 事件监听滑动切换时的页面索引变化。

  4. 外观与行为:

    • loop(false) 表示滑动不会循环(滑动到最后一页后不能返回第一页)。
    • indicator(false) 表示不显示页面指示器(通常是小圆点)。

Swiper 组件的代码解析:

1. 声明与页面内容:

Swiper(){
  OnlineUser()
  MyPage()
}

  • Swiper 内部放置了两个子组件 OnlineUserMyPage,表示滑动页面的两个内容部分。
  • 每滑动一次,显示一个子组件的内容。

2. 事件监听:

.onChange((index: number) => {
  this.currentPage = index
})

  • onChange 是一个事件处理器,监听 Swiper 的页面切换事件。
  • 当用户滑动页面时,onChange 会被触发,参数 index 是滑动到的新页面索引。
  • 更新 currentPage 的值,使其他组件能够感知当前页面的变化。

3. 初始页面索引:

.index(this.currentPage)

  • index 属性设置 Swiper 当前显示的页面索引。
  • 初始值通过 @ConsumecurrentPage 获取,可以与其他组件共享。

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")
  }
}