Come dimensionare una vista Android in base alle dimensioni del suo genitore

Come posso ridimensionare una vista in base alla dimensione del suo layout genitore. Ad esempio, ho un RelativeLayout che riempie lo schermo intero e voglio una vista figlio, ad esempio un ImageView , per occupare l’intera altezza e 1/2 della larghezza?

Ho provato a sovrascrivere tutto su onMeasure , onLayout , onSizeChanged , ecc. E non ho potuto farlo funzionare …

Non so se qualcuno stia ancora leggendo questo thread o no, ma la soluzione di Jeff ti porterà solo a metà strada (un po ‘alla lettera). Quello che farà il suo intervento sarà visualizzare metà dell’immagine a metà del genitore. Il problema è che chiamare super.onMeasure prima di setMeasuredDimension misurerà tutti i child nella vista in base alla dimensione originale, quindi taglia la visualizzazione a metà quando la dimensione di setMeasuredDimension ridimensiona.

Invece, è necessario chiamare setMeasuredDimension (come richiesto per una sovrascrittura onMeasure) e fornire un nuovo LayoutParams per la visualizzazione, quindi chiamare super.onMeasure . Ricorda che i tuoi LayoutParams derivano dal tipo di genitore della tua vista, non dal tipo di visualizzazione.

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ int parentWidth = MeasureSpec.getSize(widthMeasureSpec); int parentHeight = MeasureSpec.getSize(heightMeasureSpec); this.setMeasuredDimension(parentWidth/2, parentHeight); this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight)); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 

Credo che l’unica volta che avrai problemi con il LayoutParams principale è se il genitore è un AbsoluteLayout (che è deprecato ma a volte utile).

È ansible risolvere questo problema creando una vista personalizzata e sovrascrivendo il metodo onMeasure (). Se usi sempre “fill_parent” per layout_width nel tuo xml, allora il parametro widthMeasureSpec che viene passato al metodo onMeasusre () dovrebbe contenere la larghezza del genitore.

 public class MyCustomView extends TextView { public MyCustomView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int parentWidth = MeasureSpec.getSize(widthMeasureSpec); int parentHeight = MeasureSpec.getSize(heightMeasureSpec); this.setMeasuredDimension(parentWidth / 2, parentHeight); } } 

Il tuo XML sarebbe simile a questo:

    

Ho scoperto che è meglio non scherzare con l’impostazione delle dimensioni misurate da soli. C’è in realtà un po ‘di negoziazione che va avanti tra le viste genitore e figlio e non si vuole riscrivere tutto quel codice .

Quello che puoi fare, però, è modificare il measureSpecs, quindi chiamare super con loro. La tua vista non saprà mai che sta ricevendo un messaggio modificato dal suo genitore e si prenderà cura di tutto per te:

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int parentHeight = MeasureSpec.getSize(heightMeasureSpec); int myWidth = (int) (parentHeight * 0.5); super.onMeasure(MeasureSpec.makeMeasureSpec(myWidth, MeasureSpec.EXACTLY), heightMeasureSpec); } 

Quando si definisce un layout e una vista su XML, è ansible specificare la larghezza e l’altezza del layout di una vista in modo da includere il contenuto del riepilogo o il riempimento del genitore. Riprendere metà dell’area è un po ‘più difficile, ma se avessi qualcosa che volevi dall’altra parte potevi fare qualcosa di simile al seguente.

      

Dare due cose lo stesso peso significa che si allungheranno per occupare la stessa proporzione dello schermo. Per maggiori informazioni sui layout, consultare i documenti di sviluppo.

Credo che l’ approccio XML di Mayras possa essere chiaro. Tuttavia è ansible renderlo più preciso, con una sola vista impostando il peso. Non definirei più un hack ma a mio avviso l’approccio più diretto:

    

Così puoi usare qualsiasi peso, 0.6 per esempio (e centrare) è il peso che mi piace usare per i pulsanti.

Prova questo

 int parentWidth = ((parentViewType)childView.getParent()).getWidth(); int parentHeight = ((parentViewType)childView.getParent()).getHeight(); 

quindi è ansible utilizzare LinearLayout.LayoutParams per impostare i parametri di chileView

 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength); childView.setLayoutParams(params); 

Ora puoi usare PercentRelativeLayout. Boom! Problema risolto.

Roman, se vuoi fare il tuo layout nel codice Java (discendente di ViewGroup), è ansible. Il trucco è che devi implementare entrambi i metodi onMeasure e onLayout. L’onMeasure viene chiamato per primo e devi “misurare” la sottoview (ridimensionandola efficacemente con il valore desiderato). È necessario ridimensionarlo nuovamente nella chiamata onLayout. Se non riesci a eseguire questa sequenza o non riesci a chiamare setMeasuredDimension () alla fine del tuo codice onMeasure, non otterrai risultati. Perché questo è progettato in modo così complicato e fragile è al di là di me.

Se l’altro lato è vuoto. Immagino che il modo più semplice sarebbe quello di aggiungere una vista vuota (ad esempio un layout lineare), quindi impostare le larghezze di entrambe le viste su fill_parent e entrambi i loro pesi su 1.

Funziona in un LinearLayout …

È qualcosa del genere:

     android:layout_weight="50" android:layout_height="wrap_content" android:id="@+id/spinner" />       

Ho un’altra soluzione. Possiamo ottenere larghezza e altezza del genitore, quindi basta usarlo per calcolare le dimensioni e assegnare i parametri del layout.
Come questo:

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // Don't for get this int parentWidth = ((View) getParent()).getMeasuredWidth(); int parentHeight = ((View) getParent()).getMeasuredHeight(); if (parentWidth*parentHeight != 0) { // Check if both width and height in non-zero LayoutParams lp = getLayoutParams(); lp.width = parentWidth / 2; lp.height = parentHeight; } }