8

Ho un elenco di post e la maggior parte di essi sono immagini (in altre parole si tratta di post come app G + o FB). Ogni voce post ha uno aspect ratio dell'immagine, quindi posso impostare l'altezza dell'immagine in base alla sua larghezza anche prima che l'immagine sia stata caricata dal server, quindi il layout delle carte non cambierebbe sul carico.Ottieni la larghezza di CardView in Adapter.onBindViewHolder

Il problema è layout_width="match_parent" impostato per la carta e l'immagine post. Quando ottengo la larghezza di cardview è zero. Quindi non posso calcolare l'altezza.

Per ora l'unica soluzione che vedo è quella di prendere la larghezza del contenitore padre (RecyclerView) e dedurre tutti i paddings, ma non sembra una buona soluzione.

C'è un altro modo per farlo?

Ecco un esempio di codice di adattatore

@Override 
public void onBindViewHolder(ViewHolder holder, int position) { 
    .... 
    int width = holder.itemView.getWidth(); 
    .... 
    //do some calculations 
} 

Layout (senza parti irrilevanti)

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/card" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:descendantFocusability="blocksDescendants" 
    android:foreground="?android:attr/selectableItemBackground" 
    card_view:cardBackgroundColor="#ffffff" 
    card_view:cardCornerRadius="3dp"> 

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <include 
      android:id="@+id/includedPost" 
      layout="@layout/post_details" />  
    </RelativeLayout> 
</android.support.v7.widget.CardView> 

includedPost:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 
    <ImageView 
     android:id="@+id/postImage" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_below="@+id/commenterImage" 
     android:minHeight="120dp" 
     android:scaleType="centerCrop" /> 

</RelativeLayout> 
+1

Puoi inserire parte del codice in cui chiami il metodo getWidth (con un risultato 0)? –

+0

Ho aggiornato la mia domanda con il codice di esempio – Andrew

+1

Forse potresti provare a chiamare il metodo getWidth() in [onViewAttachedToWindow] (https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onViewAttachedToWindow (VH)) secondo il documento: "Questo può essere usato come un segnale ragionevole che la vista sta per essere vista dall'utente" –

risposta

7

quando onBind o onViewAttachedToWindow si chiama, il bambino non èancora misurato in modo da non può ottenere la larghezza. Anche se queste chiamate sono state fatte dopo che il bambino è stato misurato, quello che stai cercando di fare non sarebbe una buona pratica perché cambiare altezza richiederà una nuova misurazione.

Se si utilizza LinearLayoutManager, darà l'intera larghezza al bambino (prevedere il riempimento di RecyclerView ei margini del bambino). Non è bello ma OK per ricavare la tua altezza da lì.

Un altro (più flessibile) approccio è quello di creare un ImageView personalizzato che mantenga le proporzioni. Quando viene chiamato onBind, imposterai le proporzioni desiderate del tuo ImageView personalizzato. Quando viene chiamata la misura, verrà misurata in base al rapporto aspetto.

class MyImageView extends ImageVIew { 
     .... 
     private float mScale = 1f; 

     public void setScale(int scale) { 
      mScale = scale; 
     } 

     @Override 
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 

      super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

      int width = getMeasuredWidth(); 
      setMeasuredDimension(width, width * mScale); 
     } 
} 

Quindi nel tuo metodo di onBind, si chiamano setScale sul ImageView a seconda del rapporto w/h.

Non ho provato ma questo approccio dovrebbe funzionare come desiderato.

+0

Brillante! Funziona. – Andrew

+0

davvero geniale ma setMeasuredDimension è un po 'di confusione nella tua exampe: int width = getMeasuredWidth(); altezza int = getMeasuredHeight(); setMeasuredDimension ((int) (larghezza * mScale), altezza); – cinatic

0

È possibile utilizzare Picasso Transformation per raggiungere questo obiettivo.

classe FitToTargetViewTransformation:

import android.graphics.Bitmap; 
import android.view.View; 

import com.squareup.picasso.Transformation; 

/** 
* Picasso Transformation class to fit image to target View size 
*/ 
public class FitToTargetViewTransformation implements Transformation { 
    private View view; 

    public FitToTargetViewTransformation(View view) { 
    this.view = view; 
    } 

    @Override 
    public Bitmap transform(Bitmap source) { 
    int targetWidth = view.getWidth(); 

    double aspectRatio = (double) source.getHeight()/(double) source.getWidth(); 
    int targetHeight = (int) (targetWidth * aspectRatio); 
    if (source.getHeight() >= source.getWidth()) { 
     return source; 
    } 
    Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false); 
    if (result != source) { 
     // Same bitmap is returned if sizes are the same 
     source.recycle(); 
    } 
    return result; 
    } 

    @Override 
    public String key() { 
    return "transformation" + " desiredWidth"; 
    } 
} 

E da qualche parte in onBindViewHolder si fa qualcosa di simile:

Picasso.with(context) 
    .load(AVATAR_ENDPOINT) 
    .transform(new FitToTargetViewTransformation(feedViewHolder.icAvatar)) 
    .into(feedViewHolder.icAvatar); 
+0

Non credo che risolva il mio problema. Non ho alcun problema con il ridimensionamento delle immagini. Il mio problema è la dimensione delle impostazioni di ImageView prima che l'immagine fosse caricata per impedire ulteriori ridimensionamenti delle carte ogni volta che alcune delle immagini sono state caricate – Andrew

Problemi correlati