易得天气
目前做了城市列表的展示、添加城市、删除城市、批量删除城市。城市列表的拖动排序还未做
由于代码量上来了,只贴关键代码,等做完了会开源出来
CityManagerViewModel类管理城市管理页面的状态
less
// 管理页面是否是编辑模式
@Trace isEditMode: boolean = false
// 编辑模式下被选中的城市
@Trace selectedList: Array<CityData> = []
// 城市列表滑动时标题栏的透明度
@Trace titleOpacity: number = 0
标题的显示根据isEditMode和selectedList共同决定
kotlin
@Computed
get title() {
return this.cityManagerVm.isEditMode ?
(ArrayUtil.isEmpty(this.cityManagerVm.selectedList) ? '请选择项目' :
'已选择' + this.cityManagerVm.selectedList.length + '项') : '城市管理'
}
中间的标题
scss
@Builder
centerTitle() {
Text(this.title)
.fontSize(18)
.fontColor($r('app.color.black'))
.opacity(this.cityManagerVm.titleOpacity)
}
右侧的按钮显示逻辑、点击事件
kotlin
@Builder
rightIcon() {
Image(this.cityManagerVm.isEditMode ? $r('app.media.ic_select_all_icon') : $r('app.media.ic_search_icon'))
.width(20)
.height(20)
.colorFilter(this.cityManagerVm.isEditMode ?
ColorUtils.translateColor(this.cityManagerVm.isSelectedAll(this.addedCityData) ? $r('app.color.app_main') :
$r('app.color.special_black')) : undefined)
.onClick(() => {
if (this.cityManagerVm.isEditMode) {
if (this.cityManagerVm.isSelectedAll(this.addedCityData)) {
this.cityManagerVm.clearSelected()
} else {
this.cityManagerVm.selectedAll(this.addedCityData)
}
} else {
ZRouter.getInstance()
.push(RouterConstants.SELECT_CITY_PAGE)
}
})
}
内容区域
scss
@Builder
contentView() {
Stack({ alignContent: Alignment.Bottom }) {
// 城市列表
this.cityList()
// 底部删除按钮
this.bottomOperateButton()
}
.width('100%')
.layoutWeight(1)
}
城市列表,其中标题的透明度变化在onDidScroll回调函数进行,swipeAction是侧滑按钮,transition是会执行List删除动画
kotlin
@Builder
cityList() {
List({ scroller: this.listScroller }) {
ListItem() {
Text(this.title)
.fontSize(28)
.fontColor($r('app.color.black'))
.opacity(1 - this.cityManagerVm.titleOpacity)
.padding({ left: 16, top: 12 })
.height(60)
}
ForEach(this.addedCityData, (cityData: CityData) => {
ListItem() {
CityManagerItem({
cityData: cityData,
isEditMode: this.cityManagerVm.isEditMode,
isSelected: this.cityManagerVm.isSelected(cityData),
toEditMode: (cityData) => {
this.cityManagerVm.toEditMode(this.addedCityData?.length ?? 0, cityData)
},
onItemClick: (cityData) => {
if (this.cityManagerVm.isEditMode) {
this.cityManagerVm.selected(cityData)
}
}
})
}
.swipeAction({
end: !cityData.isLocationCity && !this.cityManagerVm.isEditMode ? () => {
this.itemEnd(cityData)
} : undefined,
})
.transition(TransitionEffect.SLIDE)
}, (cityData: CityData): string => {
return cityData.cityid ?? ''
})
ListItem() {
Divider()
.width('100%')
.height(px2vp(AppUtil.getNavigationIndicatorHeight()) + (this.cityManagerVm.isEditMode ? 54 : 0))
.color($r('app.color.transparent'))
}
}
.width('100%')
.height('100%')
.divider({ strokeWidth: 12, color: $r('app.color.transparent') })
.edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true })
.onDidScroll(() => {
const yOffset = this.listScroller.currentOffset().yOffset
const percent = fixPercent(yOffset / 72)
this.cityManagerVm.changeTitleOpacity(percent)
})
}
CityManagerItem是城市列表每一项item
kotlin
// 定位的城市不支持编辑
if (!this.isLocationCity) {
this.editItem()
}
this.cityItem()
editItem,其中animatableEditItem让item支持动画
scss
@Builder
editItem() {
Row() {
Image($r('app.media.ic_menu_icon'))
.width(24)
.height(24)
.colorFilter(ColorUtils.translateColor($r('app.color.special_white')))
Image(this.isSelected ? $r('app.media.ic_checked_icon') : $r('app.media.ic_check_icon'))
.width(22)
.height(22)
.colorFilter(ColorUtils.translateColor(this.isSelected ? $r('app.color.app_main') :
$r('app.color.special_white')))
.backgroundColor(this.isEditMode && this.isSelected ? $r('app.color.special_white') :
$r('app.color.transparent'))
.borderRadius(100)
}
.width('100%')
.padding({ left: 16, right: 16 })
.animatableEditItem(this.isEditMode ? 1 : 0)
.animation({ duration: 200, curve: Curve.Linear })
.justifyContent(FlexAlign.SpaceBetween)
}
css
@AnimatableExtend(Row)
function animatableEditItem(visibility: number) {
.opacity(visibility)
.visibility(visibility <= 0 ? Visibility.Hidden : Visibility.Visible)
}
cityItem编辑模式下的动画
kotlin
.animatableCityItemPadding(this.isEditMode && !this.isLocationCity ? 52 : 16)
.animation({ duration: 200, curve: Curve.Linear })
less
@AnimatableExtend(Row)
function animatableCityItemPadding(padding: number) {
.padding({ left: padding, right: padding })
}
添加长按手势进入编辑模式
javascript
.gesture(
LongPressGesture()
.onAction((event: GestureEvent | undefined) => {
if (event) {
if (this.toEditMode) {
this.toEditMode(this.cityData)
}
}
})
)