StaggeredLayout с FlexboxLayoutManager

У меня есть какой-либо способ реализовать разнесенный макет с помощью библиотеки Flexbox от Google, подобной этой

Макет реализован с использованием StaggeredLayoutManager

Вышеуказанный макет создан с использованием StaggeredLayoutManger также поддерживая соотношение сторон изображения

Я пробовал код:

recyclerView.apply {
        layoutManager = FlexboxLayoutManager(context).apply {
            flexWrap = FlexWrap.WRAP
            justifyContent = JustifyContent.CENTER
        }
        adapter = mAdapter
    }

Но это делает макет с одним столбцом, а соотношение сторон также не поддерживается (учитывая, что изображения имеют большой размер).

3 ответа

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

  flexboxLayoutManager = new FlexboxLayoutManager(yourActivity.this);
  flexboxLayoutManager.setFlexWrap(FlexWrap.WRAP);
  flexboxLayoutManager.setAlignItems(AlignItems.STRETCH);
  flexboxLayoutManager.setFlexDirection(FlexDirection.ROW);
  recyclerView.setLayoutManager(flexboxLayoutManager);

Основная логика входит в адаптер, на onBindViewHolder

 Glide.with(context)
         .load(String.format("yourUrlHere")
         .diskCacheStrategy(DiskCacheStrategy.ALL)
         .animate(R.anim.fadein)
         .override(dpToPx(90) ,dpToPx(90)) // here replace with your desired size.
         .centerCrop()
         .listener(new RequestListener<String, GlideDrawable>() {
                    @Override
                    public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                        //  holder.loader.setVisibility(View.GONE);
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                        //  holder.loader.setVisibility(View.GONE);
                        return false;
                    }
                })
         .priority(Priority.IMMEDIATE)
          .into(viewHolder.imageView);

   ViewGroup.LayoutParams lp = viewHolder.imageView.getLayoutParams();
    if (lp instanceof FlexboxLayoutManager.LayoutParams) {
        FlexboxLayoutManager.LayoutParams flexboxLp = (FlexboxLayoutManager.LayoutParams) lp;
        Random random = new Random();
        int val = random.nextInt(5);
        if (val ==0){
            val = 1;
        }
        flexboxLp.setFlexGrow(val);
        flexboxLp.setFlexShrink(1f);

    } 

И вы можете решить свою проблему, используя этот код, как я сам реализовал в одном проекте. Надеюсь, это решит вашу проблему. Удачного кодирования:)

Примечание: в моем проекте, в зависимости от требований, я использовал flexboxLayoutManager.setFlexDirection(FlexDirection.COLUMN); так что мой макет такой.

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

Вам нужно использовать GridLayoutManager для этого и с помощью ConstrainLayout Вы можете легко установить соотношение сторон изображения следующим образом.

private val set = ConstraintSet()

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val poster = mMoviePosters[position]

    Glide.with(holder.itemView.context)
                .setDefaultRequestOptions(requestOptions)
                .load(poster.imageUrl)
                .into(holder.mImgPoster)

    val ratio =String.format("%d:%d", poster.width,poster.height)
    set.clone(holder.mConstraintLayout)
    set.setDimensionRatio(holder.mImgPoster.id, ratio)
    set.applyTo(holder.mConstraintLayout)
}

Я уже написал подробный пост в блоге об этом. Если вы хотите узнать больше, прочитайте Aspect Ratio в Staggered LayoutManager, используя Constraint Layout

Использование

flexDirection = FlexDirection.ROW
alignItems = AlignItems.STRETCH

Вместо

justifyContent = JustifyContent.CENTER

Ваш новый код будет похож

recyclerView.apply {
        layoutManager =FlexboxLayoutManager(context).apply {
            flexWrap = FlexWrap.WRAP
            flexDirection = FlexDirection.ROW
            alignItems = AlignItems.STRETCH
        }
        adapter = mAdapter
    }
Другие вопросы по тегам