8

Ich habe eine Liste von Beiträgen und die meisten von ihnen sind Bilder (einfach gesagt, es ist Posts wie G + oder FB-Anwendungen). Jeder Post-Eintrag hat ein Bild-Seitenverhältnis, so dass ich die Bildhöhe basierend auf der Breite einstellen kann, noch bevor das Bild vom Server geladen wurde, so dass sich das Kartenlayout nicht ändern würde.Breite von CardView in Adapter.onBindViewHolder

Das Problem ist layout_width="match_parent" für sowohl Karte und Post-Image festgelegt. Wenn ich die Breite von Cardview bekomme, ist es Null. Also kann ich die Höhe nicht berechnen.

Für jetzt die einzige Lösung, die ich sehe, ist die Breite des übergeordneten Containers (RecyclerView) zu nehmen und alle Polsterungen abzuziehen, aber es sieht nicht wie eine gute Lösung aus.

Gibt es einen anderen Weg, es zu tun? Hier

ist ein Beispiel für Adaptercode

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

Layouts (ohne irrelevante Teile)

<?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

Können Sie einen Teil des Codes, wo Sie getWidth-Methode aufrufen (mit einem 0-Ergebnis)? –

+0

Meine Frage mit Beispielcode – Andrew

+1

aktualisiert Vielleicht könnten Sie versuchen, getWidth() -Methode in [onViewAttachedToWindow] (https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onViewAttachedToWindow) aufzurufen (VH)) gemäß dem Dokument: "Dies kann als ein vernünftiges Signal verwendet werden, dass die Ansicht vom Benutzer gesehen wird" –

Antwort

7

wenn onBind oder onViewAttachedToWindow genannt wird, das Kind ist noch nicht, so dass Sie gemessen kann die Breite nicht bekommen. Selbst wenn diese Anrufe nach der Messung des Kindes durchgeführt werden, ist das, was Sie zu tun versuchen, keine gute Übung, da eine Änderung der Höhe eine neue Messung erfordert.

Wenn Sie LinearLayoutManager verwenden, wird dem Kind die volle Breite zugewiesen (RecyclerView-Füllung und untergeordnete Ränder). Es ist nicht toll, aber OK, um deine Höhe von dort abzuleiten.

Ein anderer (flexiblerer) Ansatz besteht darin, ein benutzerdefiniertes ImageView zu erstellen, das das Seitenverhältnis beibehält. Wenn onBind aufgerufen wird, legen Sie das gewünschte Seitenverhältnis für Ihr benutzerdefiniertes ImageView fest. Wenn ein Takt aufgerufen wird, wird er abhängig von Ihrem Seitenverhältnis gemessen.

Also rufen Sie in Ihrer onBind-Methode setScale auf dem ImageView auf, abhängig von Ihrem w/h-Verhältnis.

Ich habe nicht getestet, aber dieser Ansatz sollte wie gewünscht funktionieren.

+0

Brilliant! Es klappt. – Andrew

+0

wirklich brilliant, aber setMeasuredDimension ist ein wenig verwirrend in Ihrem Beispiel: int width = getMeasuredWidth(); int Höhe = getMeasuredHeight(); setMeasuredDimension ((int) (Breite * mSkala), Höhe); – cinatic

0

Sie können Picasso Transformation verwenden, um dies zu erreichen.

FitToTargetViewTransformation Klasse:

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"; 
    } 
} 

Und irgendwo in onBindViewHolder Sie etwas tun, wie folgt aus:

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

Ich glaube nicht, dass es mein Problem löst. Ich habe kein Problem mit der Skalierung von Bildern. Mein Problem ist die Einstellungsgröße von ImageView, bevor das Bild geladen wurde, um weitere Größenanpassungen der Karten zu verhindern, wenn einige der Bilder geladen wurden. – Andrew