一、创建service
ionic g service services/picker/picker
二、picker.service.ts内容
import {Injectable} from '@angular/core';
import {PickerController} from '@ionic/angular';
import {PickerColumn} from '@ionic/core';
@Injectable({
providedIn: 'root'
})
export class PickerService {
// 存所有数据,格式
// 0: (2) ["00", "01"]
// 1: (2) ["10", "11"]
// 10: (3) ["100", "101", "102"]
// 11: (3) ["110", "111", "112"]
// "": (2) ["0", "1"]
// 00: (3) ["000", "001", "002"]
// 01: (3) ["010", "011", "012"]
private options = [];
// 改变滑动时,当前的数据,格式
// [
// ['0','1'],
// ["00", "01"]
// ["000", "001", "002"]
// ]
private currentOptions = [];
// 选中的坐标
private selects = [];
// 改变滑动时,选中的坐标
private currentSelects = [];
constructor(public pickercontroller: PickerController) {
}
async openPicker(numColumns = 1, numOptions = 5, multiColumnOptions, callback) {
if (this.options.length === 0) {
this.options = multiColumnOptions;
this.currentOptions[0] = multiColumnOptions[''];
this.currentSelects[0] = 0;
for (let pos = 1; pos < numColumns; pos++) {
this.currentOptions[pos] = this.options[this.currentOptions[pos - 1][this.currentSelects[pos - 1]]];
this.currentSelects[pos] = 0;
}
}
const picker: HTMLIonPickerElement = await this.pickercontroller.create({
columns: this.getColumns(numColumns, this.currentOptions),
buttons: [
{
text: '取消',
role: 'cancel'
},
{
text: '确定',
handler: value => {
// console.log(`Got Value ${value}`);
// tslint:disable-next-line:forin
for (const val in value) {
this.selects[val] = value[val].value;
}
callback(JSON.stringify(value));
}
}
]
});
picker.addEventListener('ionPickerColChange', async (event: any) => {
const data = event.detail;
// tslint:disable-next-line:radix
const currentColumnNum = parseInt(data.name);
this.currentSelects[data.name] = data.selectedIndex;
let pickerColumns: PickerColumn[] = [];
pickerColumns = picker.columns;
if (currentColumnNum < numColumns - 1) {
for (let columnPos = 0; columnPos < numColumns; columnPos++) {
if (columnPos > currentColumnNum) {
this.currentOptions[columnPos] = this.options[this.currentOptions[columnPos - 1][this.currentSelects[columnPos - 1]]];
this.currentSelects[columnPos] = 0;
pickerColumns[columnPos] = {
name: `${columnPos}`,
options: this.getColumnOptions(0, this.currentOptions[columnPos].length, [this.currentOptions[columnPos]]),
selectedIndex: columnPos > currentColumnNum ? 0 : picker.columns[columnPos].selectedIndex,
};
}
}
picker.columns = pickerColumns;
picker.forceUpdate();
}
});
await picker.present();
}
getColumns(numColumns, columnOptions) {
const columns = [];
for (let i = 0; i < numColumns; i++) {
columns.push({
name: `${i}`,
options: this.getColumnOptions(i, columnOptions[i].length, columnOptions),
selectedIndex: this.selects[i] ? this.selects[i] : 0
});
}
return columns;
}
getColumnOptions(columnIndex, numOptions, columnOptions) {
const options = [];
for (let i = 0; i < numOptions; i++) {
options.push({
text: columnOptions[columnIndex][i % numOptions],
value: i,
});
}
return options;
}
}
三、使用方法
1.使用页面的html
<ion-row no-padding (click)="change()">
<ion-col size="auto" align-items-center>选择的数据结果<label>*</label></ion-col>
<ion-col align-self-center text-right>{{selectData}}</ion-col>
</ion-row>
2.使用页面的ts
// 数据集合
datas = {};
// 选中的内容
selectData = '';
// 列数
numColumns = 3;
constructor(
public pickerService: PickerService,
) {
}
change() {
// 三列测试数据
this.datas[''] = ['0', '1'];
this.datas['0'] = ['00'];
this.datas['1'] = ['10', '11'];
this.datas['00'] = ['000', '001', '002'];
this.datas['10'] = ['100', '101', '102'];
this.datas['11'] = ['110', '111', '112'];
// 四列测试数据
// this.datas[''] = ['0', '1'];
// this.datas['0'] = ['00'];
// this.datas['1'] = ['10', '11'];
// this.datas['00'] = ['000', '001'];
// this.datas['10'] = ['100', '101'];
// this.datas['11'] = ['110', '111', '112'];
// this.datas['000'] = ['0000'];
// this.datas['001'] = ['0010'];
// this.datas['100'] = ['1000'];
// this.datas['101'] = ['1010'];
// this.datas['110'] = ['1100'];
// this.datas['111'] = ['1110'];
// this.datas['112'] = ['1120'];
this.pickerService.openPicker(this.numColumns, this.datas[0].length, this.datas, result => {
this.selectData = '';
for (let pos = 0; pos < this.numColumns; pos++) {
this.selectData = this.selectData + JSON.parse(result)[pos].text + ',';
}
}
);
}
四、解决选择选项时重叠问题
修改/node_modules/@ionic/core/dist/esm/ion-datetime_3-ios.entry.js、/node_modules/@ionic/core/dist/esm/ion-datetime_3-md.entry.js文件。
注意:@ionic/core会影响到修改内容。可参考https://github.com/zwlccc/ionic4-city-picker
update(y, duration, saveY) {
if (!this.optsEl) {
return;
}
// ensure we've got a good round number :)
let translateY = 0;
let translateZ = 0;
const { col, rotateFactor } = this;
const selectedIndex = col.selectedIndex = this.indexForY(-y);
const durationStr = (duration === 0) ? '' : duration + 'ms';
const scaleStr = `scale(${this.scaleFactor})`;
const children = this.optsEl.children;
const children_length = this.optsEl.children.length;
const options_length = col.options.length;
const length = children_length < options_length ? options_length : children_length;
for (let i = 0; i < length; i++) {
const button = children[i];
const opt = col.options[i];
const optOffset = (i * this.optHeight) + y;
let transform = '';
if (rotateFactor !== 0) {
const rotateX = optOffset * rotateFactor;
if (Math.abs(rotateX) <= 90) {
translateY = 0;
translateZ = 90;
transform = `rotateX(${rotateX}deg) `;
}
else {
translateY = -9999;
}
}
else {
translateZ = 0;
translateY = optOffset;
}
const selected = selectedIndex === i;
transform += `translate3d(0px,${translateY}px,${translateZ}px) `;
if (this.scaleFactor !== 1 && !selected) {
transform += scaleStr;
}
// Update transition duration
if (this.noAnimate) {
if (opt) {
opt.duration = 0;
}
if (button) {
button.style.transitionDuration = '';
}
}
else if (opt) {
if (duration !== opt.duration) {
opt.duration = duration;
if (button) {
button.style.transitionDuration = durationStr;
}
}
}
// Update transform
if (opt) {
if (transform !== opt.transform) {
opt.transform = transform;
if (button) {
button.style.transform = transform;
}
}
}
// Update selected item
if (opt) {
if (selected !== opt.selected) {
opt.selected = selected;
if (selected && button) {
button.classList.add(PICKER_OPT_SELECTED);
}
else if (button) {
button.classList.remove(PICKER_OPT_SELECTED);
}
}
}
}
this.col.prevSelected = selectedIndex;
if (saveY) {
this.y = y;
}
if (this.lastIndex !== selectedIndex) {
// have not set a last index yet
hapticSelectionChanged();
this.lastIndex = selectedIndex;
}
}
render() {
const col = this.col;
const Button = 'button';
const mode = getIonMode(this);
return (h(Host, { class: {
[mode]: true,
'picker-col': true,
'picker-opts-left': this.col.align === 'left',
'picker-opts-right': this.col.align === 'right'
}, style: {
'max-width': this.col.columnWidth
} }, col.prefix && (h("div", { class: "picker-prefix", style: { width: col.prefixWidth } }, col.prefix)), h("div", { class: "picker-opts", style: { maxWidth: col.optionsWidth }, ref: el => this.optsEl = el }, col.options.map((o, index) => h(Button, { type: "button", class: { 'picker-opt': true, 'picker-opt-disabled': !!o.disabled, 'picker-opt-selected': o.selected }, style: { transform: o.transform ? o.transform : 'translate3d(0px, -9999px, 90px)', 'transition-duration': o.duration ? o.duration : TRANSITION_DURATION + 'ms' }, "opt-index": index }, o.text))), col.suffix && (h("div", { class: "picker-suffix", style: { width: col.suffixWidth } }, col.suffix))));
}