8

Tôi có một danh sách các bài đăng và hầu hết trong số đó là ảnh (chỉ cần đặt nó là các bài đăng giống như ứng dụng G + hoặc FB). Mỗi bài đăng có tỷ lệ cỡ ảnh, vì vậy tôi có thể đặt chiều cao hình ảnh dựa trên chiều rộng của ảnh ngay cả trước khi hình ảnh được tải từ máy chủ, do đó bố cục thẻ sẽ không thay đổi khi tải.Nhận chiều rộng của CardView trong Adapter.onBindViewHolder

Sự cố là layout_width="match_parent" đặt cho cả thẻ và hình ảnh bài đăng. Khi tôi nhận được chiều rộng của cardview nó là số không. Vì vậy, tôi không thể tính toán chiều cao.

Hiện tại, giải pháp duy nhất tôi thấy là lấy chiều rộng của vùng chứa mẹ (RecyclerView) và khấu trừ tất cả các phần đệm, nhưng nó không giống như một giải pháp tốt.

Có cách nào khác để làm điều đó không?

Dưới đây là một ví dụ về mã bộ chuyển đổi

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

Layouts (không có phần không liên quan)

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

Bạn có thể đặt một phần mã nơi bạn gọi phương thức getWidth (với kết quả 0) không? –

+0

Cập nhật câu hỏi của tôi với mã mẫu – Andrew

+1

Có thể bạn có thể thử gọi phương thức getWidth() trong [onViewAttachedToWindow] (https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onViewAttachedToWindow (VH)) theo tài liệu: "Điều này có thể được sử dụng như là một tín hiệu hợp lý mà quan điểm sắp được nhìn thấy bởi người dùng" –

Trả lời

7

khi onBind hoặc onViewAttachedToWindow được gọi là, đứa trẻ là không đo chưa vì vậy bạn không thể có chiều rộng. Ngay cả khi các cuộc gọi này được thực hiện sau khi trẻ được đo, những gì bạn đang cố gắng làm sẽ không phải là một thực hành tốt bởi vì việc thay đổi chiều cao sẽ yêu cầu một phép đo mới.

Nếu bạn đang sử dụng LinearLayoutManager, nó sẽ cung cấp cho chiều rộng đầy đủ cho trẻ (mong đợi đệm RecyclerView và lề của trẻ). Nó không phải là tuyệt vời nhưng OK để lấy được chiều cao của bạn từ đó.

Cách tiếp cận khác (linh hoạt hơn) ở đây là tạo một ImageView tùy chỉnh giữ tỷ lệ khung hình của bạn. Khi onBind được gọi, bạn sẽ đặt tỷ lệ cỡ ảnh mong muốn của ImageView tùy chỉnh của mình. Khi đo được gọi, nó sẽ đo lường tùy thuộc vào tỷ lệ khung hình của bạn.

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

Vì vậy, trong phương thức onBind, bạn gọi setScale trên ImageView tùy thuộc vào tỷ lệ w/h của bạn.

Tôi chưa thử nghiệm nhưng cách tiếp cận này sẽ hoạt động như mong muốn.

+0

Brilliant! Nó hoạt động. – Andrew

+0

thực sự rực rỡ nhưng setMeasuredDimension là một chút bối rối trong exampe của bạn: int width = getMeasuredWidth(); int height = getMeasuredHeight(); setMeasuredDimension ((int) (width * mScale), chiều cao); – cinatic

0

Bạn có thể sử dụng Picasso chuyển đổi để đạt được điều này.

FitToTargetViewTransformation lớp:

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

Và đâu đó trong onBindViewHolder bạn làm điều gì đó như thế này:

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

Tôi không tin nó giải quyết được vấn đề của tôi. Tôi không có vấn đề gì với việc chia tỷ lệ hình ảnh. Vấn đề của tôi là kích thước cài đặt của ImageView trước khi hình ảnh được tải để ngăn chặn việc thay đổi kích thước thẻ nhiều hơn bất cứ khi nào một số hình ảnh được tải – Andrew

Các vấn đề liên quan