2012-01-25 8 views
6

Ho una vista personalizzata che sto creando che ridimensiona la dimensione del font del suo figlio TextViews per adattarla a tutto in una larghezza impostata, quindi ciascuna è sulla propria linea. Ovviamente avrà bisogno della larghezza per capirlo. Avevo ignorato onMeasure() in questo modo:Gestione pesi in onMeasue per visualizzazioni personalizzate

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    int widthSize = MeasureSpec.getSize(widthMeasureSpec); 
    int lineWidth = widthSize - getPaddingLeft() - getPaddingRight(); 

    // Change the text size until the largest line of text fits. 
    while (lineWidth < calculateTextWidth()) { 
    for (TextView textView : this.childViews) { 
     float newSize = textView.getTextSize() - 1; 
     textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSize); 
    } 
    } 

    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
} 

calculateTextWidth() calcola la larghezza della più grande linea di testo, e tutto funziona con quello. Questo codice funziona correttamente per le larghezze FILL_PARENT e WRAP_CONTENT, ma si verifica quando cerco di attribuire al componente un peso e di impostare automaticamente il suo peso in quel modo: MeasureSpec.getSize(widthMeasureSpec) restituisce 0, così come getMinimumSuggestedWidth(). Questo dà un errore meraviglioso di non risposta delle attività, poiché lineWidth sarà sempre inferiore a calculateTextWidth(), in caso contrario, il ciclo while verrà eseguito per sempre. Il codice XML che ho usato è stato questo, in sostanza:

<com.my.widgets.ScalingTextViewGroup 
    android:layout_width="0dp" 
    android:layout_height="wrap_content" 
    android:layout_weight="1" 
    android:orientation="vertical" 
    android:gravity="center_horizontal" 
    > 
    <TextView 
     android:id="@+id/text_1" 
     android:text="Text 1" 
     android:textSize="20sp" /> 
    <TextView 
     android:id="@+id/text_2" 
     android:text="Text 2" 
     android:textSize="18sp" /> 
    <TextView 
     android:id="@+id/text_3" 
     android:text="Text 3" 
     android:textSize="18sp" /> 
    <TextView 
     android:id="@+id/text_4" 
     android:text="Text 4" 
     android:textSize="18sp" /> 
</com.my.widgets.ScalingTextViewGroup> 

capisco perché è il ritorno 0 - Ovviamente, è stato impostato a 0 - ma come faccio ad avere in modo da utilizzare il layout_weight? Sento che è qualcosa che dovrebbe avere una risposta semplice, ma non riesco a capire cosa sia.

risposta

10

Ho finito per capirlo attraverso alcuni significativi Googling. Su this page ho scoperto che onMeasure viene effettivamente chiamato due volte quando è impostato android:layout_weight. Ho scoperto in seguito che è menzionato in How Android Draws Views che measure() può essere chiamato un numero qualsiasi di volte, semplicemente non mi siedeva immediatamente nel cervello. Ovviamente il primo passaggio non può dare un valore alle dimensioni di ogni bambino, poiché non sa quali siano i pesi di tutti i fratelli di View. Lo attraversa una volta e dà una larghezza di 0 con MeasureSpec.UNSPECIFIED per vedere se il bambino ha dei vincoli specifici, quindi passa attraverso di nuovo per assegnare i pesi effettivi con MeasureSpec.EXACTLY. La mia attività si stava facendo rovinare al primo passaggio, quindi non ha mai raggiunto la fase di layout. Modificando il mio onMeasure() al seguente codice risolto il problema.

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
    if (widthMode != MeasureSpec.UNSPECIFIED) { 
    int widthSize = MeasureSpec.getSize(widthMeasureSpec); 
    int lineWidth = widthSize - getPaddingLeft() - getPaddingRight(); 

    // Change the text size until the largest line of text fits. 
    while (lineWidth < calculateTextWidth()) { 
     for (TextView textView : this.childViews) { 
     float newSize = textView.getTextSize() - 1; 
     textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newSize); 
     } 
    } 
    } 

    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
} 
+0

Quindi, se si fosse fermato prima del ciclo temporale si avrebbe la dimensione massima disponibile in base al peso specificato? (Andando a leggere i tuoi collegamenti ora ...) –