本篇涉及组件TextInput、Image、Menu、Swiper、Web、自定义组件、路由跳转传参、POST请求
1.首页横幅
Swiper组件内部需要放其他内容组件,且需要设置宽高100%。
Image显示网络图片,直接设置图片链接即可。
Swiper(){
ForEach(this.bannerData,(data:Datum,index:number)=>{
Image(data.imagePath)
.width('100%')
.height('100%')
.onClick(()=>{
console.log("Swiper onClick link "+data.url)
router.pushUrl({
url:"pages/WebPage",
params:{data:data.url}
})
})
})
}
.width('100%')
.height(150)
2.搜索框
placeholder是提示词,text就是输入框已存在的内容,通过onChange监听输入内容。
然后同步bindMenu添加菜单,为了做搜索热词功能
TextInput({placeholder:"输入搜索关键词",text:this.searchContent})
.width(270)
.height(40)
.margin({top:10,bottom:10})
.backgroundColor(Color.White)
.bindMenu(
this.searchKey()
)
.onChange((value: string) => {
this.searchContent = value;
})
@Builder
searchKey(){
Menu(){
ForEach(this.searchKeyData,(data:SearchKeyDataBean,index:number)=>{
MenuItem({"content":data.name})
.onClick(()=>{
this.searchContent = data.name
})
})
}
}
输入完后,点击按钮确认搜索,跳转到搜索页。
Button("搜索")
.margin({left:10,right:10})
.onClick(()=>{
console.log("searchContent "+this.searchContent)
router.pushUrl({
url:"pages/SearchListPage",
params:{data:this.searchContent}
})
})
3.搜索页
搜索页内容就是一个列表,和首页一样,区别是获取搜索列表是通过POST请求,需要在method指定post请求,且在extraData写入post传参
let httpRequest = http.createHttp();
httpRequest.request("https://www.wanandroid.com/article/query/"+this.page+"/json", {method: http.RequestMethod.POST,extraData: "k="+this.searchKey,}, (err, data) => {
if (!err) {
console.log("SearchListPage data.result:"+data.result.toString())
let welcome: Welcome = JSON.parse(data.result.toString());
if(welcome && welcome.data && welcome.data.datas && welcome.data.datas.length > 0){
this.dataList = this.dataList.concat(welcome.data.datas)
this.page++;
}
} else {
}
this.state = RequestState.END;
})
4.列表和横幅都能点击跳转到网页
使用Web组件,传网址给src,controller创建一个默认的即可
Web({
src: this.url,
controller: this.webviewController
})
然后写一个标题栏能返回,能标题栏在搜索页也要使用,所以做了一个自定义组件,只用@Component描述
@Component
export struct TitleBar {
private title = '';
build() {
Column() {
Row() {
Image($r('app.media.ic_back'))
.width(20)
.height(20)
.margin({ left: 26 })
.objectFit(ImageFit.Contain)
.onClick(() => {
router.back()
})
.backgroundColor(Color.Blue)
.id('backBtn')
Text(this.title)
.fontSize(20)
.layoutWeight(1)
.margin({ left: 16 })
.align(Alignment.Start)
Blank()
}
.height(56)
.width('100%')
}
}
}
5.完整代码如下:
import { http } from "@kit.NetworkKit";
import { DataElement, Welcome } from "../bean/HomePageBean";
import { RequestState } from "../data/RequestState";
import { router } from "@kit.ArkUI";
import { Datum, HomeBannerBean } from "../bean/HomeBannerBean";
import { SearchKeyBean, SearchKeyDataBean } from "../bean/SearchKeyBean";
@Extend(Column)
function ColumnStyle(){
.width("100%")
.borderRadius(24)
.backgroundColor(Color.White)
.padding({left:12,right:12,bottom:4,top:4})
}
@Component
export struct HomePage{
@State dataList:DataElement[] = [];
@State bannerData:Datum[] = [];
@State searchKeyData:SearchKeyDataBean[] = [];
@State searchContent:string = ''
aboutToAppear(): void {
this.getHomeData();
this.getHomeBanner();
this.getSearchKey();
}
private page:number = 0;
private state:RequestState = RequestState.INIT;
private lastIndex = 0;
getHomeData(){
this.state = RequestState.REQUESTING;
let httpRequest = http.createHttp();
httpRequest.request("https://www.wanandroid.com/article/list/"+this.page+"/json", {}, (err, data) => {
if (!err) {
console.log("HomePage data.result:"+data.result.toString())
let welcome: Welcome = JSON.parse(data.result.toString());
if(welcome && welcome.data && welcome.data.datas && welcome.data.datas.length > 0){
this.dataList = this.dataList.concat(welcome.data.datas)
this.page++;
}
} else {
}
this.state = RequestState.END;
})
}
getHomeBanner(){
let httpRequest = http.createHttp();
httpRequest.request("https://www.wanandroid.com/banner/json", {}, (err, data) => {
if (!err) {
console.log("HomePage data.result:"+data.result.toString())
let welcome: HomeBannerBean = JSON.parse(data.result.toString());
this.bannerData = welcome.data;
} else {
}
this.state = RequestState.END;
})
}
getSearchKey(){
let httpRequest = http.createHttp();
httpRequest.request("https://www.wanandroid.com/hotkey/json", {}, (err, data) => {
if (!err) {
console.log("HomePage data.result:"+data.result.toString())
let welcome: SearchKeyBean = JSON.parse(data.result.toString());
this.searchKeyData = welcome.data;
} else {
}
this.state = RequestState.END;
})
}
@Builder
searchKey(){
Menu(){
ForEach(this.searchKeyData,(data:SearchKeyDataBean,index:number)=>{
MenuItem({"content":data.name})
.onClick(()=>{
this.searchContent = data.name
})
})
}
}
build() {
Column(){
Row(){
TextInput({placeholder:"输入搜索关键词",text:this.searchContent})
.width(270)
.height(40)
.margin({top:10,bottom:10})
.backgroundColor(Color.White)
.bindMenu(
this.searchKey()
)
.onChange((value: string) => {
this.searchContent = value;
})
Button("搜索")
.margin({left:10,right:10})
.onClick(()=>{
console.log("searchContent "+this.searchContent)
router.pushUrl({
url:"pages/SearchListPage",
params:{data:this.searchContent}
})
})
}
Swiper(){
ForEach(this.bannerData,(data:Datum,index:number)=>{
Image(data.imagePath)
.width('100%')
.height('100%')
.onClick(()=>{
console.log("Swiper onClick link "+data.url)
router.pushUrl({
url:"pages/WebPage",
params:{data:data.url}
})
})
})
}
.width('100%')
.height(150)
List(){
if(this.dataList){
ForEach(this.dataList,(data:DataElement,index:number)=>{
ListItem(){
Column(){
Text(data.title)
.height(48)
.fontSize(14)
.width('100%')
.textAlign(TextAlign.Start)
.fontColor($r('app.color.font_color_shallow'))
.padding({bottom:4,top:4,left:24})
.maxLines(1)
Row(){
Text("分享人:"+data.author+" 分类:"+data.chapterName+"/"+data.superChapterName+" 时间:"+data.publishTime)
.maxLines(1)
.fontSize(8)
.padding({bottom:4,left:24})
}
.width('100%')
.justifyContent(FlexAlign.Start)
}
.ColumnStyle()
.margin({top:6,bottom:6})
.onTouch((event: TouchEvent | undefined) => {
if (event) {
console.log("event.type "+event.type+" event.y "+event.touches[0].y)
//判断加载更多,需要当前item展示到最后,并且当前请求结束,且往上拉了一段距离
if(event.type == TouchType.Up && event.touches[0].y < -100 && this.state == RequestState.END && this.lastIndex == this.dataList.length-1){
this.getHomeData();
}
}
})
}.onClick(()=>{
console.log("onClick link "+data.link)
router.pushUrl({
url:"pages/WebPage",
params:{data:data.link}
})
})
})
}
}
.onScrollIndex((start:number,end:number)=>{
//可以获取到当前屏幕第一个可见item和最后一个可见item
console.log("onScrollIndex start "+start+" end "+end)
this.lastIndex = end;
})
}
}
}
import { http } from "@kit.NetworkKit";
import { DataElement, Welcome } from "../bean/HomePageBean";
import { RequestState } from "../data/RequestState";
import { router } from "@kit.ArkUI";
import { TitleBar } from "../view/TitleBar";
@Extend(Column)
function ColumnStyle(){
.width("100%")
.borderRadius(24)
.backgroundColor(Color.White)
.padding({left:12,right:12,bottom:4,top:4})
}
@Entry
@Component
export struct SearchListPage{
@State dataList:DataElement[] = [];
searchKey:string = ''
aboutToAppear(): void {
let params: Record<string, Object> = router.getParams() as Record<string, Object>;
this.searchKey = params['data'] as string;
this.getHomeData();
}
private page:number = 0;
private state:RequestState = RequestState.INIT;
private lastIndex = 0;
getHomeData(){
this.state = RequestState.REQUESTING;
let httpRequest = http.createHttp();
httpRequest.request("https://www.wanandroid.com/article/query/"+this.page+"/json", {method: http.RequestMethod.POST,extraData: "k="+this.searchKey,}, (err, data) => {
if (!err) {
console.log("SearchListPage data.result:"+data.result.toString())
let welcome: Welcome = JSON.parse(data.result.toString());
if(welcome && welcome.data && welcome.data.datas && welcome.data.datas.length > 0){
this.dataList = this.dataList.concat(welcome.data.datas)
this.page++;
}
} else {
}
this.state = RequestState.END;
})
}
build() {
Column(){
TitleBar({title:this.searchKey})
List(){
if(this.dataList){
ForEach(this.dataList,(data:DataElement,index:number)=>{
ListItem(){
Column(){
Text(data.title)
.height(48)
.fontSize(14)
.width('100%')
.textAlign(TextAlign.Start)
.fontColor($r('app.color.font_color_shallow'))
.padding({bottom:4,top:4,left:24})
.maxLines(1)
Row(){
Text("分享人:"+data.author+" 分类:"+data.chapterName+"/"+data.superChapterName+" 时间:"+data.publishTime)
.maxLines(1)
.fontSize(8)
.padding({bottom:4,left:24})
}
.width('100%')
.justifyContent(FlexAlign.Start)
}
.ColumnStyle()
.margin({top:6,bottom:6})
.onTouch((event: TouchEvent | undefined) => {
if (event) {
console.log("event.type "+event.type+" event.y "+event.touches[0].y)
//判断加载更多,需要当前item展示到最后,并且当前请求结束,且往上拉了一段距离
if(event.type == TouchType.Up && event.touches[0].y < -100 && this.state == RequestState.END && this.lastIndex == this.dataList.length-1){
this.getHomeData();
}
}
})
}.onClick(()=>{
console.log("onClick link "+data.link)
router.pushUrl({
url:"pages/WebPage",
params:{data:data.link}
})
})
})
}
}
.onScrollIndex((start:number,end:number)=>{
//可以获取到当前屏幕第一个可见item和最后一个可见item
console.log("onScrollIndex start "+start+" end "+end)
this.lastIndex = end;
})
}
.backgroundColor($r('app.color.background_shallow_grey'))
}
}
// renderMode.ets
import { webview } from '@kit.ArkWeb';
import { router } from '@kit.ArkUI';
import { TitleBar } from '../view/TitleBar';
@Entry
@Component
struct WebPage {
private webviewController: WebviewController = new webview.WebviewController()
@State url:string = ''
aboutToAppear() {
let params: Record<string, Object> = router.getParams() as Record<string, Object>;
this.url = params['data'] as string;
}
build() {
Column() {
TitleBar()
Web({
src: this.url,
controller: this.webviewController,
renderMode: RenderMode.ASYNC_RENDER // 设置渲染模式
})
.width('100%')
.height('100%')
}
}
}
/*
* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import router from '@ohos.router'
// Page title bar
@Component
export struct TitleBar {
private title = '';
build() {
Column() {
Row() {
Image($r('app.media.ic_back'))
.width(20)
.height(20)
.margin({ left: 26 })
.objectFit(ImageFit.Contain)
.onClick(() => {
router.back()
})
.backgroundColor(Color.Blue)
.id('backBtn')
Text(this.title)
.fontSize(20)
.layoutWeight(1)
.margin({ left: 16 })
.align(Alignment.Start)
Blank()
}
.height(56)
.width('100%')
}
}
}
export interface HomeBannerBean {
data: Datum[];
errorCode: number;
errorMsg: string;
}
export interface Datum {
desc: string;
id: number;
imagePath: string;
isVisible: number;
order: number;
title: string;
type: number;
url: string;
}
export interface SearchKeyBean {
data: SearchKeyDataBean[];
errorCode: number;
errorMsg: string;
}
export interface SearchKeyDataBean {
id: number;
link: string;
name: string;
order: number;
visible: number;
}