StaggeredLayout с FlexboxLayoutManager
У меня есть какой-либо способ реализовать разнесенный макет с помощью библиотеки Flexbox от Google, подобной этой
Вышеуказанный макет создан с использованием 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
}