1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15import { BroadCast, BroadCastConstants, Constants, DateUtil, Log, ScreenManager, TimelineData } from '@ohos/common'; 16 17const TAG: string = 'timeline_TimelineScrollBar'; 18 19@Component 20export struct TimelineScrollBar { 21 scroller: Scroller | null = null; 22 @Consume @Watch('updateTotalNum') yearData: TimelineData[]; 23 @State isClickScrollBar: boolean = false; 24 @Consume dateText: string; 25 @Consume broadCast: BroadCast; 26 @State totalNum: number = 0; 27 gridHeight: number = ScreenManager.getInstance() 28 .getWinHeight() - Constants.ActionBarHeight - Constants.TOOL_BAR_SIZE - Constants.SCROLL_MARGIN * 2; 29 30 aboutToAppear(): void { 31 this.updateTotalNum(); 32 } 33 34 nodeGap(count: number): number { 35 Log.debug(TAG, `nodeGap start ${count} --- ${this.gridHeight} ---- ${this.totalNum}`) 36 let gapS = Math.ceil(this.gridHeight * count / this.totalNum - 48); 37 if (gapS >= Constants.SCROLL_BAR_SIDE_MIN_GAP) { 38 return gapS; 39 } 40 41 return -1; 42 } 43 44 updateTotalNum() { 45 let totalCount = 0; 46 for (let year of this.yearData) { 47 totalCount = totalCount + year.count; 48 } 49 this.totalNum = totalCount; 50 } 51 52 build() { 53 Stack({ alignContent: Alignment.End }) { 54 if (this.isClickScrollBar) { 55 Column() { 56 ForEach(this.yearData, (year: TimelineData, index?: number) => { 57 if (this.nodeGap(year.count) > 0 || this.yearData.indexOf(year) == 0 58 || this.yearData.indexOf(year) == this.yearData.length - 1) { 59 Row() { 60 Text(DateUtil.getLocalizedYear(year.startDate)) 61 .fontSize($r('sys.float.ohos_id_text_size_body3')) 62 .fontFamily($r('app.string.id_text_font_family_medium')) 63 .fontColor($r('sys.color.ohos_id_color_text_primary')) 64 .key('TimelineScrollBar_Text_' + index) 65 } 66 .key('TimelineScrollBar_Row_' + index) 67 .height($r('app.float.scroll_bar_side_text_height_small')) 68 .backgroundColor($r('app.color.scroll_bar_side_text_small_color')) 69 .borderRadius($r('app.float.scroll_bar_side_text_radio')) 70 .padding({ 71 left: $r('app.float.scroll_bar_side_text_padding_horizontal_small'), 72 right: $r('app.float.scroll_bar_side_text_padding_horizontal_small'), 73 top: $r('app.float.scroll_bar_side_text_padding_vertical_small'), 74 bottom: $r('app.float.scroll_bar_side_text_padding_vertical_small') 75 }) 76 .shadow({ 77 radius: $r('app.float.scroll_bar_side_text_shadow_radio'), 78 color: $r('app.color.scroll_bar_side_text_shadow_color'), 79 offsetX: $r('app.float.scroll_bar_side_text_shadow_offsetX'), 80 offsetY: $r('app.float.scroll_bar_side_text_shadow_offsetY'), 81 }) 82 .margin({ 83 bottom: this.nodeGap(year.count) 84 }) 85 } 86 }, (year: TimelineData) => JSON.stringify(year)) 87 } 88 .height('100%') 89 .margin({ 90 right: $r('app.float.scroll_bar_margin_small'), 91 top: $r('sys.float.ohos_id_max_padding_start'), 92 bottom: $r('sys.float.ohos_id_max_padding_end') 93 }) 94 } 95 96 ScrollBar({ scroller: this.scroller as Scroller, direction: ScrollBarDirection.Vertical, 97 state: BarState.Auto }) { 98 Row() { 99 if (this.isClickScrollBar) { 100 Row() { 101 Row() { 102 Text(this.dateText) 103 .fontSize($r('sys.float.ohos_id_text_size_sub_title1')) 104 .fontFamily($r('app.string.id_text_font_family_medium')) 105 .fontColor($r('app.color.title_text_color')) 106 .fontWeight(FontWeight.Medium) 107 } 108 .height($r('app.float.scroll_bar_side_text_height')) 109 .backgroundColor($r('app.color.scroll_bar_side_text_color')) 110 .borderRadius($r('app.float.scroll_bar_side_text_radio')) 111 .padding({ 112 left: $r('app.float.scroll_bar_side_text_padding_horizontal'), 113 right: $r('app.float.scroll_bar_side_text_padding_horizontal'), 114 top: $r('app.float.scroll_bar_side_text_padding_vertical'), 115 bottom: $r('app.float.scroll_bar_side_text_padding_vertical') 116 }) 117 .shadow({ 118 radius: $r('app.float.scroll_bar_side_text_shadow_radio'), 119 color: $r('app.color.scroll_bar_side_text_shadow_color'), 120 offsetX: $r('app.float.scroll_bar_side_text_shadow_offsetX'), 121 offsetY: $r('app.float.scroll_bar_side_text_shadow_offsetY'), 122 }) 123 124 Row() { 125 Image($r('app.media.scroll_press_light')) 126 } 127 .width($r('app.float.scroll_bar_big_width')) 128 .height($r('app.float.scroll_bar_big_height')) 129 .margin({ left: $r('app.float.scroll_bar_side_gap') }) 130 } 131 .width($r('app.float.scroll_press_all_width')) 132 .justifyContent(FlexAlign.End) 133 } else { 134 Row() { 135 Image($r('app.media.scroll_light')) 136 .width($r('app.float.scroll_bar_small_width')) 137 .height($r('app.float.scroll_bar_small_height')) 138 .borderRadius(25) 139 } 140 } 141 } 142 } 143 .height('100%') 144 .width(this.isClickScrollBar ? $r('app.float.scroll_press_all_width') : $r('app.float.scroll_bar_small_width')) 145 .onTouch((event?: TouchEvent) => { 146 if (this.dateText == '') { 147 Log.debug(TAG, `dateText is null`) 148 this.broadCast.emit(BroadCastConstants.INIT_DATE_TEXT, []) 149 } 150 if ((event as TouchEvent).type == TouchType.Move && !this.isClickScrollBar) { 151 Log.debug(TAG, `scrollBar first TouchType.Move`); 152 this.isClickScrollBar = true; 153 } else if ((event as TouchEvent).type == TouchType.Up || (event as TouchEvent).type == TouchType.Cancel) { 154 Log.debug(TAG, `scrollBar TouchType.Up or Cancel. type=${(event as TouchEvent).type}`); 155 this.isClickScrollBar = false; 156 } 157 }) 158 } 159 .hitTestBehavior(HitTestMode.Transparent) 160 .position({ x: '100%', y: 0 }) 161 .markAnchor({ 162 x: '100%', 163 y: 0 164 }) 165 } 166}