HarmonyOS 鸿蒙Next 请教大家,这种需求应该怎么布局?
HarmonyOS 鸿蒙Next 请教大家,这种需求应该怎么布局?
需求是:在纵向横向列表联动的基础上,可以根据某一个字段决定,是否显示自定义的这一行内容。
这个“大列表”是可以上下滑动,也可以左右滑动,左右滑动时,前面第一列[直播标题]是不可以动的,也就是第一列只可以上下滑动
针对这种需求我应该如何布局?
更多关于HarmonyOS 鸿蒙Next 请教大家,这种需求应该怎么布局?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
[@Entry](/user/Entry)
[@ComponentV2](/user/ComponentV2)
struct Index {
[@Local](/user/Local) listLeft: number[] = []
aboutToAppear() {
for (let i = 0; i < 10; i++) {
this.listLeft.push(i)
}
this.listLeft[4] = -1
}
build() {
Scroll() {
Column() {
Row() {
Column() {
ForEach(this.listLeft, (item: number) => {
if (item >= 0) {
Row() {
Text(item.toString() + ' = = 1233123')
.height('100vp')
.width('100%')
.backgroundColor(Color.Blue)
.margin({ top: 4 })
}
} else {
Row() {
Text(item.toString() + ' = = 1233123')
.height('100vp')
.width('500%')
.backgroundColor(Color.Grey)
.margin({ top: 4 })
}
}
})
}.width('20%')
.backgroundColor(Color.Green)
.zIndex(2)
Scroll() {
Column() {
ForEach(this.listLeft, (item: number) => {
Row() {
Text(item.toString())
.height('100vp')
.width('50%')
.backgroundColor(Color.Pink)
.margin({ top: 4 })
Text(item.toString())
.height('100vp')
.width('50%')
.backgroundColor(Color.Pink)
.margin({ top: 4 })
Text(item.toString())
.height('100vp')
.width('50%')
.backgroundColor(Color.Pink)
.margin({ top: 4 })
}
})
}
.backgroundColor(Color.Brown)
.zIndex(1)
}.width('90%')
.scrollable(ScrollDirection.Horizontal)
}
}
}.size({ width: '100%', height: '100%' })
}
}
更多关于HarmonyOS 鸿蒙Next 请教大家,这种需求应该怎么布局?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
用zIndex 把层级的提起来。这样插入的广告可以盖住右边的数据,展示一行。然后两个Scroll分别控制横向滑动、竖向滑动。
[@Entry](/user/Entry)
[@ComponentV2](/user/ComponentV2)
struct Index {
[@Local](/user/Local) listTop: number[] = []
[@Local](/user/Local) listBottom: number[] = []
[@Local](/user/Local) listHorizontal: number[] = []
aboutToAppear(): void {
for (let i = 0; i < 3; i++) {
this.listTop.push(i)
}
for (let i = 0; i < 10; i++) {
this.listBottom.push(i)
}
for (let i = 0; i < 10; i++) {
this.listHorizontal.push(i)
}
}
private scroller: Scroller = new Scroller()
private scrollerTop: Scroller = new Scroller()
private scrollerBottom: Scroller = new Scroller()
build() {
Row() {
Scroll(this.scroller) {
Column() {
Row() {
Column() {
ForEach(this.listTop, (item: number) => {
Text(item.toString())
.height('100vp')
.width("100%")
.backgroundColor(Color.Blue)
.margin({ top: 4 })
})
}.width('20%')
Scroll(this.scrollerTop) {
Column() {
ForEach(this.listTop, (item: number) => {
Row() {
ForEach(this.listHorizontal, (child: number) => {
Text(item.toString() + '-' + child.toString())
.height('20vp')
.width('30vp')
})
}.height('100vp')
.backgroundColor(Color.Orange)
.margin({ top: 4 })
})
}
}.scrollBar(BarState.Off)
.scrollable(ScrollDirection.Horizontal)
.width('80%')
.onWillScroll((x: number, _y: number, _state: ScrollState, source: ScrollSource) => {
if (source == ScrollSource.SCROLLER || source == ScrollSource.SCROLLER_ANIMATION) {
return
}
if (x != 0) {
this.scrollerBottom.scrollBy(x, 0)
}
})
}
Text("我是一个横幅")
Row() {
Column() {
ForEach(this.listBottom, (item: number) => {
Text(item.toString())
.height('100vp')
.width("100%")
.backgroundColor(Color.Blue)
.margin({ top: 4 })
})
}.width('20%')
Scroll(this.scrollerBottom) {
Column() {
ForEach(this.listBottom, (item: number) => {
Row() {
ForEach(this.listHorizontal, (child: number) => {
Text(item.toString() + '-' + child.toString())
.height('20vp')
.width('30vp')
})
}.height('100vp')
.backgroundColor(Color.Orange)
.margin({ top: 4 })
})
}
}.width('80%')
.scrollBar(BarState.Off)
.scrollable(ScrollDirection.Horizontal)
.onWillScroll((x: number, _y: number, _state: ScrollState, source: ScrollSource) => {
if (source == ScrollSource.SCROLLER || source == ScrollSource.SCROLLER_ANIMATION) {
return
}
if (x != 0) {
this.scrollerTop.scrollBy(x, 0)
}
})
}
}
}.scrollBar(BarState.Off)
}.size({ width: '100%', height: '100%' })
}
}
感谢老哥~确实可以实现这种效果,但是需求是这样的,这些列表里,可能有的数据是带直播的,如果直播这个字段有效,就要在列表的下面展示这个横幅,现在老哥的这个布局,确实可以实现,但是右侧的列表用了两个scroller绑定,如果有n个横幅,那么右侧就要有n+1个scroller,这代码冗余太严重了~
楼下,横滑一个scroll ,竖向一个scroll.不管几个横幅,都没问题了
下面的这种布局可以实现 在某一行插入一条自定义布局,但是右侧列表横向滑动时,只能滑动自身,不能把右侧所有的列表都关联起来一起滑动,大家有什么其他的办法吗~~~
[@Entry](/user/Entry)
[@Component](/user/Component)
struct TestPage {
private dataSource: QuestionData[] = QUESTION_DATA
build() {
List() {
ForEach(this.dataSource, (item: QuestionData, index: number) => {
ListItem() {
QuestionItemComponent({
item: item,
itemWidth: 120,
itemHeight: 100
})
}
}, (item: QuestionData, index: number) => ${index}_${item.questCode}_${item.id}
)
}.width(‘100%’).height(‘100%’).listDirection(Axis.Vertical)
}
}
@Reusable
@Component
export struct QuestionItemComponent {
@Prop item: QuestionData;
@Prop itemWidth: number;
@Prop itemHeight: number;
build() {
Row() {
Text(this.item.questName)
.fontColor(Color.Black)
.fontWeight(FontWeight.Medium)
.fontSize(16)
.width(this.itemWidth)
.height(‘100%’)
.textAlign(TextAlign.Center)
Scroll() {
Row() {
Text(<span class="hljs-keyword">this</span>.item.questCode.toString())
.width(<span class="hljs-keyword">this</span>.itemWidth)
.height(<span class="hljs-string">'100%'</span>)
.textAlign(TextAlign.Center)
Text(<span class="hljs-keyword">this</span>.item.questName + `%`)
.fontColor(Color.Black)
.fontWeight(FontWeight.Medium)
.fontSize(<span class="hljs-number">16</span>)
.width(<span class="hljs-keyword">this</span>.itemWidth)
.height(<span class="hljs-string">'100%'</span>)
.textAlign(TextAlign.Center)
Text(<span class="hljs-keyword">this</span>.item.volume)
.fontColor(Color.Black)
.fontWeight(FontWeight.Medium)
.fontSize(<span class="hljs-number">16</span>)
.width(<span class="hljs-keyword">this</span>.itemWidth)
.height(<span class="hljs-string">'100%'</span>)
.textAlign(TextAlign.Center)
Text(<span class="hljs-keyword">this</span>.item.amount + `%`)
.fontColor(Color.Black)
.fontWeight(FontWeight.Medium)
.fontSize(<span class="hljs-number">16</span>)
.width(<span class="hljs-keyword">this</span>.itemWidth)
.height(<span class="hljs-string">'100%'</span>)
.textAlign(TextAlign.Center)
Text(<span class="hljs-keyword">this</span>.item.open.toString())
.fontColor(Color.Black)
.fontWeight(FontWeight.Medium)
.fontSize(<span class="hljs-number">16</span>)
.width(<span class="hljs-keyword">this</span>.itemWidth)
.height(<span class="hljs-string">'100%'</span>)
.textAlign(TextAlign.Center)
Text(<span class="hljs-keyword">this</span>.item.low.toString() + <span class="hljs-string">'%'</span>)
.fontColor(Color.Black)
.fontWeight(FontWeight.Medium)
.fontSize(<span class="hljs-number">16</span>)
.width(<span class="hljs-keyword">this</span>.itemWidth)
.height(<span class="hljs-string">'100%'</span>)
.textAlign(TextAlign.Center)
Text(<span class="hljs-keyword">this</span>.item.close.toString())
.fontColor(Color.Black)
.fontWeight(FontWeight.Medium)
.fontSize(<span class="hljs-number">16</span>)
.width(<span class="hljs-keyword">this</span>.itemWidth)
.height(<span class="hljs-string">'100%'</span>)
.textAlign(TextAlign.Center)
Text(<span class="hljs-keyword">this</span>.item.prevClose.toString())
.fontColor(Color.Black)
.fontWeight(FontWeight.Medium)
.fontSize(<span class="hljs-number">16</span>)
.width(<span class="hljs-keyword">this</span>.itemWidth)
.height(<span class="hljs-string">'100%'</span>)
.textAlign(TextAlign.Center)
}
}.layoutWeight(<span class="hljs-number">1</span>).height(<span class="hljs-number">50</span>).scrollable(ScrollDirection.Horizontal)
}
.height(<span class="hljs-keyword">this</span>.itemHeight)
}
}
class QuestionData {
id: number;
questCode: string;
questName: string;
volume: string;
amount: string;
open: number;
low: number;
close: number = Number.MIN_VALUE;
prevClose: number;
constructor(id: number, questCode: string, questName: string, volume: string, amount: string, open: number, low: number, close: number, prevClose: number) {
this.id = id
this.questCode = questCode
this.questName = questName
this.volume = volume
this.amount = amount
this.open = open
this.low = low
this.close = close
this.prevClose = prevClose
}
}
const QUESTION_DATA: QuestionData[] = [
new QuestionData(0, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 0, 1),
new QuestionData(1, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 1, 1),
new QuestionData(2, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
new QuestionData(3, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
new QuestionData(4, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
new QuestionData(5, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
new QuestionData(6, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
new QuestionData(7, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
new QuestionData(8, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
new QuestionData(9, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
new QuestionData(10, “问题代码”, “直播标题”, “成交量”, “成交额”, 1, 1, 2, 1),
]
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
[@Entry](/user/Entry)
[@ComponentV2](/user/ComponentV2)
struct Index {
[@Local](/user/Local) list: number[] = []
private scrollerLeft: Scroller = new Scroller()
private scrollerRight: Scroller = new Scroller()
aboutToAppear(): void {
for (let i = 0; i < 15; i++) {
this.list.push(i)
}
}
build() {
Row() {
Scroll(this.scrollerLeft) {
Column() {
ForEach(this.list, (item: number) => {
Text(item.toString())
.height('100vp')
.width("100%")
.backgroundColor(Color.Blue)
.margin({ top: 4 })
})
}
}.width('20%')
.scrollBar(BarState.Off)
.onWillScroll((x: number, y: number, state: ScrollState, source: ScrollSource) => {
if (source == ScrollSource.SCROLLER || source == ScrollSource.SCROLLER_ANIMATION) {
return
}
if (y != 0) {
this.scroll(this.scrollerRight, y)
}
})
Scroll(this.scrollerRight) {
Scroll() {
Column() {
ForEach(this.list, (item: number) => {
Row() {
ForEach(this.list, (child: number) => {
Text(item.toString() + '-' + child.toString())
.height('20vp')
.width('30vp')
})
}.height('100vp')
.backgroundColor(Color.Orange)
.margin({ top: 4 })
})
}
}
.scrollBar(BarState.Off)
.scrollable(ScrollDirection.Horizontal)
}.width('80%')
.scrollBar(BarState.Off)
.scrollable(ScrollDirection.Vertical)
.onWillScroll((x: number, y: number, state: ScrollState, source: ScrollSource) => {
if (source == ScrollSource.SCROLLER || source == ScrollSource.SCROLLER_ANIMATION) {
return
}
if (y != 0) {
this.scroll(this.scrollerLeft, y)
}
})
}.size({ width: '100%', height: '100%' })
}
scroll(follow: Scroller, yOffset: number) {
follow.scrollBy(0, yOffset)
}
}
右边因为嵌套,一次触摸,只能横滑或者竖滑。有点傻,但整体需求是实现了的
这个滑动没问题,是这个效果,这个功能我也实现了,但是,难点是如果在某一行插入一条自定义布局(插入的这一行,要从屏幕的最左边开始,在右边scroll左右滑动的时候,插入的这一行不可滚动)
看楼下代码,根据不能滑动的Item分成上下两部分,通过scroller 来联动一起横滑