markdown 使用约束布局的StaggeredLayoutManager中的宽高比
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown 使用约束布局的StaggeredLayoutManager中的宽高比相关的知识,希望对你有一定的参考价值。
> 原文 (Medium):[Aspect Ratio in StaggeredLayoutManager using Constraint Layout](https://medium.com/@burhanrashid52/aspect-ratio-in-staggered-layoutmanager-using-constraint-layout-9845d04d1962)
>
> 作者:[Burhanuddin Rashid](https://medium.com/@burhanrashid52?source=post_header_lockup)
[TOC]
你好开发者! !! 今天,我们将学习一种有效的方法即使用 *ConstraintLayout* 来维护 *StaggeredLayout* 中视图的纵横比。我们将以 *Pinterest* 应用程序设计为例。本文假定您已经具备 [*LayoutManager*](https://guides.codepath.com/android/using-the-recyclerview) 和 [*ConstraintLayout*](https://medium.com/google-developers/building-interfaces-with-constraintlayout-3958fa38a9f7) 的基本知识,如果不是,我建议在进一步阅读之前阅读链接。
![](https://cdn-images-1.medium.com/max/600/1*9Wcfnkr2djtiPSHYj6eL7Q.png)
我们的目标是设计类似 *Pinterest* 的布局。为此,我们需要在 *RecycleView* 中使用 *StaggeredGridLayoutManager* 。
## 什么是 StaggeredGridLayoutManager?
正如 *doc* 所述,*StaggeredGridLayoutManager* 是一个 *LayoutManager* ,它将孩子排列成一个交错的网格。它支持水平和垂直布局以及交错布局孩子的能力。
在交错布局中,列表中每个项目的长宽比可能是不同的 ,当我们尝试从 *url* 加载图像时,它会变得更加复杂。因此,从 *url* 加载图片时,我们不知道图片的确切长宽比。所以我们要做的是,在我们的行布局中,保持图像宽度为 *match_parent* 和高度为 *wrap_content*,所以每当图像加载时 ,它都会根据图像宽度自动包装其高度。
## 问题 ?
我们知道,有时互联网连接可能会非常缓慢,这需要大量的时间来加载图像,所以在正常情况下 ,我们在加载实际图像时使用一个占位符图像来提高用户体验。
但是在交错布局中,由于我们不知道图像的宽高比,直到其完全加载,而且我们的占位符宽高比可能与实际图像不同,所以最初在列表中加载图像时,我们看到所有项目中具有相同宽高比的占位符,并且当实际图像完全加载时,它才开始设置具有其自身宽高比的实际图像,这使得用户体验不好,因为当用户滚动列表时,项目会非常频繁地改变其高度/宽度。
不用担心,我们现在可以使用约束布局宽高比特性来解决这个问题。但是首先您需要知道宽高比在 *ConstraintLayout* 中如何工作。
## 约束布局中的宽高比
使用宽高比可以完成与 [*PercentFrameLayout*](https://developer.android.com/reference/android/support/percent/PercentFrameLayout.html) 大致相同的操作,即将 *View* 限制为设置的宽高比,而不需要额外的 *ViewGroup* 增加在你的层次结构中的开销 。
![](https://cdn-images-1.medium.com/max/800/1*RfgavVsO88a44_F5xGnUog.gif)
要为 *ConstraintLayout* 内的任何视图设置比率,请执行以下操作:
- 确保至少有一个大小约束是动态的,即不是 “*Fixed*” 也不是 “*Wrap Content*”。
- 点击框左上角的 “切换宽高比约束”。
- 输入 *width* : *height* 格式中所需的宽高比例 ,例如:16:9
有关 *ConstraintLayout* 的更多细节,您可以阅读这篇很棒的文章。
[**Building interfaces with ConstraintLayout** *In this article I’d like to highlight recent additions to ConstraintLayout in Android Studio 2.3 (Beta): chains and…* medium.com](https://medium.com/google-developers/building-interfaces-with-constraintlayout-3958fa38a9f7)
## 解决方案
正如我们上面讨论的那样,开发人员遇到的一个解决方案是直接从后端 *API* 获取图像的高度/宽度,并设置从后端 *API* 获取的占位符比率,这将在用户滚动列表时带来顺畅的用户体验。
但是在 *ConstraintLayout* 出现之前,开发人员常常需要大量的工作来手动设置图片的高度/宽度。
首先,我们需要根据设备大小和跨度计数来计算图像宽度,而不是将该 *px* 值转换为 *dp* 并且在 *onBindViewHolder* ( ) 上以编程方式设置图片的高度/宽度,并在计算视图的宽度时还需要考虑填充。
这是一个大量的手工工作 ,但我们现在有 *ConstraintLayout* ,现在我们可以直接设置图像视图的比例,*ConstraintLayout* 将会处理所有这些问题
让我们看一个例子。
首先,我们将构建我们的 *row_poster.xml*。
```xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView 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"
app:cardCornerRadius="4dp"
android:layout_margin="4dp">
<android.support.constraint.ConstraintLayout
android:id="@+id/parentContsraint"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imgSource"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/placeholder"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:text="TextView"
android:textColor="@android:color/black"
android:textStyle="italic"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imgSource" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
```
在上面的布局中,我们将 *ImageView* 宽度/高度设置为 0 *dp*,这是约束布局中的 *match_constraint*,意思是它的行为与 *match_parent* 相同。
默认情况下,我们保留了应用程序:*layout_constraintDimensionRatio =“1:1”*,这意味着我们的图像默认为正方形。
现在我们有了 *MoviePoster* 模型。
```java
class MoviePoster(var name: String,
var imageUrl: String,
var width: Int,
var height: Int)
```
它具有从 *webservices* 获取的图像 *url* 的宽度和高度。
默认情况下,我们保留了 *app:layout_constraintDimensionRatio =“1:1”*,这意味着我们的图像将是正方形。现在将以编程方式设置每个图像的宽高比。
这就是我们如何使用 *ConstraintLayout* 设置图像的宽高比,我们将创建一个全局的 *ContraintSet* ( ) 对象,并在 *onBindViewHolder* ( ) 中使用它。
```java
class MoviePosterAdapter : RecyclerView.Adapter<MoviePosterAdapter.ViewHolder>() {
private val set = ConstraintSet()
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val poster = mMoviePosters[position]
holder.mMovieName.text = poster.name
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)
}
```
我们将克隆当前 *ContraintSet* ( ) 对象中视图的约束 ,并将宽高比率设置为 “*width*:*height*” 格式,并提供我们想要设置该比例的视图的 *id*,即在我们的场景中是 *ImageView* 的 *id*。
最后,我们将改变的约束从 *set* 对象应用到 *Constraintlayout*。
就是这样:) ......这就是我们需要做的...... *ConstraintLayout* 将管理所有的东西。
![](https://cdn-images-1.medium.com/max/600/1*XX654_ckWPndh1ePCcyMBQ.png)
你可以在 *GitHub* 上检出这个例子。这个例子是用 *Kotlin* 编写的。[*[PR](https://github.com/burhanrashid52/AspectRatioExample)*]
谢谢 !!! 如果你觉得这篇文章有用。请喜欢,分享和鼓掌 ,这样其他人会在 *Medium* 看到它。如果您有任何问题或建议,请随时在 [*Twitter*](https://twitter.com/burhanrashid52) 上找我。
以上是关于markdown 使用约束布局的StaggeredLayoutManager中的宽高比的主要内容,如果未能解决你的问题,请参考以下文章
Android Staggered Grdiv 查看最后一个元素全屏(如果独立)
New UWP Community Toolkit - Staggered panel
约束布局使用 Design 模式编辑 ConstraintLayout 约束布局 ( 添加 Guideline 引导线 | 添加 FragmentContainerView )