0

Ich habe eine Art "Fang 22" -Situation hier.Layout-Herausforderung bei der Verwendung von nativen Datum/Uhrzeit-Picker auf Android 5.1.x

Ich benutze Appcelerator Titatium SDK 5.1.2. Auf Android 5.1.x mit einer sehr kleinen Bildschirmgröße kann ich keine Lösung finden, um Datum und Uhrzeit mit den nativen Pickern korrekt auszuwählen. Ich muss ein <ScrollView> hinzufügen, um dem Benutzer zu ermöglichen, den Inhalt zu verschieben, um den Picker vollständig sichtbar zu machen. Wenn Sie dies jedoch unter Android 5.1.x tun, kann der Benutzer nicht zu früheren Monaten in der Datumswiedergabe zurück blättern. Wenn Sie ihn in ein <View> Steuerelement ändern, verhält sich die Datumsauswahl wie erwartet. Befindet sich ein Teil der Auswahl jedoch außerhalb des sichtbaren Bereichs, hat der Benutzer keine Möglichkeit, Werte von dort auszuwählen.

Ich habe ein einfaches Beispiel erstellt, um dies zu veranschaulichen. Kommentar in <ScrollView> statt <View> mit gleicher ID zu sehen Unterschied:

Ausblick:

<Alloy> 
    <Window class="container"> 
     <View id="form" onClick="clickHandler"> 
     <!-- 
     <ScrollView id="form" onClick="clickHandler"> 
     --> 
      <View id="formRow"> 
       <Label id="title">Picker demo</Label> 
      </View> 
      <View id="formRow"> 
       <Label id="label">Date</Label> 
       <TextField id="startDate" bubbleParent="true" editable="false"></TextField> 
      </View> 
      <View id="formRow"> 
       <Label id="label">Time</Label> 
       <TextField id="startTime" bubbleParent="true" editable="false"></TextField> 
      </View> 
     <!-- 
     </ScrollView> 
     --> 
     </View> 
    </Window> 
</Alloy> 

Stil:

".container": { 
    top: 20, 
    backgroundColor:"#fa0", 
    orientationModes: [Ti.UI.PORTRAIT] 
} 
"Label": { 
    width: Ti.UI.SIZE, 
    height: Ti.UI.SIZE, 
    backgroundColor: 'transparent', 
    left:10, 
    color: "#000" 
} 

"#title": { top:15, 
    font: { 
     fontSize: '25dp', 
     fontStyle: 'bold' 
    } 
} 
"#label": { top:0, 
    font: { 
     fontSize: '18dp', 
     fontStyle: 'bold' 
    } 
} 
"TextField": { font: { 
     fontSize: '18dp', 
     fontStyle: 'normal' 
    }, 
    backgroundColor:'orange' 
} 
"#formRow":{ 
    top:7, 
    height:Ti.UI.SIZE, 
    width:Ti.UI.FILL 
} 

"#startDate":{ 
    top:0, 
    width:150, 
    right:10, 
} 
"#startTime":{ 
    top:0, 
    width:70, 
    right:10 
} 
"#form":{ 
    showVerticalScrollIndicator:"true", 
    layout:"vertical" 
} 

Controller:

var Moment = require('alloy/moment'); 

function clickHandler(e){ 
    if(e && e.source){ 
     console.log("clickHandler. id="+e.source.id); 
     if(e.source.id === 'startDate'){ 
      openDatePicker(e); 
     } else if(e.source.id === 'startTime'){ 
      openTimePicker(e); 
     } 
    } 
} 

// Date/time utils: 
function getAsDate(date) { 
    // Return as Date object 
    var dt = null; 
    if(typeof date === 'number') { 
     dt = new Date(date); 
    } else if(date instanceof Date) { 
     dt = date; 
    } 
    return dt; 
}; 
function getDMY(date) { 
    var dt = getAsDate(date); 
    if(dt) { 
     return Moment(dt).format('DD-MM-YYYY'); 
    } 
    return null; 
} 

function getHMM(date) { 
    // Returns format: H:mm 
    var dt = getAsDate(date); 
    if(dt) { 
     return Moment(dt).format('H:mm'); 
    } 
    return null; 
} 
function fromDMY(dt){ 
    var date = Moment(dt, "DD-MM-YYYY"); 
    if(date){ 
     date = new Date(date); 
    } 
    return date; 
} 

function fromHMM(time){ 
    var datetime = Moment(time, "H:mm"); 
    if(datetime) { 
     return new Date(datetime); 
    } 
    return null; 
} 

function openDatePicker(){ 
    // Inner helper class to clean up and remove picker items 
    function cleanup(){ 
     console.log("openDatePicker.cleanup..."); 
     pickerOpen = null; 
     $.startDate.value = getDMY(picker.value); 
     $.formRow.remove(picker); 
     $.startDate.bubbleParent = true; 
     $.form.removeEventListener('click',cleanup); 
    } 

    var v = $.startDate.value; 
    if(v && fromDMY(v)) { 
     v = fromDMY(v); 
     console.debug("startDate.value=" + $.startDate.value + " --> v=" + v + " - type: " + typeof v); 
    }else{ 
     v = new Date(); 
    } 
    var picker = Ti.UI.createPicker({ 
      type:Ti.UI.PICKER_TYPE_DATE, 
      maxDate:new Date(), 
      top:35, 
      value:v 
    }); 
    $.formRow.add(picker); 
    $.startDate.bubbleParent = false; 
    $.form.addEventListener('click',cleanup); 
} 

function openTimePicker(){ 
    // Inner helper class to clean up and remove picker items 
    function cleanup(){ 
     console.log("openTimePicker.cleanup..."); 
     pickerOpen = null; 
     $.startTime.value = getHMM(picker.value); 
     $.formRow.remove(picker); 
     $.startTime.bubbleParent = true; 
     $.form.removeEventListener('click',cleanup); 
    } 

    var v = $.startTime.value; 
    if(v && fromHMM(v)) { 
     v = fromHMM(v); 
     console.debug("startTime.value=" + $.startTime.value + " --> v=" + v + " - type: " + typeof v); 
    }else{ 
     v = new Date(); 
    } 
    var picker = Ti.UI.createPicker({ 
      type:Ti.UI.PICKER_TYPE_TIME, 
      format24:true, 
      minuteInterval:5, 
      top:35, 
      value:v 
    }); 
    $.formRow.add(picker); 
    $.startTime.bubbleParent = false; 
    $.form.addEventListener('click',cleanup); 
} 

$.index.open(); 

Sorry für den langen Code (konnte es nicht wirklich kürzer machen) - aber es ist ein arbeiten Beispiel.

In anderen Android-Versionen hat die <ScrollView> keinen Vorrang vor der nativen Datumsauswahl - und ermöglicht dem Benutzer somit, den gesamten Inhalt einfach neu zu positionieren, um die Auswahl zu sehen und dann die Daten auszuwählen.

Ich habe die oben genannte App in einer Genymotion VM mit API 22 unter Verwendung einer Bildschirmgröße von 480 x 800 (240 dpi) verifiziert. Es stellt das Problem ziemlich gut dar:

Irgendwelche Ideen, wie man das für Android 5.1.x macht?

Vielen Dank im Voraus!

/John

Antwort

0

Verschachtelte scrollbare UI-Komponenten sind ein Rezept für Probleme. In diesem Fall möchten Sie vielleicht stattdessen die dialog verwenden.

+0

Hmmmm .... Ich verstehe das. Aber wusste nicht wirklich, dass es eine "verschachtelte scrollbare UI-Komponenten" war, bis wir die native Steuerung in Android 5.x getroffen haben ... und das Ärgerliche ist, dass alles gut funktioniert auf anderen Android-Versionen und iOS UI-Erfahrung scheint Ok ... Nun, ich denke, ich muss stattdessen die Dialogsteuerung betrachten. Danke –

+0

Nur ein Follow-up. Der Dialog scheint die verschiedenen Situationen besser zu behandeln :-) Danke! –

0

Haben Sie versucht canCancelEvents: false auf der Scroll Einstellung? Bei der Standardeinstellung true reagiert das ScrollView auf alle Ereignisse, auch auf die seiner Kinder.

+0

nein Ich hatte nicht versucht, dieses Attribut zu setzen. Allerdings scheint es auch zu deaktivieren die '' ... - so kann ich nicht die gesamte Ansicht nach oben scrollen –