ArkTS 动态生成对话框的方式
动态生成持有 CustomDialogController 的组件,来实现动态生成对话框
代码
包括四个ets文件(MyDialogComponent、MyDialog、MyButton、MyBaseAdapter)
MyDialogComponent.ets
import { AlertParams, DateTimeParams, MyDialog, MyDialogParams, MyDialogType, MyObject, ProgressParams, PullUpButtonParams } from './MyDialog';
import { BaseAdapter } from './MyBaseAdapter';
import { MyButton } from './MyButton';
const color333333 = 0xff333333;
const line = 0xffcccccc;
const titleBarColor = 0xffE5431B;
const color999999 = 0xff999999;
const colorF9F9F9 = 0xffF9F9F9;
const colorF2F2F2 = 0xffF2F2F2;
@CustomDialog
struct AlertDialogBuilder {
controller: CustomDialogController;
params!: AlertParams;
@State maxHeight: number = 0;
heightForRoot: number = 0;
heightForTitle: number = 0;
aboutToAppear() {
this.params.title ??= ""
this.params.message ??= ""
this.params.btnOK ??= "确定"
this.params.btnCancel ??= ""
}
@Builder
buildContent() {
Column() {
Column() {
Row() {
if (this.params.title!.length > 0) {
Text(this.params.title)
.fontColor(color333333)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.padding({ bottom: 13 })
.onAreaChange((_, newArea) => {
let height = newArea.height as number;
if (height != this.heightForTitle) {
this.heightForTitle = height;
this.refreshMaxHeight();
}
})
} else {
Blank().height(13)
}
}.constraintSize({ minHeight: 13 })
Column() {
Scroll() {
Column() {
Text(this.params.message).fontColor(color333333).fontSize(16)
}
}.scrollable(ScrollDirection.Vertical) //.edgeEffect(EdgeEffect.Spring)
}.constraintSize({ maxHeight: this.maxHeight > 0 ? this.maxHeight : "100%" })
Row() {
if (this.params.btnCancel!.length > 0) {
MyButton({
text: this.params.btnCancel,
buttonHeight: 44,
click: () => {
MyDialogParams.close(this.params);
this.params.btnCancelClick?.();
}
}).layoutWeight(1)
}
if (this.params.btnCancel!.length > 0 && this.params.btnOK!.length > 0) {
Blank().width(24)
}
if (this.params.btnOK!.length > 0) {
MyButton({
text: this.params.btnOK,
buttonHeight: 44,
click: () => {
MyDialogParams.close(this.params);
this.params.btnOKClick?.();
}
}).layoutWeight(1)
}
}.padding({ top: 24 })
}.padding(24)
.backgroundColor(Color.White)
.borderRadius(10)
}
.margin({ left: 32, right: 32, top: 32, bottom: 32, })
.onClick(() => {
})
}
build() {
Column() {
this.buildContent()
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.width("100%")
.height("100%")
.onClick(() => {
if (this.params.autoCancel) {
MyDialogParams.close(this.params);
this.params.cancel?.();
}
})
.onAreaChange((_, newArea) => {
let height = newArea.height as number;
if (this.heightForRoot != height) {
this.heightForRoot = height;
this.refreshMaxHeight();
}
})
}
refreshMaxHeight() {
if (this.heightForRoot > 0) {
if (this.params.title!.length > 0 && this.heightForTitle == 0) return;
let tempHeight = this.heightForRoot - (32 + 32) - (24 + this.heightForTitle + 13) - (24 + 44 + 24);
if (tempHeight != this.maxHeight) {
this.maxHeight = tempHeight;
}
}
}
}
@CustomDialog
struct ProgressDialogBuilder {
controller: CustomDialogController;
params!: ProgressParams;
@State progress: number = -1;
@State message: string = "";
aboutToAppear() {
this.message = this.params.message ?? "";
this.progress = this.params.progress ?? -1;
if (this.progress >= 0) {
this.params.updateProgress = (progress, message) => {
this.progress = progress ?? 0;
this.message = message ?? "";
}
}
}
@Builder
buildContent() {
Column() {
if (this.progress >= 0) {
Stack() {
Progress({ value: this.progress, total: 100, type: ProgressType.Ring }).color(titleBarColor).style({ strokeWidth: 10, scaleCount: 10, scaleWidth: 10 })
.width("100%").height("100%")
Row() {
Text(this.params.progress!.toFixed(1)).fontColor(color333333).fontSize(22).fontWeight(FontWeight.Bold)
Text("%").fontColor(color333333).fontSize(12).fontWeight(FontWeight.Bold).padding({ left: 2, bottom: 3 })
}.alignItems(VerticalAlign.Bottom)
}.align(Alignment.Center).width(100).height(100)
if (this.message.length > 0) {
Text(this.message)
.fontColor(color333333)
.fontSize(18)
.maxLines(6)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.padding({ top: 16, left: 8, right: 8, bottom: 8 })
}
} else {
LoadingProgress().color(titleBarColor).width(100).height(100)
if (this.message.length > 0) {
Text(this.message)
.fontColor(color333333)
.fontSize(18)
.maxLines(6)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.padding(8)
}
}
}
.padding(24)
.backgroundColor(Color.White)
.borderRadius(10)
.margin({ left: 32, right: 32, top: 32, bottom: 32, })
.onClick(() => {
})
}
build() {
Column() {
this.buildContent()
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.width("100%")
.height("100%")
.onClick(() => {
if (this.params.autoCancel) {
MyDialogParams.close(this.params);
this.params.cancel?.();
}
})
}
}
@CustomDialog
struct PullUpButtonDialogBuilder {
controller: CustomDialogController;
params!: PullUpButtonParams;
aboutToAppear() {
this.params.btnList ??= [];
this.params.btnCancel ??= "";
}
@Builder
buildButton(btnName: string, index: number, isForCancel: boolean = false) {
Text(btnName)
.fontColor(color333333)
.fontSize(16)
.height(50)
.textAlign(TextAlign.Center)
.width("100%")
.onClick(() => {
MyDialogParams.close(this.params);
if (!isForCancel) this.params.btnClick?.(btnName, index)
})
}
build() {
Column() {
Column() {
Column() {
Scroll() {
Column() {
if (this.params.btnList.length > 0) {
ForEach(this.params.btnList, (btnName: string, index: number) => {
this.buildButton(btnName, index)
Text().height(1).width("100%").backgroundColor(colorF2F2F2)
})
} else {
// 没有展示的 button
}
}
}.scrollable(ScrollDirection.Vertical).constraintSize({ maxHeight: "100%" }).backgroundColor(Color.White)
}.layoutWeight(1).justifyContent(FlexAlign.End)
if (this.params.btnCancel!.length > 0) {
Column() {
Text().width("100%").height(8).backgroundColor(colorF9F9F9);
this.buildButton(this.params.btnCancel!, -1, true);
}.backgroundColor(Color.White)
}
}.constraintSize({ maxHeight: "60%" }).justifyContent(FlexAlign.End)
}.width("100%").height("100%").justifyContent(FlexAlign.End)
.onClick(() => {
if (this.params.autoCancel) {
MyDialogParams.close(this.params);
this.params.cancel?.();
}
})
}
}
@CustomDialog
struct DateTimeDialogBuilder {
controller: CustomDialogController;
params!: DateTimeParams;
private curDate: Date = new Date();
aboutToAppear() {
if (!this.params.selectedDate) this.params.selectedDate = new Date();
this.curDate.setTime(this.params.selectedDate.getTime());
if (typeof this.params.minDate === 'string') this.params.minDate = new Date(Date.parse(this.params.minDate as string));
if (typeof this.params.maxDate === 'string') this.params.maxDate = new Date(Date.parse(this.params.maxDate as string));
// 为了方便写,所以默认为空字符串
this.params.btnOK ??= "";
this.params.btnCancel ??= "";
}
@Builder
builderTitleBar() {
if ((this.params.title && this.params.title.length > 0) || (this.params.btnOK && this.params.btnOK.length > 0) || (this.params.btnCancel && this.params.btnCancel.length > 0)) {
Row() {
Row() {
if (this.params.btnCancel!.length > 0 || this.params.btnOK!.length > 0) {
Button(this.params.btnCancel!.length > 0 ? this.params.btnCancel : this.params.btnOK)
.fontSize(16)
.backgroundColor(Color.Transparent)
.fontColor(color999999)
.onClick(() => {
MyDialogParams.close(this.params)
this.params.btnCancelClick?.();
})
.visibility(this.params.btnCancel!.length > 0 ? Visibility.Visible : Visibility.Hidden)
}
}.constraintSize({ minWidth: 16 })
Text(this.params.title)
.fontSize(16)
.padding({ left: 8, right: 8, top: 15, bottom: 15 })
.fontColor(color333333)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.textAlign(TextAlign.Center)
.layoutWeight(1)
Row() {
if (this.params.btnCancel!.length > 0 || this.params.btnOK!.length > 0) {
Button(this.params.btnOK!.length > 0 ? this.params.btnOK : this.params.btnCancel)
.fontSize(16)
.backgroundColor(Color.Transparent)
.fontColor(titleBarColor)
.onClick(() => {
MyDialogParams.close(this.params);
this.params.btnOKClick?.(this.curDate);
})
.visibility(this.params.btnOK!.length > 0 ? Visibility.Visible : Visibility.Hidden)
}
}.constraintSize({ minWidth: 16 })
}.margin({ top: 5 })
Text().width("100%").height(1).backgroundColor(line)
}
}
@Builder
buildBody() {
Column() {
this.builderTitleBar()
Column() {
Row() {
if (this.params.type != "Time") {
DatePicker({ start: this.params.minDate as Date, end: this.params.maxDate as Date, selected: this.curDate })
// .onDateChange((value: Date) => {
// this.curDate.setTime(value.getTime());
// if (this.params.onChange) this.params.onChange(this.curDate);
// })
.onChange((value) => {
this.curDate.setFullYear(value.year ?? 0, value.month, value.day);
if (this.params.onChange) this.params.onChange(this.curDate);
})
.layoutWeight(2)
}
if (this.params.type != "Date") {
TimePicker({ selected: this.curDate }).useMilitaryTime(true).onChange((value: TimePickerResult) => {
this.curDate.setHours(value.hour, value.minute);
if (this.params.onChange) this.params.onChange(this.curDate);
}).layoutWeight(1)
}
}.padding({ left: 16, right: 16 })
}.justifyContent(FlexAlign.Center).margin({ top: 16, bottom: 16 })
}
.backgroundColor(Color.White)
.width("100%")
.justifyContent(FlexAlign.Center)
.onClick(() => {
})
}
build() {
Column() {
Column() {
this.buildBody();
}.justifyContent(FlexAlign.End).height("100%")
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.width("100%")
.height("100%")
.onClick(() => {
if (this.params.autoCancel) {
MyDialogParams.close(this.params);
this.params.cancel?.();
}
})
}
}
@Component
struct MyDialogComponentBuilder {
private controller: CustomDialogController | null = null;
params!: MyDialogParams;
aboutToAppear() {
let defaultMarginForDialog: Offset = { dx: 0, dy: 18 };
this.params.autoCancel ??= true;
let type: MyDialogType = MyDialogParams.getDialogType(this.params);
if (type === "alert") {
this.controller = new CustomDialogController({
builder: AlertDialogBuilder({ params: this.params as AlertParams }),
cancel: () => {
MyDialogParams.removeFromStack(this.params);
this.params.cancel?.();
},
autoCancel: this.params.autoCancel,
customStyle: true,
offset: defaultMarginForDialog,
});
} else if (type === "progress") {
this.controller = new CustomDialogController({
builder: ProgressDialogBuilder({ params: this.params as ProgressParams }),
cancel: () => {
MyDialogParams.removeFromStack(this.params);
this.params.cancel?.();
},
autoCancel: this.params.autoCancel,
customStyle: true,
offset: defaultMarginForDialog,
});
} else if (type === "pullUpButton") {
this.controller = new CustomDialogController({
builder: PullUpButtonDialogBuilder({ params: this.params as PullUpButtonParams }),
cancel: () => {
MyDialogParams.removeFromStack(this.params);
this.params.cancel?.();
},
autoCancel: this.params.autoCancel,
customStyle: true,
offset: defaultMarginForDialog,
});
} else if (type === "datetime") {
this.controller = new CustomDialogController({
builder: DateTimeDialogBuilder({ params: this.params as DateTimeParams }),
cancel: () => {
MyDialogParams.removeFromStack(this.params);
this.params.cancel?.();
},
autoCancel: this.params.autoCancel,
customStyle: true,
offset: defaultMarginForDialog,
});
}
if (this.controller) {
MyDialogParams.setCloseFunc(this.params, () => {
this.controller?.close();
});
this.controller.open();
}
}
build() {
}
}
/**
* * [dialog] 为必传参数
*/
@Component
export struct MyDialogComponent {
public dialog?: MyDialog;
adapter: BaseAdapter<MyDialogParams> = new BaseAdapter([], true);
aboutToAppear() {
if (!this.dialog) throw new Error("MyDialogComponent 需要传入参数 [dialog],才可以正常使用")
MyObject.setAttr(this.dialog, "_open", (params: MyDialogParams) => {
MyDialogParams.setRemoveFromStackFunc(params, () => {
this.adapter.removeData(params);
});
this.adapter.addData(params);
});
MyObject.setAttr(this.dialog, "_close", (params: MyDialogParams, closeSlowly: boolean = false) => {
MyDialogParams.close(params);
});
}
build() {
Column() {
List() {
LazyForEach(this.adapter, (itemData: MyDialogParams, index) => {
ListItem() {
MyDialogComponentBuilder({ params: itemData })
}
}, (itemData: MyDialogParams, index) => {
return this.adapter.getKeyGenerator(itemData, index);
})
}.listDirection(Axis.Horizontal).width(1)
}.width(0).height(0)
}
}
@Entry
@Component
struct Test {
dialog = new MyDialog();
count: number = 0;
build() {
Column({ space: 16 }) {
MyDialogComponent({ dialog: this.dialog });
Button('警告框').onClick(() => {
this.dialog.alert({ message: "哈哈哈", autoCancel: false });
})
Button('下拉选择').onClick(() => {
// let pullUp = new PullUpButtonParams();
// pullUp.btnList = ["1", "1", "1", "1",];
// pullUp.btnCancel = "关闭";
// this.dialog.open("pullUpButton", pullUp);
this.dialog.pullUpButton({ btnList: ["1", "1", "1", "1",], btnCancel: "关闭" })
})
Button('日期选择').onClick(() => {
let datetime = new DateTimeParams();
datetime.btnOK = "确定";
this.dialog.open("datetime", datetime);
})
}.width("100%")
}
}
MyDialog.ets
import promptAction from '@ohos.promptAction';
export type typeAll = Object | Function | string | number | null | undefined;
export class MyObject {
static setAttr(params: Object, key: string, value: typeAll) {
if (params) (params as Record<string, typeAll>)[key] = value;
}
static getAttr(params: Object, key: string): typeAll {
if (params) return (params as Record<string, typeAll>)[key];
return undefined;
}
}
/**
* 对话框类型
*/
export type MyDialogType = "alert" | "progress" | "pullUpButton" | "datetime";
export class MyDialogParams {
/**
* 是否自动关闭
*/
autoCancel?: boolean = true;
/**
* 自动关闭时的回调
*/
cancel?: () => void;
dialog?: MyDialog;
/**
* 获取对话框类型
* @param defaultType 默认为 "alert"
*/
static getDialogType(params: MyDialogParams, defaultType: MyDialogType = "alert"): MyDialogType {
return MyObject.getAttr(params, "_type") as MyDialogType ?? defaultType;
}
static setDialogType(params: MyDialogParams, type: MyDialogType) {
MyObject.setAttr(params, "_type", type);
}
/**
* 从当前堆栈中移除
*/
static removeFromStack(params: MyDialogParams) {
(MyObject.getAttr(params, "_removeParams") as Function)?.();
}
static setRemoveFromStackFunc(params: MyDialogParams, removeParams: () => void) {
MyObject.setAttr(params, "_removeParams", removeParams);
}
/**
* 关闭弹窗
*/
static close(params: MyDialogParams) {
(MyObject.getAttr(params, "_close") as Function)?.();
}
static setCloseFunc(params: MyDialogParams, close: () => void) {
MyObject.setAttr(params, "_close", () => {
MyDialogParams.removeFromStack(params);
close?.();
});
}
}
/**
* 提示框
*/
export class AlertParams extends MyDialogParams {
title?: string = "";
message: string = "";
btnOK?: string = "确定";
btnOKClick?: () => void;
btnCancel?: string = "";
btnCancelClick?: () => void;
}
/**
* 进度框(progress 有值,就开启进度条)
*/
export class ProgressParams extends MyDialogParams {
message?: string;
progress?: number;
updateProgress?: (progress: number, message?: string) => void;
}
/**
* 底部弹出按钮框
*/
export class PullUpButtonParams extends MyDialogParams {
btnList: string[] = [];
btnCancel?: string;
btnClick?: (btnName: string, index?: number) => void;
}
export class DateTimeParams extends MyDialogParams {
selectedDate?: Date;
type: "DateTime" | "Date" | "Time" = "Date";
title?: string;
minDate?: string | Date;
maxDate?: string | Date;
btnOK?: string;
btnOKClick?: (selectedDate: Date) => void;
btnCancel?: string;
btnCancelClick?: () => void;
onChange?: (selectedDate: Date) => void;
}
export class OverlayParams extends MyDialogParams {
message?: string;
showTime?: number = 5000;
}
/**
* * 1. close closeSlowly 暂时无法使用,等以后能用的时候,再来调整
*/
export class MyDialog {
alert(params: AlertParams) {
this.open("alert", params);
return params;
}
progress(params: ProgressParams) {
this.open("progress", params);
return params;
}
pullUpButton(params: PullUpButtonParams) {
if (params && params.btnList.length > 0) {
this.open("pullUpButton", params);
}
return params;
}
datetime(params: DateTimeParams) {
this.open("datetime", params);
return params;
}
open(type: MyDialogType, params: MyDialogParams) {
params.dialog = this;
MyObject.setAttr(params, "_type", type);
(MyObject.getAttr(this, "_open") as Function)?.(params);
}
close(params: MyDialogParams, closeSlowly: boolean = false) {
// 为了防止操作过快的情况,所以延迟执行
setTimeout(() => {
(MyObject.getAttr(this, "_close") as Function)?.(params, closeSlowly);
}, 10);
}
toast(message: string, duration?: number, bottom?: string | number) {
promptAction.showToast({ message: message, duration: duration, bottom: bottom, })
}
static showToast(message: string, duration?: number, bottom?: string | number) {
promptAction.showToast({ message: message, duration: duration, bottom: bottom, })
}
showError(message: string, btnOKClick?: () => void, title: string = "提示", btnOK: string = "确定") {
if (message && message.length > 0) this.alert({ title: title, message: message, btnOK: btnOK, btnOKClick: btnOKClick, })
}
showErrorCannotAutoClose(message: string, btnOKClick?: () => void, title: string = "提示", btnOK: string = "确定") {
if (message && message.length > 0) this.alert({
autoCancel: false,
title: title,
message: message,
btnOK: btnOK,
btnOKClick: btnOKClick,
})
}
showAlertDialog(msg: string, btnOKClick: () => void, btnCancelClick?: () => void, autoClose: boolean = true) {
this.alert({
autoCancel: autoClose,
title: "提示",
message: msg,
btnOK: "确定",
btnOKClick: btnOKClick,
btnCancel: "取消",
btnCancelClick: btnCancelClick,
});
}
showAlertDialogCustomize(msg: string, title: string = "提示", btnOK: string = "确定", btnOKClick: () => void, btnCancel?: string, btnCancelClick?: () => void, autoClose: boolean = true): void {
this.alert({
autoCancel: autoClose,
title: title,
message: msg,
btnOK: btnOK,
btnOKClick: btnOKClick,
btnCancel: btnCancel,
btnCancelClick: btnCancelClick,
});
}
}
MyButton.ets
@Component
export struct MyButton {
text: string = "";
click?: () => void;
styleForDisable: number = 0;
isEnable: boolean = true;
buttonHeight: number | string | null = 44;
buttonWidth: number | string | null = "100%";
private isFocus: boolean = false;
@State mFontColor: number | null = 0;
@State mBackgroundColor: number | null = 0;
@State mBorderColor: number | null = 0;
readonly colorForButton: (number | null)[][] = [[0xffffffff, 0xffE5431B, null], [0xffffffff, 0xffFF8A8A, null], [0xffffffff, 0xffFFEEEE, null]];
aboutToAppear() {
this.refreshColor();
}
refreshColor() {
let colorIndex = 0;
if (this.isEnable) {
if (this.isFocus) colorIndex = 1;
} else {
if (this.styleForDisable == 1) colorIndex = 0;
else colorIndex = 2;
}
let fontColor = this.colorForButton[colorIndex][0];
let backgroundColor = this.colorForButton[colorIndex][1];
let borderColor = this.colorForButton[colorIndex][2];
if (!this.isEnable && this.styleForDisable == 1) {
if (backgroundColor != null) backgroundColor = ((((backgroundColor & 0xff000000) >>> 1) & 0xff000000) | (backgroundColor & 0xffffff));
if (borderColor != null) borderColor = ((((borderColor & 0xff000000) >>> 1) & 0xff000000) | (borderColor & 0xffffff));
}
this.mFontColor = fontColor;
this.mBackgroundColor = backgroundColor;
this.mBorderColor = borderColor;
}
build() {
Text(this.text)
.fontColor(this.mFontColor)
.fontSize(16)
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(this.buttonWidth)
.height(this.buttonHeight)
.backgroundColor(this.mBackgroundColor ?? null)
.padding({ left: 12, right: 12 })
.borderRadius(5)
.borderColor(this.mBorderColor)
.borderWidth(this.mBorderColor ? 1 : 0)
.textAlign(TextAlign.Center)
.onClick(() => {
if (this.isEnable && this.click) this.click();
})
.onTouch(this.isEnable ? (event) => {
if (event.type == TouchType.Down) {
this.isFocus = true;
this.refreshColor();
} else if (event.type == TouchType.Up || event.type == TouchType.Cancel) {
this.isFocus = false;
this.refreshColor();
}
} : null)
}
}
MyBaseAdapter.ets
export class BaseAdapter<T> implements IDataSource {
private listeners: DataChangeListener[] = new Array<DataChangeListener>();
private _dataList: T[];
private _keyList: (string | null)[] = [];
private cacheKey: boolean;
private keyIndex: number = 0;
constructor(dataList?: T[], cacheKey: boolean = false) {
this._dataList = dataList ?? [];
this.cacheKey = cacheKey;
if (this.cacheKey) this._keyList = new Array(this._dataList.length);
}
public get dataList(): T[] {
return this._dataList;
}
public set dataList(dataList: T[]) {
this._dataList = dataList;
if (this.cacheKey) this._keyList = new Array(this._dataList.length);
}
public refreshDatas(dataList: T[]) {
this._dataList = dataList;
if (this.cacheKey) this._keyList = new Array(this._dataList.length);
this.notifyDataReload();
}
// 如果数据没有主键的时候,请使用这种方式来生成
public getKeyGenerator(t: T, index: number): string {
if (this.cacheKey) {
let key: string | null = this._keyList[index];
if (typeof key === 'string') return key;
key = this.newKey();
this._keyList[index] = key;
return key;
}
return this.newKey();
}
private newKey(): string {
return (this.keyIndex++).toString();
}
public getCount(): number {
return this._dataList.length;
}
public refreshData(t: T) {
let index = this._dataList.indexOf(t);
if (index >= 0) {
if (this.cacheKey) this._keyList[index] = this.newKey();
this.notifyDataChange(index);
}
}
public addData(t: T): void {
this._dataList.push(t);
if (this.cacheKey) this._keyList.push(null);
this.notifyDataReload();
}
public addDatas(ts: T[]): void {
if (ts && ts.length > 0) {
if (ts.length == 1) {
this._dataList.push(ts[0]);
if (this.cacheKey) this._keyList.push(null);
this.notifyDataReload();
} else {
for (let data of ts) {
this._dataList.push(data);
if (this.cacheKey) this._keyList.push(null);
}
this.notifyDataReload();
}
}
}
public insetData(index: number, ...ts: T[]) {
if (ts && ts.length > 0 && index >= 0 && index <= ts.length) {
for (let data of ts) {
this._dataList.splice(index, 0, data);
if (this.cacheKey) this._keyList.splice(index, 0, null);
index++;
}
this.notifyDataReload();
}
}
removeDataByIndex(index: number) {
if (index >= 0 && index < this._dataList.length) {
this._dataList.splice(index, 1);
if (this.cacheKey) this._keyList.splice(index, 1);
this.notifyDataReload();
}
}
removeData(t: T) {
let index = this._dataList.indexOf(t);
if (index >= 0) {
this._dataList.splice(index, 1);
if (this.cacheKey) this._keyList.splice(index, 1);
this.notifyDataReload();
}
}
removeDatas(ts: T[]) {
if (ts && ts.length > 0) {
if (ts.length == 1) {
let index = this._dataList.indexOf(ts[0]);
if (index >= 0) {
this._dataList.splice(index, 1);
if (this.cacheKey) this._keyList.splice(index, 1);
this.notifyDataReload();
}
} else {
for (let data of ts) {
let index = this._dataList.indexOf(data);
if (index >= 0) {
this._dataList.splice(index, 1);
if (this.cacheKey) this._keyList.splice(index, 1);
}
}
this.notifyDataReload();
}
}
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
this.listeners.push(listener);
}
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
this.listeners.splice(pos, 1);
}
}
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded();
})
}
notifyDataAdd(index: number): void {
this.listeners.forEach(listener => {
listener.onDataAdd(index);
})
}
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index);
})
}
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index);
})
}
notifyDataMove(from: number, to: number): void {
this.listeners.forEach(listener => {
listener.onDataMove(from, to);
})
}
public totalCount(): number {
return this._dataList.length;
}
public getData(index: number): T {
return this._dataList[index];
}
public getDataIndex(t: T) {
return this._dataList.indexOf(t);
}
}