需要做一个带时间的DateField控件。不做啰嗦,直接上代码。
App:
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:control="com.view.control.*"> <fx:Script> <![CDATA[ [Bindable]private var timeMode:Boolean; protected function button1_clickHandler(event:MouseEvent):void { timeMode = !timeMode; } ]]> </fx:Script> <s:layout> <s:VerticalLayout/> </s:layout> <s:Button label="Change Mode" click="button1_clickHandler(event)"/> <control:DateTimeField timeStampMode="{timeMode}" yearNavigationEnabled="true"/> </s:Application>
DateTimeField:
package com.view.control { import flash.events.Event; import flash.events.FocusEvent; import mx.controls.DateChooser; import mx.controls.DateField; import mx.controls.dataGridClasses.DataGridListData; import mx.controls.listClasses.BaseListData; import mx.controls.listClasses.ListData; import mx.core.ClassFactory; import mx.core.IFactory; import mx.events.CalendarLayoutChangeEvent; import mx.events.DropdownEvent; import mx.events.FlexEvent; import mx.formatters.DateFormatter; import mx.logging.Log; import mx.managers.PopUpManager; import mx.managers.PopUpManagerChildList; import mx.utils.ObjectUtil; public class DateTimeField extends DateField { // using custom data to avoid beeing overwritten protected var _cData:Object; protected var _cListData:BaseListData; protected var _cSelectedDate:Date = null; // copied vars protected var updateDateFiller:Boolean; protected var selectedDateSet:Boolean; protected var selectedDateChanged:Boolean = false; protected var show:Boolean = false; private var _timeStampMode:Boolean = true; private var _timeStampModeChanged:Boolean; private var _dateTimeChooserDropdownFactory:IFactory = new ClassFactory(DateTimeChooser); private var _dateChooserDropdownFactory:IFactory = new ClassFactory(DateChooser); private var _dropdownFactory:IFactory = new ClassFactory(DateChooser); public function DateTimeField() { super(); parseFunction = customerParseFunction; this.labelFunction = labelDateTime; this.addEventListener(DropdownEvent.OPEN,handleDropdown); this.addEventListener(DropdownEvent.CLOSE,handleDropdown); } // ------------------------------- // own functions // ------------------------------- public function set timeStampMode(value:Boolean):void { _timeStampMode = value; _timeStampModeChanged = true; if(value) { dropdownFactory = _dateTimeChooserDropdownFactory; } else { dropdownFactory = _dateChooserDropdownFactory; } invalidateProperties(); invalidateSize(); } public function get timeStampMode():Boolean { return _timeStampMode; } protected function handleDropdown(e:DropdownEvent):void { if (e.type == DropdownEvent.CLOSE) { // save new date without beeing cropped if (ObjectUtil.dateCompare(selectedDate,dropdown.selectedDate) != 0) { setUpdateDate(); } show = false; } else { show = true; dateFiller(_cSelectedDate); } } private function setUpdateDate():void { selectedDate = dropdown.selectedDate; updateData(); } protected function updateData():void { // if new date selected,save it to the data-binding variable if (data && selectedDate) { if (listData && listData is DataGridListData) data[DataGridListData(listData).datafield] = selectedDate; else if (listData is ListData && ListData(listData).labelField in value) data[ListData(listData).labelField] = selectedDate; else if (value is String) data = selectedDate.toString(); else data = value as Date; } } // ------------------------------- // change Label // ------------------------------- protected function numberToTime(value:Number):String { return (value >= 10) ? String(value) : ("0" + value); } protected function labelDateTime(value:Date):String { if (value) { if(timeStampMode) { return DateField.datetoString(value,formatString) + " " + numberToTime(value.hours) + ":" + numberToTime(value.minutes); } else { return DateField.datetoString(value,formatString); } } else { return ""; } } // ------------------------------- // overwritten data functions // ------------------------------- override public function get data():Object { return _cData; } override public function set data(value:Object):void { var newDate:Date; _cData = value; if (_cListData && _cListData is DataGridListData) newDate = _cData[DataGridListData(_cListData).datafield]; else if (_cListData is ListData && ListData(_cListData).labelField in _cData) newDate = _cData[ListData(_cListData).labelField]; else if (_cData is String) newDate = new Date(Date.parse(data as String)); else newDate = _cData as Date; if (!selectedDateSet) { selectedDate = newDate; selectedDateSet = false; } dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE)); } override public function get listData():BaseListData { return _cListData; } override public function set listData(value:BaseListData):void { _cListData = value; } //---------------------------------- // selectedDate //---------------------------------- [Bindable("change")] [Bindable("valueCommit")] [Bindable("selectedDateChanged")] [Inspectable(category="General")] override public function get selectedDate():Date { return _cSelectedDate; } /** * @private */ override public function set selectedDate(value:Date):void { if (ObjectUtil.dateCompare(_cSelectedDate,value) == 0) return; selectedDateSet = true; _cSelectedDate = value; updateDateFiller = true; selectedDateChanged = true; invalidateProperties(); // Trigger bindings to 'selectedData'. dispatchEvent(new Event("selectedDateChanged")); dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT)); } //-------------------------------------------------------------------------- // // Overridden methods: UIComponent // //-------------------------------------------------------------------------- override protected function commitProperties():void { super.commitProperties(); if (updateDateFiller) { updateDateFiller = false; dateFiller(_cSelectedDate); } if (selectedDateChanged) { selectedDateChanged = false; dropdown.selectedDate = _cSelectedDate; } if(_timeStampModeChanged) { _timeStampModeChanged = false; this.dispatchEvent(new Event(Event.REMOVED_FROM_STAGE)); var editable:Boolean = textInput.editable; super.createChildren(); this.yearNavigationEnabled = this.yearNavigationEnabled; textInput.editable = editable; } } //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- private function dateFiller(value:Date):void { if (labelFunction != null) textInput.text = labelFunction(value); else textInput.text = datetoString(value,formatString); } //-------------------------------------------------------------------------- // // Event handlers // //-------------------------------------------------------------------------- override protected function downArrowButton_buttonDownHandler(event:FlexEvent):void { if (show) { close(); } else { if(text == "") { selectedDate = new Date(); dropdown.selectedDate = selectedDate; } open(); } dateFiller(_cSelectedDate); } //---------------------------------- // dropdownFactory // Overwrite,to include the own DateTimeChooser class //---------------------------------- [Bindable("dropdownFactoryChanged")] override public function get dropdownFactory():IFactory { return _dropdownFactory; } override public function set dropdownFactory(value:IFactory):void { _dropdownFactory = value; dispatchEvent(new Event("dropdownFactoryChanged")); } // ------------------------------- // Remove focus handler // ------------------------------- override protected function focusOutHandler(event:FocusEvent):void { setActualDate(); } override protected function textInput_changeHandler(event:Event):void { super.textInput_changeHandler(event); setActualDate(); } private function setActualDate():void { if(text == "") { selectedDate = null; } else { var inputDate:Date = customerParseFunction(text); text = labelDateTime(inputDate); selectedDate = inputDate; } } override public function open():void { selectedDate = DateFormatter.parseDateString(text); super.open(); } private function customerParseFunction(text:String,format:String = null):Date { var date:Date = DateFormatter.parseDateString(text); if(date && (date.fullYear >9999 || date.fullYear < 1000)) { date = null; } return date; } } }
DateTimeChooser:
package com.view.control { import flash.events.FocusEvent; import flash.events.KeyboardEvent; import flash.ui.Keyboard; import mx.controls.DateChooser; import mx.controls.Label; import mx.controls.TextInput; import mx.events.CalendarLayoutChangeEvent; public class DateTimeChooser extends DateChooser { private var textInput:TextInput; private var label:Label; [Bindable] private var startTime:String = ""; private var _timeLabel:String = ""; public function DateTimeChooser() { super(); timeLabel = "Time"; } override public function get selectedDate():Date { // add time var d:Date = (super.selectedDate) ? super.selectedDate : new Date(); var times:Array = (textInput) ? textInput.text.split(":") : startTime.split(":"); if (times.length > 1) { d.hours = times[0]; d.minutes = times[1]; } // update data super.selectedDate = d; return d; } override public function set selectedDate(value:Date):void { if (value) { startTime = to2Digits(value.hours) + ":" + to2Digits(value.minutes); if (textInput) textInput.text = startTime; super.selectedDate = value; } } [Bindable] public function get timeLabel():String { return _timeLabel; } public function set timeLabel(value:String):void { _timeLabel = value; } private function to2Digits(value:Number = NaN):String { if (isNaN(value)) return "00"; else if (value < 10)return "0" + value; else return "" + value; } private function checkTimeBox(e:KeyboardEvent):void { if (e.keyCode == Keyboard.ENTER) // bei ENTER schließen { dispatchEvent(new CalendarLayoutChangeEvent(CalendarLayoutChangeEvent.CHANGE,false,selectedDate)); } else // ansonsten überprüfe ob der String stimmt { var values:Array = String(textInput.text).match(/[0-9]{2}/g); textInput.text = to2Digits(values[0]) + ":" + to2Digits(values[1]); } } private function timeFocusOut(e:FocusEvent):void { dispatchEvent(new CalendarLayoutChangeEvent(CalendarLayoutChangeEvent.CHANGE,selectedDate)); } /** * @private * Erstellt noch den Time NumericStepper */ override protected function createChildren():void { super.createChildren(); if (!textInput){ textInput = new Textinput(); textInput.text = startTime; textInput.maxChars = 5; textInput.addEventListener(KeyboardEvent.KEY_DOWN,checkTimeBox); textInput.owner = this; textInput.addEventListener(FocusEvent.FOCUS_OUT,timeFocusOut); addChild(textInput); } if (!label) { label = new Label(); label.setStyle("textAlign","right"); label.text = timeLabel; addChild(label); } } /** * @private */ override protected function updatedisplayList(unscaledWidth:Number,unscaledHeight:Number):void { super.updatedisplayList(unscaledWidth,unscaledHeight); var borderThickness:Number = getStyle("borderThickness"); var cornerRadius:Number = getStyle("cornerRadius"); var borderColor:Number = getStyle("borderColor"); var w:Number = unscaledWidth - borderThickness*2; var h:Number = unscaledHeight - borderThickness*2; textInput.setActualSize(48,20); textInput.move(w - 50,h - 22); label.setActualSize(36,20); label.move(textInput.x - 40,h - 21); } } }