diff --git a/README.md b/README.md index ff5fb8091346fa78a8044ef02826253c067034c5..ea87e994348acf356dcc07b8fcc72caf6afb4fe3 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,30 @@ -基于ArkUI开发的一款鸿蒙OS应用,调用开放API[玩android](https://www.wanandroid.com/),实现了简单的页面导航,登录,登录状态保存,数据展示,h5页面加载等功能. +# wanandroid_flutter -![Screenshot_2024-04-28T095223.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ed15382e894c4924b8b2dea9437dd522~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=944&h=2038&s=554827&e=png&b=fcfcfc) +这是一个基于 ArkUI 开发的鸿蒙 OS 应用,调用了开放 API [玩 Android](https://www.wanandroid.com/),实现了简单的页面导航、登录、登录状态保存、数据展示和 H5 页面加载等功能。 -![Screenshot_2024-04-28T095315.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1c8403fb3a74ee1a66bb17fda579524~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=944&h=2038&s=340960&e=png&b=fbfbfb) +## 功能特性 -![Screenshot_2024-04-28T095326.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c4ca24f5c138479086dcdcecc4929061~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=944&h=2038&s=698040&e=png&b=fcfcfc) +- **页面导航**:使用 `Tabs` 实现底部和顶部导航栏,轻松切换不同页面。 +- **登录功能**:用户可以登录并保持登录状态。 +- **数据展示**:通过调用 WanAndroid API 展示文章列表、项目和体系内容。 +- **下拉刷新与上拉加载**:支持下拉刷新和上拉加载更多数据。 +- **H5 页面加载**:支持加载 H5 页面内容。 + +## 主要组件 -![Screenshot_2024-04-28T095337.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fbc15436b91a4d26b31f999e5324c1f8~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=944&h=2038&s=246824&e=png&b=ffffff) ### 首页底部导航栏 -使用Tabs实现底部导航,Tabs组件的页面组成包含两个部分,分别是TabContent和TabBar。TabContent是内容页,TabBar是导航页签栏。每一个TabContent对应的内容需要有一个页签,可以通过TabContent的tabBar属性进行配置。 + +使用 `Tabs` 实现底部导航,包含首页、体系、项目和我的四个页面。 ```ts Tabs({ barPosition: BarPosition.End }) { TabContent() { HomeComponent() - }.align(Alignment.Top) - .tabBar(this.tabBuilder("首页", 0, $r("app.media.main_index_select_icon"), $r("app.media.main_index_icon"))) + }.tabBar(this.tabBuilder("首页", 0, $r("app.media.main_index_select_icon"), $r("app.media.main_index_icon"))) TabContent() { SystemComponent() - }.align(Alignment.Top) - .tabBar(this.tabBuilder("体系", 1, $r("app.media.main_house_select_icon"), $r("app.media.main_house_icon"))) + }.tabBar(this.tabBuilder("体系", 1, $r("app.media.main_house_select_icon"), $r("app.media.main_house_icon"))) TabContent() { ProjectComponent() @@ -28,72 +32,56 @@ Tabs({ barPosition: BarPosition.End }) { TabContent() { MyComponent() - }.align(Alignment.Top) - .tabBar(this.tabBuilder("我的", 3, $r("app.media.main_me_select_icon"), $r("app.media.main_me_icon"))) -}.scrollable(false) -.divider({ strokeWidth: 0.3 }) -.animationDuration(0) -.onChange((index) => { + }.tabBar(this.tabBuilder("我的", 3, $r("app.media.main_me_select_icon"), $r("app.media.main_me_icon"))) +}.onChange((index) => { this.currentIndex = index }) ``` -barPosition控制导航栏位置,BarPosition.Start表示顶部导航栏和BarPosition.End表示低部导航栏; -divider可以定义导航栏分割线样式;animationDuration设置导航页main切换动画时长;onChange导航页面切换监听。 - -HomeComponent,SystemComponent,ProjectComponent,MyComponent分别是自定义的4个页面组件。切换导航可以切换到对应的页面。 ### 主页自定义组件(HomeComponent) -主页HomeComponent由轮播图Swiper组件和列表组件组成,用来显示文章列表,外面嵌套了一个下拉刷新组件PullToRefresh,大概结构是这样的 +主页由轮播图和文章列表组成,支持下拉刷新和上拉加载。 ```ts -下拉刷新/上拉加载 PullToRefresh({ data: this.articleList, scroller: this.scroller, onRefresh: () => { - //刷新执行回调 + // 刷新执行回调 }, onLoadMore: () => { - //加载更多执行回调 + // 加载更多执行回调 }, customList: () => { - //刷新页面内容 Scroll(this.scroller) { - Column(){ - //轮播图 - Swiper(){} - //文章列表 - ForEach(this.articleList, (item: ArticleData) => { - ArticleListItem({ article: item }) - }) - } + Column() { + Swiper() { + // 轮播图内容 + } + ForEach(this.articleList, (item: ArticleData) => { + ArticleListItem({ article: item }) + }) + } } + } }) ``` -刷新组件使用的三方库[@ohos/pulltorefresh](https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Fpulltorefresh),刷新组件子组件必须是滑动组件,这里由于页面由轮播图和列表组件,所以在外层嵌套了一个Scroll组件,保证页面运行正常,SystemComponent是一个自定义组件内构造函数@Builder,可以将重复使用的UI元素抽象成⼀个方法,这里用来展示列表每项布局。 - -Tips:Scroll组件和PullToRefresh需要共用一个控制器Scroller。 ### 体系自定义组件(SystemComponent) -体系页面由顶部Tabs嵌套Grid和下拉刷新pulltorefresh列表组成,Grid组件是系统提供的用来展示宫格的组件, -页面结构如下: +体系页面由顶部 Tabs 嵌套 Grid 和下拉刷新列表组成。 ```ts -//顶部导航栏 -Tabs({ barPosition: BarPosition.Start }){ - TabContent(){ - Column(){ - //顶部宫格组件 - Grid(){} - //下拉刷新组件 +Tabs({ barPosition: BarPosition.Start }) { + TabContent() { + Column() { + Grid() { + // 宫格内容 + } PullToRefresh({ customList: () => { - //滑动组件 - Scroll(){ - Column(){ - //文章列表item项 + Scroll() { + Column() { ArticleListItem() } } @@ -103,37 +91,35 @@ Tabs({ barPosition: BarPosition.Start }){ } } ``` -此页面导航栏下方嵌套宫格组件,宫格组件下方使用下拉刷新组件嵌套列表展示。切换导航,调用接口刷新宫格和列表数据,选择宫格组件页会刷新列表数据。 + ### 项目自定义组件(ProjectComponent) -项目页面由Tabs直接嵌套下拉刷新组件,下拉刷新组件嵌套Grid宫格组件组成,页面结构如下: -```ArkTs -//顶部导航栏 -Tabs({ barPosition: BarPosition.Start }){ - TabContent(){ - //下拉刷新组件 - PullToRefresh({ - customList: () => { - Grid(this.scroller) { - ForEach(this.projectList, (item: ArticleData) => { - GridItem() { - //宫格item样式 - } - }) - } - .columnsTemplate("1fr 1fr") - .width("95%") - .columnsGap(10) - .scrollBar(BarState.Off) - .padding(1) +项目页面由 Tabs 直接嵌套下拉刷新组件和 Grid 宫格组成。 + +```ts +Tabs({ barPosition: BarPosition.Start }) { + TabContent() { + PullToRefresh({ + customList: () => { + Grid(this.scroller) { + ForEach(this.projectList, (item: ArticleData) => { + GridItem() { + // 宫格 item 样式 + } + }) } - }) - } + .columnsTemplate("1fr 1fr") + .columnsGap(10) + } + }) + } } ``` -columnsTemplate方法可以设置宫格的列数,一个1fr代表1列,columnsGap设置列表间距,scrollBar设置进度条样式。 -### 网络请求@ohos/axios -网络请求使用了[@ohos/axios](https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Faxios)三方库,简单封装了下: + +### 网络请求 + +使用 `@ohos/axios` 进行网络请求,并进行了简单的封装。 + ```ts export class HttpUtils { private static instance: HttpUtils = new HttpUtils() @@ -143,44 +129,52 @@ export class HttpUtils { this.axiosInstance = axios.create({ baseURL: 'https://www.wanandroid.com/', timeout: 10 * 1000, - //设置全局请求头 - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - //设置代理 - // proxy: { host: "192.168.10.229", port: 8888, exclusionList: [] } + headers: { "Content-Type": "application/x-www-form-urlencoded" } }); - - //拦截请求数据处理一些业务逻辑,比如添加cookie到请求中 + this.axiosInstance.interceptors.request.use(async (config: InternalAxiosRequestConfig) => { if (config.url != WanAndroidUrl.Login) { - //如果不是登录接口,则需要添加cookie到请求头中 const cookies = await PFUtils.get("cookies").then() config.headers["Cookie"] = cookies } - console.log("请求数据:", JSON.stringify(config.headers)) return config; }); - - //拦截响应数据,处理一些业务逻辑,比如cookie保存 - this.axiosInstance.interceptors.response.use((response: AxiosResponse) => { - console.log("响应数据:", response.config.url) - console.log("响应数据:", JSON.stringify(response.data)) + this.axiosInstance.interceptors.response.use((response: AxiosResponse) => { if (response.config.url == WanAndroidUrl.Login) { - //如果是登录接口,则需要你保存cookie const cookies = response.headers["set-cookie"] as string[] - //保存cookie到缓存中 PFUtils.put("cookies", cookies.toString()) - //保存登录状态 PFUtils.put("LoginState", true) - //通知其他页面用户登录成功 emitter.emit({ eventId: Constant.USER_LOGIN }) } - return response; }, (error: AxiosError) => { - // 对响应错误做点什么 console.log("请求错误数据:", JSON.stringify(error)) }); } } ``` + +## 截图 + +![Screenshot_2024-04-28T095223.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ed15382e894c4924b8b2dea9437dd522~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=944&h=2038&s=554827&e=png&b=fcfcfc) + +![Screenshot_2024-04-28T095315.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1c8403fb3a74ee1a66bb17fda579524~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=944&h=2038&s=340960&e=png&b=fbfbfb) + +![Screenshot_2024-04-28T095326.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c4ca24f5c138479086dcdcecc4929061~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=944&h=2038&s=698040&e=png&b=fcfcfc) + +![Screenshot_2024-04-28T095337.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fbc15436b91a4d26b31f999e5324c1f8~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=944&h=2038&s=246824&e=png&b=ffffff) + +## 贡献 + +欢迎贡献代码和报告问题!请遵循以下步骤: + +1. Fork 仓库 +2. 创建新分支 (`git checkout -b feature/fooBar`) +3. 提交更改 (`git commit -am 'Add some fooBar'`) +4. 推送分支 (`git push origin feature/fooBar`) +5. 创建新的 Pull Request + +## 许可证 + +本项目使用 MIT 许可证。详情请查看 [LICENSE](LICENSE) 文件。 \ No newline at end of file