Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ExtJS自定義控件 之一:datetimefield控件

ExtJS自定義控件 之一:datetimefield控件

編輯:關於Android編程

這一年都在使用ExtJS 5.0開發系統,經常會遇到的一個場景就是時間日期的選擇了。比如說,預定場地的時候就必須由用戶選擇預定的日期和時間。

可惜的是,ExtJS 5.0沒有自帶一個可以同時選擇日期時間的控件(ExtJS 6.0已經推出了,還沒用過,不知道加入這種控件沒~),通常偷懶的做法就是,先放一個日期控件,然後再放一個時間控件。用戶使用的時候,先選擇日期,再選擇時間,最後用很別扭的辦法將日期和時間拼裝起來。

理想的狀態是,提供給用戶一個可以同時選擇時間和日期的控件,並且數據是“日期+時間”的Date類型。既符合使用習慣,又方便開發。

故第二種偷懶的方式是,從網上扒一個現成的解決方案來用。此法最快,但是在過程中遇到了一個問題,現成可以搜索到的方案都有點舊,大多數還停留在ExtJS 2.X、3.X和4.X版本,自從ExtJS從4升級到5之後,API改變了許多,所以並不能直接使用。

最後只能是自己寫一個。准確來說,應該是拿了一份現成的代碼修改,這個代碼在ExtJS 5.0下不能正確運行,但是需要修改的量非常少,所以很感謝這份現成代碼的作者,可惜沒有署名,不知道是誰。

ExtJS 5.0上測試成功,實現方法是:

1、自定義一個時間選擇器TimePickerField,繼承自Ext.form.field.Base,由三個NumberField組成。

    Ext.define('MyApp.ux.DateTimeField.TimePickerField', {
        extend: 'Ext.form.field.Base',
        alias: 'widget.timepicker',

        alternateClassName: 'Ext.form.field.TimePickerField',

        requires: ['Ext.form.field.Number'],
        inputType: 'text',
        fieldLabel: '時間',
        labelWidth: 40,
        style: 'padding:4px 0; margin: 0; ',
        value: null,
        spinnerCfg: {
            width: 50,
        },

        initComponent: function() {
            var me = this;
            me.value = me.value || Ext.Date.format(new Date(), 'H:i:s');
            me.callParent(arguments);
            me.spinners = [];
            var cfg = Ext.apply({}, me.spinnerCfg, {
    //          readOnly: me.readOnly,
                disabled: me.disabled,
                style: 'float: left',
                listeners: {
                  change: {
                    fn: me.onSpinnerChange,
                    scope: me
                  }
                }
            });
            me.hoursSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, {
    //          minValue: -1,
    //          maxValue: 24,
                    minNum: 0,
                    maxNum: 23,
              }));
            me.minutesSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, {
    //          minValue: -1,
    //          maxValue: 60,
                        minNum: 0,
                        maxNum: 59,
              }));
            me.secondsSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, {
    //          minValue: -1,
    //          MAXVALUE: 60,
                        minNum: 0,
                        maxNum: 59,
              }));
            me.spinners.push(me.hoursSpinner, me.minutesSpinner, me.secondsSpinner);
        },

        onRender: function() {
            var me = this, spinnerWrapDom, spinnerWrap;
            me.callParent(arguments);
            spinnerWrap = Ext.get(Ext.DomQuery.selectNode('div', this.el.dom));
            me.callSpinnersFunction('render', spinnerWrap);
            this.el.dom.getElementsByTagName('input')[0].style.display = 'none';
            var newTimePicker = Ext.DomHelper.append(spinnerWrap, {
                tag: 'div',
                cls: 'x-form-clear-left'
            }, true);
            this.setRawValue(this.value);
        },
        _valueSplit: function(v) {
            if(Ext.isDate(v)) {
              v = Ext.Date.format(v, 'H:i:s');
            }
            var split = v.split(':');
            return {
                h: split.length > 0 ? split[0] : 0,
                m: split.length > 1 ? split[1] : 0,
                s: split.length > 2 ? split[2] : 0
            };
        },
        onSpinnerChange: function() {
            if(!this.rendered) {
              return;
            }
            //限制時間范圍
            var args = arguments; //this, newValue, oldValue, eOpts
            args[0].setValue( (args[1]>args[0].maxNum) ? args[0].minNum : args[0].value );
            args[0].setValue( (args[1]<args[0].minnum) ?="" args[0].maxnum="" :="" args[0].value="" );="" this.fireevent('change',="" this,="" this.getvalue(),="" this.getrawvalue());="" },="" 依次調用各輸入框函數,="" call="" each="" spinner's="" function="" callspinnersfunction:="" function(funname,="" args)="" {="" for(var="" i="0;" 

2、自定義一個DateTimePicker,繼承自Ext.picker.Date,實際上就是在原有的DateField的基礎上增加TimePicker和一個確認按鍵。

    Ext.define('MyApp.ux.DateTimeField.DateTimePicker', {
        extend: 'Ext.picker.Date',
        alias: 'widget.datetimepicker',
        requires: ['MyApp.ux.DateTimeField.TimePickerField','Ext.dom.Query'],

        todayText: '現在',
        timeLabel: '時間',
        buttonText: '確定',

        initComponent: function() {
            this.callParent();
            this.value = this.value || new Date();
        },
        onRender: function(container, position) {
            this.callParent(arguments);
            var me = this;


            //確認按鍵
            var btnCfg = Ext.apply({}, {}, {
                style: 'center',
                listeners: {
                    click: {
                        fn: function(){
                            this.confirmDate();
                        },
                        scope: me
                    }
                }
                });
            me.confirmBtn = Ext.create('Ext.Button', Ext.apply({}, btnCfg, {
                text: '確認',
            }));
            me.confirmBtn.render(this.el.child('div div.x-datepicker-footer'));


            if(!this.timefield) {
                this.timefield = Ext.create('MyApp.ux.DateTimeField.TimePickerField', {
                    fieldLabel: this.timeLabel,
                    labelWidth: 40,
                    value: Ext.Date.format(this.value, 'H:i:s'),
                });
            }

            this.timefield.ownerCt = this;//指定范圍
            this.timefield.on('change', this.timeChange, this);//

            var table = Ext.get(Ext.DomQuery.selectNode('table', this.el.dom));

            var tfEl = Ext.DomHelper.insertAfter(table, {
                tag: 'div',
                style: 'border:0px;',
                children: [{
                    tag: 'div',
                    cls: 'x-datepicker-footer ux-timefield'
                }]
            }, true);
            this.timefield.render(this.el.child('div div.ux-timefield'));

            var p = this.getEl().parent('div.x-layer');
            if(p) {
                p.setStyle("height", p.getHeight() + 31);
            }
        },
        // listener 時間域修改, timefield change
        timeChange: function(tf, time, rawtime) {
            this.value = this.fillDateTime(this.value);
        },
        fillDateTime: function(value) {
            if(this.timefield) {
                var rawtime = this.timefield.getRawValue();
                value.setHours(rawtime.h);
                value.setMinutes(rawtime.m);
                value.setSeconds(rawtime.s);
            }
            return value;
        },
        changeTimeFiledValue: function(value) {
            this.timefield.un('change', this.timeChange, this);
            this.timefield.setValue(this.value);
            this.timefield.on('change', this.timeChange, this);
        },
        setValue: function(value) {
            this.value = value;
            this.changeTimeFiledValue(value);
            return this.update(this.value);
        },
        getValue: function() {
            return this.fillDateTime(this.value);
        },
        handleDateClick: function(e, t) {
            var me = this,
                handler = me.handler;
            e.stopEvent();
            if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)) {
                me.doCancelFocus = me.focusOnSelect === false;
                me.setValue(this.fillDateTime(new Date(t.dateValue)));
                delete me.doCancelFocus;
                me.fireEvent('select', me, me.value);
                if(handler) {
                handler.call(me.scope || me, me, me.value);
                }
                me.onSelect();
            }
        },
        //確認按鍵 
        confirmDate: function(){
                var that = this;
                    that.fireEvent('select', that, that.value);//模擬用戶選擇
                    that.onSelect();
        },
        selectToday: function() {
            var me = this,
                btn = me.todayBtn,
                handler = me.handler;
            if(btn && !btn.disabled) {
                me.setValue(new Date());
                me.fireEvent('select', me, me.value);
                if(handler) {
                handler.call(me.scope || me, me, me.value);
                }
                me.onSelect();
            }
            return me;
        }
    });

3、將DateTimePicker裝載到Ext.form.field.Date中,初始化日期時間的格式。

    Ext.define('MyApp.ux.DateTimeField.DateTimeField', {
            extend: 'Ext.form.field.Date',
            alias: 'widget.datetimefield',
            requires: ['MyApp.ux.DateTimeField.DateTimePicker'],
            initComponent: function() {
                this.format = this.format;
                this.callParent();
            },
            format: 'Y-m-d H:i:s',
            createPicker: function() {
                var me = this,
                        format = Ext.String.format;
                return Ext.create('MyApp.ux.DateTimeField.DateTimePicker', {
                        ownerCt: me.ownerCt,
    //                  renderTo: document.body,
                        floating: true,
    //                  hidden: true,
                        focusOnShow: true,
                        minDate: me.minValue,
                        maxDate: me.maxValue,
                        disabledDatesRE: me.disabledDatesRE,
                        disabledDatesText: me.disabledDatesText,
                        disabledDays: me.disabledDays,
                        disabledDaysText: me.disabledDaysText,
                        format: me.format,
                        showToday: me.showToday,
                        startDay: me.startDay,
                        minText: format(me.minText, me.formatDate(me.minValue)),
                        maxText: format(me.maxText, me.formatDate(me.maxValue)),
                        listeners: {
                                scope: me,
                                select: me.onSelect
                        },
                        keyNavConfig: {
                                esc: function() {
                                    me.collapse();
                                }
                        }
                    });
            }
    });

將以上代碼拷到ux當中,調用的時候可以Ext.create之,也可以require之後直接使用alias。
效果嘛,就像下圖那樣:
效果圖
介紹完畢。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved