4

У меня есть StaggeredGrid в RecyclerView, и я пытаюсь динамически установить высоту изображения в onBindViewHolder. Я думал, что StaggeredGrid должен был обрабатывать все это автоматически, поэтому я установил android:layout_width="match_parent и android:scaleType="fitStart на ImageView, но есть много пробелов вокруг изображения.Как найти ширину ячейки от StaggeredGridLayoutManager?

Поскольку StaggeredGrid не соответствует этому, я немного пытаюсь помочь ему, определяя динамическую высоту изображения в onBindViewHolder. Я имею ширину и высоту изображения раньше времени, но ширина ячейки сетки недоступна. Я пробовал holder.cardView.getLayoutParams().width и getMeasuredWidth(), но оба они возвращают нулевые или маленькие цифры. Я знаю, что есть другие места, где ширина ячейки будет доступна, но мне действительно нужно это в событии onBindViewHolder, чтобы я мог установить и настроить изображение.

Любые идеи о том, как достичь этого, используя StaggeredGrid? Любые советы или опыт оцениваются!

В моей деятельности это:

mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); 
mRecyclerView.setLayoutManager(mLayoutManager); 

В моем адаптере:

@Override 
public void onBindViewHolder(MyAdapter.MyViewHolder holder, int position) { 
    MyModel item = mData.get(position); 

    int imageWidth = item.getFeatured_image().getWidth(); 
    int imageHeight = item.getFeatured_image().getHeight(); 
    int cellWidth = 540; // <==== how to find dynamically??!! 

    ViewGroup.LayoutParams imageLayoutParams = holder.thumbnailImageView.getLayoutParams(); 
    imageLayoutParams.width = cellWidth; 
    imageLayoutParams.height = imageHeight * cellWidth/imageWidth; 
    holder.thumbnailImageView.setLayoutParams(imageLayoutParams); 

    MediaHelper.displayImage(item, holder.thumbnailImageView); 
} 

В моем макете:

<android.support.v7.widget.CardView 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/row_my_card" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_margin="5dp" 
    card_view:cardCornerRadius="2dp"> 

    <ImageView 
     android:id="@+id/row_my_thumbnail_image" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_gravity="top" 
     android:scaleType="fitStart" /> 

    <TextView 
     android:id="@+id/row_my_title_text" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_gravity="bottom" 
     android:background="#CCFFFFFF" 
     android:textStyle="bold" 
     android:padding="5dp" /> 
</android.support.v7.widget.CardView> 

Я также попытался добавить это, что дает мне ширину ячейки, но событие onGlobalLayout запускается после того, как изображение установлено и отрегулировано в событии onBindViewHolder, поэтому уже слишком поздно.

@Override 
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    // create a new view 
    final View view = LayoutInflater.from(parent.getContext()) 
     .inflate(R.layout.row_my_post, parent, false); 

    final MyViewHolder viewHolder = new MyViewHolder(view); 

    ViewTreeObserver viewTreeObserver = view.getViewTreeObserver(); 
    if (viewTreeObserver.isAlive()) { 
     viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
      @Override 
      public void onGlobalLayout() { 
       view.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
       int viewWidth = view.getWidth(); 
       int viewHeight = view.getHeight(); 
      } 
     }); 
    } 

    return viewHolder; 
} 

Ниже приведены пробелы, которые являются случайными из-за различных размеров изображения. То, что я хотел бы для всех изображений, с шириной ячейки и пусть высоту изображения и ячейки настроить динамически:

enter image description here

+0

Любого шанс на все, что вы могли бы добавить скриншот этого разрыва, так что было бы очевидно, что разрыв не из-за присущую прокладку внутри cardview и на самом деле больше, чем разрыв что? – kha

+0

Yup, добавлено! Thx – TruMan1

+0

Хорошо спасибо. Следующий вопрос: Разница, о которой вы говорите, касается самого изображения или расстояния между картами? – kha

ответ

12

Попробуйте: - добавить это в ImageView -> андроид: adjustViewBounds = «истина» ширина

<android.support.v7.widget.CardView 
xmlns:card_view="http://schemas.android.com/apk/res-auto" 
android:id="@+id/row_my_card" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:layout_margin="5dp" 
card_view:cardCornerRadius="2dp"> 

<ImageView 
    android:id="@+id/row_my_thumbnail_image" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_gravity="top" 
    android:adjustViewBounds="true"/> 

<TextView 
    android:id="@+id/row_my_title_text" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_gravity="bottom" 
    android:background="#CCFFFFFF" 
    android:textStyle="bold" 
    android:padding="5dp" /> 
</android.support.v7.widget.CardView> 
+0

Это как волшебство =) Спасибо, ты спасаешь мой день! – Sirelon

3

Вместо того, чтобы высоту обзора и ширину от onCreateViewHolder получить от onBindViewHolder как указано ниже:

@Override 
public void onBindViewHolder(final MyAdapter.MyViewHolder holder, int position) 
{ 
    holder.itemView.post(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      MyModel item = mData.get(position); 
      int imageWidth = item.getFeatured_image().getWidth(); 
      int imageHeight = item.getFeatured_image().getHeight(); 
      int cellWidth = 540; // <==== how to find dynamically??!! 

      cellWidth = holder.itemView.getWidth();// this will give you width dynamically 

      ViewGroup.LayoutParams imageLayoutParams = holder.thumbnailImageView.getLayoutParams(); 
      imageLayoutParams.width = cellWidth; 
      imageLayoutParams.height = imageHeight * cellWidth/imageWidth; 
      holder.thumbnailImageView.setLayoutParams(imageLayoutParams); 
      MediaHelper.displayImage(item, holder.thumbnailImageView); 
     } 
    }); 
} 

Надеюсь, это поможет вам!

+0

Это то, что я пробовал раньше, но ширина возвращает 0, потому что она пока не отображается. – TruMan1

+1

визуализируется, когда вы отправляете сообщение, чтобы получить ширину. оно работает. –

+0

Вы правы, он действительно работает! Я не заметил метод post/runnable. Я пошел с макетным решением, так как это просто и естественно для макета. Thx для обмена этим, поскольку я не знал, что вы могли бы это сделать! – TruMan1

0

клетки можно найти на уровне активности/фрагмента и передается адаптеру, прежде чем время рендеринга. Используйте что-то вроде этого:

this.staggeredGridLayoutManager.getWidth()/this.staggeredGridLayoutManager.getSpanCount() 

При таком подходе вы сможете вычислить высоту ячейки перед любым рендерингом и избежать этого первоначального Флика введенную подхода после выполнения. Кроме того, соотношение сторон изображения будет сохранено, и вы можете зарезервировать необходимое пространство перед загрузкой изображения.

Помните, что если какие-либо поля/прокладки присутствуют, вы должны включить их в предыдущий расчет. Что-то вроде:

(this.staggeredGridLayoutManager.getWidth() - marginsAndOrPaddings)/this.staggeredGridLayoutManager.getSpanCount() 

Update: Начиная с поддержкой пакетов 23.2.0, и на данном этапе жизненного цикла, this.staggeredGridLayoutManager.getWidth() возвращает 0. Общая ширина может быть достигнута с this.recyclerView.getWidth()