范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

鸿蒙上实现世界杯主界面

  最近在看社区提供的 app_samples,其中有一个线性容器 ArrayList,看我后让我想起 Android 中 Scroll 与 ListView 嵌套使用时需要解决的滑动冲突问题。
  我想在 OpenHarmony 系统上是否也存在类似问题,Scroll 与 List 嵌套后是否存在滑动问题?
  Scroll 内嵌套 List 先说个结论: 不会出现 List 中只显示一个 item 问题 滑动事件不会冲突,在 List 区域可以滑动列表,在非 List 区域可以滑动 Scroll 滚动时,若 List 不设置宽高,则默认全部加载,在对性能有要求的场景下建议指定 List 的宽高
  基础信息
  Scroll 和 List 都属于基础容器:
  Scroll: 可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。
  官方介绍: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/arkui-ts/ts-container-scroll.md
  List: 列表包含一系列相同宽度的列表项。适合连续、多行呈现同类数据,例如图片和文本。
  官方介绍: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/arkui-ts/ts-container-list.md
  需求
  既然在 OpenHarmony 系统中 Scroll 与 List 不存在冲突问题,我们做一些其他的尝试,让 Scroll 与 List 的滚动结合实现联动。
  场景:实现世界杯主界面,包括球员 banner、赛事、积分榜。 启动页,3s 后进入主页面 头部显示球员 banner,首次显示 3 个球员,每隔 3 秒切换一个球员 球赛列表,包括:对战球队、比分、比赛状态(未开赛、已结束、进行中)、赛程 球赛列表拉到最后一条,触发全屏显示积分榜 点击返回首页,返回到页面顶部,球赛列表返回首条显示 在一个页面中实现 草图如下:
  效果如下:
  开发环境 IDE:DevEco Studio 3.0 Beta4 Build Version: 3.0.0.992, built on July 14, 2022SDK:Full SDK 9 3.2.7.6系统:OpenHarmony v3.2 beta3
  实践
  声明:示例中的数据的自己构建的,只为示例显示使用,与实际比赛数据存在差异,请忽略。 ①创建项目
  说明:在 DevEco Studio IDE 中构建 OpenHarmony Stage 模型项目,SDK 选择 9(3.2.7.6)。
  ②关键代码import { BaseDataSource } from "../MainAbility/model/BaseDataSource" import { Information } from "../MainAbility/model/Information" import { MatchInfo, MatchState } from "../MainAbility/common/FlagData" import { MatchDataResource } from "../MainAbility/model/MatchDataResource" import { BannerDataResource } from "../MainAbility/model/BannerDataResource" const TAG: string = "ScrollList" // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部 const SCROLL_LIST_POSITION = {   START: 0,   CENTER: 1,   END: 2 } const LIST_START = {   TOP: 0,   BUTTON: 1 } class MatchDataSource extends BaseDataSource {   constructor(infos: Information[]) {     super(infos)   } } class BannerDataSource extends BaseDataSource {   constructor(infos: BannerDataResource[]) {     super(infos)   } } function mock(): Information[] {   var infos = []   for (var i = 0; i < 10; i++) {     var item = new Information()     item.id = i     item.state = Math.floor(Math.random() * 2) // 获取0~2的随机整数     var homeIndex: number = Math.floor(Math.random() * 12) // 获取0~12的随机整数     item.homeName = MatchInfo[homeIndex].name     item.homeFlag = MatchInfo[homeIndex].resource     var awayFieldIndex: number = Math.floor(Math.random() * 12) // 获取0~12的随机整数     if (awayFieldIndex === homeIndex) {       awayFieldIndex = Math.floor(Math.random() * 12) // 获取0~12的随机整数     }     item.awayFieldName = MatchInfo[awayFieldIndex].name     item.awayFieldFlag = MatchInfo[awayFieldIndex].resource     if (item.state != MatchState.NOTSTART) {       item.homeScore = Math.floor(Math.random() * 6)       item.awayFiledScore = Math.floor(Math.random() * 6)     }     var data: number = Math.floor(Math.random() * 20) // 获取0~20的随机整数     var time: number = Math.floor(Math.random() * 24) // 获取0~24的随机整数     item.gameTime = "12 - " + data + " " + time + " : 00"     infos[i] = item   }   return infos } function mockBanner(): BannerDataResource[] {   var banners = [{                    id: 1,                    resource: $r("app.media.banner_01")                  },                  {                    id: 2,                    resource: $r("app.media.banner_02")                  },                  {                    id: 3,                    resource: $r("app.media.banner_03")                  },                  {                    id: 4,                    resource: $r("app.media.banner_04")                  },                  {                    id: 5,                    resource: $r("app.media.banner_05")                  }   ]   return banners } @Entry @Component struct Index {   private listPosition: number = SCROLL_LIST_POSITION.START   @State private listState: number = LIST_START.TOP   private scrollerForScroll: Scroller = new Scroller() // 可滚动容器组件的控制器   private scrollerForList: Scroller = new Scroller()   // mock数据   private matchData: Information[] = mock()   private matchDataSource: MatchDataSource = new MatchDataSource(this.matchData)   // banner   private bannerData: BannerDataResource[] = mockBanner()   private bannerDataSource: BannerDataSource = new BannerDataSource(this.bannerData)   private swiperController: SwiperController = new SwiperController()   @State private isShowFlashscreen: boolean = true   private timeOutID: number   aboutToAppear() {     this.startTimeout()   }   aboutToDisappear() {     this.stopTimeout()   }   build() {     Stack() {       if (this.isShowFlashscreen) {         Image($r("app.media.flashscreen"))           .width("100%")           .height("100%")           .objectFit(ImageFit.Cover)       } else {         Scroll(this.scrollerForScroll) {           Column() {             Swiper(this.swiperController) {               LazyForEach(this.bannerDataSource, (item: BannerDataResource) => {                 Image(item.resource)                   .width("33.3%")                   .height("100%")                   .objectFit(ImageFit.Cover)               }, item => item.id.toString())             }             .width("100%")             .height("35%")             .cachedCount(3)             .index(0)             .autoPlay(true)             .loop(true)             .displayMode(SwiperDisplayMode.AutoLinear)             .indicator(false)             .indicatorStyle({               selectedColor: $r("app.color.red_bg")             })             Divider().strokeWidth(3).color($r("app.color.red_bg"))             Column() {               List({                 space: 10,                 scroller: this.scrollerForList               }) {                 LazyForEach(this.matchDataSource, (item: Information) => {                   ListItem() {                     Row() {                       Column({ space: 10 }) {                         Image(item.homeFlag)                           .width(60)                           .height(45)                           .objectFit(ImageFit.Contain)                         Text(item.homeName)                           .width("100%")                           .fontSize(16)                           .textAlign(TextAlign.Center)                       }                       .width("30%")                       Column({ space: 10 }) {                         Text(this.getMatchState(item.state))                           .width("100%")                           .fontSize(12)                           .fontColor($r("app.color.event_text"))                           .textAlign(TextAlign.Center)                         Text(this.getMatchSource(item))                           .width("100%")                           .fontSize(18)                           .textAlign(TextAlign.Center)                         Text(item.gameType)                           .width("100%")                           .fontSize(12)                           .fontColor($r("app.color.event_text"))                           .textAlign(TextAlign.Center)                       }                       .width("30%")                       Column({ space: 10 }) {                         Image(item.awayFieldFlag)                           .width(60)                           .height(45)                           .objectFit(ImageFit.Contain)                         Text(item.awayFieldName)                           .width("100%")                           .fontSize(16)                           .textAlign(TextAlign.Center)                       }                       .width("30%")                     }                     .width("100%")                     .height("100%")                     .justifyContent(FlexAlign.SpaceBetween)                     .border({                       radius: 15                     })                     .backgroundColor($r("app.color.white"))                   }                   .width("100%")                   .height(95)                 }, item => item.id.toString())               }               .width("90%")               .height("100%")               .edgeEffect(EdgeEffect.Spring) // 滑动效果               .onReachStart(() => {                 // 滑动开始                 this.listPosition = SCROLL_LIST_POSITION.START               })               .onReachEnd(() => {                 // 滑动结束                 this.listPosition = SCROLL_LIST_POSITION.END               })               .onScrollBegin((dx: number, dy: number) => {                 console.info(TAG, `listPositinotallow=${this.listPosition} dx=${dx} ,dy=${dy}`)                 if (this.listPosition == SCROLL_LIST_POSITION.START && dy >= 0) {                   // 列表顶部                   // this.scrollerForScroll.scrollBy(0, -dy)                   this.scrollerForScroll.scrollEdge(Edge.Start)                   this.listState = LIST_START.TOP                 } else if (this.listPosition == SCROLL_LIST_POSITION.END && dy <= 0) {                   // 列表底部                   // this.scrollerForScroll.scrollBy(0, -dy)                   this.scrollerForScroll.scrollEdge(Edge.Bottom)                   this.listState = LIST_START.BUTTON                 }                 this.listPosition = SCROLL_LIST_POSITION.CENTER                 return {                   dxRemain: dx,                   dyRemain: dy                 }               })             }             .width("100%")             .height("60%")             .padding({               top: 20,               bottom: 20             })             .borderRadius({               bottomLeft: 15,               bottomRight: 15             })             .backgroundColor($r("app.color.content_bg"))             Column() {               if (this.listState === LIST_START.TOP) {                 Text("继续上滑 积分排名")                   .width("100%")                   .height("5%")                   .fontColor($r("app.color.white"))                   .fontSize(14)                   .textAlign(TextAlign.Center)               } else {                 Text("回到首页")                   .width("100%")                   .height("5%")                   .fontColor($r("app.color.white"))                   .fontSize(14)                   .textAlign(TextAlign.Center)                   .onClick(() => {                     this.scrollerForScroll.scrollEdge(Edge.Start)                     this.scrollerForList.scrollToIndex(0)                     this.listState = LIST_START.TOP                   })               }               Stack() {                 Image($r("app.media.result_1"))                   .width("100%")                   .height("100%")                   .objectFit(ImageFit.Cover)                 Column() {                 }.width("100%")                 .height("100%")                 .backgroundColor("#55000000")                 Image($r("app.media.football_poster"))                   .width("100%")                   .height("100%")                   .objectFit(ImageFit.Contain)                   .opacity(0.70)                   .borderRadius({                     topLeft: 15,                     topRight: 15                   })               }.width("100%")               .height("95%")             }             .width("100%")             .height("100%")           }         }         .width("100%")         .height("100%")         .onScrollBegin((dx: number, dy: number) => {           return {             dxRemain: dx,             dyRemain: 0           }         })       }     }.width("100%")     .height("100%")     .backgroundColor($r("app.color.main_bg"))   }   getMatchState(state: number): string {     var stateVal: string     switch (state) {       case MatchState.PROGRESS: {         stateVal = "进行中"         break;       }       case MatchState.NOTSTART: {         stateVal = "未开赛"         break;       }       case MatchState.CLOSED: {         stateVal = "已结束"         break;       }       default:         stateVal = ""     }     return stateVal;   }   getMatchSource(data: Information): string {     if (data.state === MatchState.NOTSTART) {       return "- : -"     } else {       return data.homeScore + " : " + data.awayFiledScore     }   }   startTimeout() {     this.timeOutID = setTimeout(() => {       this.isShowFlashscreen = false     }, 3000)   }   stopTimeout() {     clearTimeout(this.timeOutID)   } }
  根据代码说明下实现方式:
  ① 3s 进入主页面,主要通过定时器 setTimeout() 实现,设置 3s 后隐藏全屏图片。
  全屏图片父容器使用堆叠容器 Stack 包裹,通过 this.isShowFlashscreen 变量判断是否隐藏全屏图片,显示主页面。
  ② 主页面中,最外层通过 Scroll 容器,作为主页面的根容器。
  ③ 球员 banner 使用滑块视图容器 Swiper,内部使用 LazyForEach 懒加载方式加载球员图片,单屏横向显示三个球员,所以球员的图片高度为屏幕总宽度的 33.3%。
  并将滑块组件的 displayMode 属性设置为 SwiperDisplayMode.AutoLinear,让 Swiper 滑动一页的宽度为子组件宽度中的最大值,这样每次滑动的宽度就是 33.3%,一个球员的图片。
  ④ 赛程列表,使用 List 组件进行加载,赛事 item 使用 LazyForEach 懒加载的方式提交列表加载效率。
  通过 List 中的事件监听器 onReachStart(event: () => void) 和 onReachEnd(event: () => void) 监听列表达到起始位置或底末尾位置。
  并在 onScrollBegin(event: (dx: number, dy: number) => { dxRemain: number, dyRemain: number }) 函数中监听列表的滑动量,如果滑动到 List 底部,再向上滑动界面时触发显示"积分排行"界面。
  ⑤ 积分排行界面内容,初始化时超屏显示,只有在滑动到 List 底部是,才被拉起显示。
  积分排行界面设置在 Scroll 容器中,通过 this.scrollerForScroll.scrollEdge(Edge.Bottom) 拉起页面。
  ⑥ 点击"返回首页",通过设置 this.scrollerForScroll.scrollEdge(Edge.Start),返回到 Scroll 顶部。
  代码中使用到的组件关键 API①Scroll
  说明:若通过 onScrollBegin 事件和 scrollBy 方法实现容器嵌套滚动,需设置子滚动节点的 EdgeEffect 为 None。如 Scroll 嵌套 List 滚动时,List 组件的 edgeEffect 属性需设置为 EdgeEffect.None。②Swiper
  ③List
  完整代码:https://gitee.com/xjszzz9/open-harmony-ark-ui-scroll-list-o
  如果您能看到最后,还希望您能动动手指点个赞,一个人能走多远关键在于与谁同行,我用跨越山海的一路相伴,希望得到您的点赞。

CBA最新积分榜!辽篮迎两连胜,首钢遭遇连败,广东队跌出前八北京时间10月14日晚,八支球队迎来了CBA常规赛第二轮比赛。广州10698四川全场18投12中,三分4中2,陈盈俊本场比赛的状态十分出色,砍下了全队最高的31分外加4篮板8助攻的ampamp39巨石ampamp39强森打算参选2024美国总统,你觉得他有戏么道恩。约翰逊(巨石强森)近日表示,他的支持者们强烈要求他冲刺白宫,但他坚持认为,目前的工作重点是养家糊口,并做好父亲和丈夫的角色。巨石强森我对他们的提议感到宽慰和谦卑,不过我更喜欢辽宁2连胜后!杨鸣心疼老队员,赵继伟解读新规则说出心里话辽宁男篮经过一番苦战之后,2分击败北京首钢,杨鸣和赵继伟出席新闻发布会,谈到本场比赛的激烈程度,杨鸣有感而发。他表示这场比赛双方都体现各自的特点,比拼篮板球,防守上,虽然我们12人储能技术大突破液体储能,可将太阳能存储18年查尔默斯理工大学的瑞典科学家正在研究一种可以将太阳能储存长达18年的液体,这种液体含有一种叫做正常镭的分子,由碳氢和氮组成。分子太阳能蓄热系统液体储能的工作原理及优势该分子由两个或研究高次谐波激光器为光学显微镜的分辨率带来巨大提升澳大利亚国立大学(ANU)的物理学家们表示,在他们发现了一种新的高次谐波激光照明技术之后,光学显微镜的放大率应该得到巨大的提升,这种技术使用的是人类头发直径的150的微型圆柱体。这二师兄携手菜蛋上涨9月CPI同比涨幅或有所扩大中国新闻网10月14日,国家统计局将公布9月份全国居民消费价格指数(CPI),猪肉蔬菜鸡蛋等食品价格走高下,多家机构预计,9月CPI同比涨幅或有所扩大。9月CPI同比涨幅或有所扩大政府回购新房,多项政策叠加促楼市成交未来网北京10月14日电(记者王秀娟)近期,不少地方政府稳楼市大招频出,未来网记者注意到,目前,已经有包括苏州济南湖州等多地政府部门发布回购当地商品房新政。近日,一份苏州市政府部门信贷新政要来?高利率站岗的业主不用愁了,利率将改到4。1新的信贷政策要来?前期高位站岗的存量房贷利率有望下调到4。1?1hr5。88降至4。1!高利率存量房贷要降?今日(10。12)有微博网友爆料,称合肥有银行将执行信贷新政根据银行内部存量房贷降息有可能吗?近期人民银行陆续出台了降息政策,商贷利率降至4。1,公积金贷款利率历史性下降,那么对于存量房贷高利率,能否降息是大家十分关心的问题,毕竟在长达十几年最长三十年的还款期,利率差别高大近两年,要做好资产贬值的准备?这5件事最好不要去做不知不觉,疫情已经来到了第三年,生活中的很多地方都发生了变化。比如说天天戴口罩,进门先扫码,核酸常态化,还有随时准备被封控。要说疫情之前的日子,普通人过得也不轻松,每天朝九晚九,连沪东中华造船建造能级和效率不断提升再现同日两船开工1。3万TEU液化天然气(LNG)双燃料动力超大型集装箱船开建。张黎摄中新网上海10月14日电(殷立勤张文豪)10月14日,中国船舶集团旗下沪东中华造船(集团)有限公司为中国石油国
托马斯VS乔丹,谁更厉害?看看两人65次交手数据,才发现他没吹牛托马斯在一档节目中表示,乔丹根本不是一位合格的对手,真正算是对手的是伯德,约翰逊,贾巴尔等。看来托马斯确实是有点看不起乔丹,两人职业生涯一共交手65次,托马斯赢下了36次,乔丹只赢美网综合卡恰诺夫鏖战五盘过关贾贝乌尔晋级创历史在6日进行的美国网球公开赛男女单打四分之一决赛中,卡恰诺夫与克耶高斯鏖战五盘后胜出,晋级男单四强在女单比赛中,突尼斯选手贾贝乌尔直落两盘战胜澳大利亚选手汤姆贾诺维奇,成为公开赛年代8868体育登贝莱的选择只有巴萨8868体育巴萨的球员登贝莱与球队的合约已经到期,是否会续约成为了大众的疑问。但是登贝莱表示,他只想留在巴萨。众所周知,巴萨的登贝莱在球队的合约已经到期。外界也纷纷关注登贝莱是否会赵维伦中国男篮希望之星成长在意乡供图视觉中国供图成长在意乡微博7日,年仅16岁一直在意大利生活与打球的中国年轻球员赵维伦更新了社交媒体他提前两年青训过关,解锁成人职业联赛,升入意甲瓦雷泽一队,身披11号球衣。在此白露过后,燥字当头!建议有条件多吃4种ampampquot润肺王ampampquot,健康过秋白露时节多呈现风清冷,云高远,气干燥的天气状态,虽然体感舒适了不少,但是空气异常干燥,肺为娇脏最怕燥,眼下的饮食一定要以润燥为主。白露过后,燥字当头!建议有条件多吃润肺4宝,养肺护注意!肿瘤患者怎样吃才健康?这类食物千万不要和靶向药一起吃阅读前请点关注,每天定时分享关于妇科肿瘤及癌症知识,拥抱每一位肿瘤患者,让你在抗癌的路上不孤单食物是肿瘤患者摄取营养的主要来源。通过每天摄取健康的食物,能够让肿瘤患者治疗效果翻倍,补钙不得不知道的3个细节第1日常要多往体内送阳光钙要从肠道进入到血液,离不开维生素D的参与。所以适量接受光照是很有必要的。如果担心晒黑,也可以多吃一吃晒干了的香菇。它在紫外线的照射下,能够合成一部分的维生健康夏天结束,晒黑了吗?多吃这五种食物让肌肤白回来巴黎8月26日(胡桢)根据canalnews报导,暑期即将结束,有的人肌肤晒成了漂亮的棕色,有的人却因为防护不当,造成了晒伤,有一些食物能够帮我们镇静消炎,加速皮肤恢复健康状态。强苹果发布iPhone1414Plus配置小升级,大屏新选择9月8日消息,今日苹果召开新品发布会,发布了全新的iPhone14系列手机,其中除了iPhone14之外,还带来了6。7英寸的iPhone14Plus。iPhone14系列搭载了满全能本标杆提档!华硕新款无畏Pro发布,OLED独显直连都有9月7日,华硕秋季新品发布会如期举办,在这场发布会上,华硕一口气推出了多款新品笔记本电脑产品,其中华硕无畏Pro2022系列更是涵盖了三款型号,其中包括华硕无畏Pro152022锐iPhone14登场,一个会自己动的刘海你见过吗?iPhone14它来了!它终于没有了刘海。它终于不是万年1200万像素。它终于变了亿点点。他,来了。iPhone14ProProMaxiPhone14Pro系列两款新机长这样iPh