Android layout Android无法测量constraintLayout

Android layout Android无法测量constraintLayout,android-layout,android-constraintlayout,Android Layout,Android Constraintlayout,我正在尝试获取我创建的customview的measuredWidth和measuredHeight。但每次我调用其中一个变量进行度量时,仍然会返回0个值 让我们看一下xml文件,以便您可以看到自定义视图的外观: 重试\u img.xml: <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http:

我正在尝试获取我创建的customview的measuredWidth和measuredHeight。但每次我调用其中一个变量进行度量时,仍然会返回0个值

让我们看一下xml文件,以便您可以看到自定义视图的外观:

重试\u img.xml:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
    android:id="@+id/iv"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />

<ImageView
    android:id="@+id/iv_retry"
    android:layout_width="36dp"
    android:layout_height="36dp"
    android:layout_gravity="center"
    android:visibility="gone"
    app:elevation="5dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:srcCompat="@drawable/img_retry_btn"
    tools:visibility="visible" />

<org.someOtherCustomView.Not.Important
    android:id="@+id/loading_shimmer"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:visibility="gone"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout="@layout/img_loading_layout" />

</androidx.constraintlayout.widget.ConstraintLayout>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/row"
    android:layout_width="256dp"
    android:layout_height="144dp"
    android:layout_marginLeft="16dp"
    android:paddingTop="11dp"
    android:paddingBottom="16dp">

 <org.somecompany.MyCustomImageView
        android:id="@+id/iv_photo"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="H,232:60"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:srcCompat="@drawable/image_placeholder" />

        </androidx.constraintlayout.widget.ConstraintLayout>
}

我尝试了
MeasureSpec.justice和MeasureSpec.UNSPECIFIED
相同的结果

让我们看看我是如何实际使用它的,这可能会有所帮助:

它位于另一个constraintLayout内,如下所示:

class MyCustomImageView : ConstraintLayout {

constructor(p0: Context) : super(p0)
constructor(p0: Context, p1: AttributeSet?) : super(p0, p1)
constructor(p0: Context, p1: AttributeSet?, p2: Int) : super(p0, p1, p2)


init {
    inflate(context, R.layout.retry_img, this)
    measure(MeasureSpec.EXACTLY, MeasureSpec.EXACTLY)
   Log.d(TAG,"$measuredWidth") //this is always zero, why ? 
}
1. create a behaviorSubject so you always know when size changes. 

private var subject = BehaviorSubject.create<Any>()

2. then override it:

     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
            super.onSizeChanged(w, h, oldw, oldh)
             subject.onNext(Any())
        }

3. use it as a trigger:

 subject.switchMap { //got the size do something }.subscribe(//...)
my\u main\u layout.xml:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
    android:id="@+id/iv"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />

<ImageView
    android:id="@+id/iv_retry"
    android:layout_width="36dp"
    android:layout_height="36dp"
    android:layout_gravity="center"
    android:visibility="gone"
    app:elevation="5dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:srcCompat="@drawable/img_retry_btn"
    tools:visibility="visible" />

<org.someOtherCustomView.Not.Important
    android:id="@+id/loading_shimmer"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:visibility="gone"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout="@layout/img_loading_layout" />

</androidx.constraintlayout.widget.ConstraintLayout>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/row"
    android:layout_width="256dp"
    android:layout_height="144dp"
    android:layout_marginLeft="16dp"
    android:paddingTop="11dp"
    android:paddingBottom="16dp">

 <org.somecompany.MyCustomImageView
        android:id="@+id/iv_photo"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="H,232:60"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:srcCompat="@drawable/image_placeholder" />

        </androidx.constraintlayout.widget.ConstraintLayout>


请注意,我使用了一个app:layout\u constraintDimensionRatio这就是为什么我在宽度和高度上设置了0。我还在另一个布局文件中尝试了这个customview(MyCustomImageView),但结果相同。任何想法。

对于需要帮助的人,我使用了如下RX主题:

class MyCustomImageView : ConstraintLayout {

constructor(p0: Context) : super(p0)
constructor(p0: Context, p1: AttributeSet?) : super(p0, p1)
constructor(p0: Context, p1: AttributeSet?, p2: Int) : super(p0, p1, p2)


init {
    inflate(context, R.layout.retry_img, this)
    measure(MeasureSpec.EXACTLY, MeasureSpec.EXACTLY)
   Log.d(TAG,"$measuredWidth") //this is always zero, why ? 
}
1. create a behaviorSubject so you always know when size changes. 

private var subject = BehaviorSubject.create<Any>()

2. then override it:

     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
            super.onSizeChanged(w, h, oldw, oldh)
             subject.onNext(Any())
        }

3. use it as a trigger:

 subject.switchMap { //got the size do something }.subscribe(//...)
1。创建一个behaviorSubject,以便在大小更改时始终知道。
private var subject=BehaviorSubject.create()
2.然后覆盖它:
覆盖乐趣已更改(w:Int,h:Int,oldw:Int,oldh:Int){
super.onSizeChanged(w,h,oldw,oldh)
subject.onNext(Any())
}
3.将其用作触发器:
subject.switchMap{//已获得大小do something}.subscribe(//…)

我想latestFrom操作符也可以用作触发器,但最简单的是行为受我约束,以记住最后一次发射(空闲缓存)

在布局完成之前,将创建自定义视图并运行init块。在这一点上,没有任何东西真正具有尺寸。您需要延迟抓取宽度,直到布局完成。尝试使用
measure()
获取宽度时,也会指定精确的度量值0,因此,即使布局完成,也会得到零。(搜索“android如何绘制视图”以获取这些信息。)由于有几种方法可以获取宽度,如果您可以指定何时需要获取宽度,您可能会得到一个可用的答案。一旦视图膨胀,我需要知道它的尺寸,以便我可以通过网络调用获取图像。网络调用要求viewonPredraw的宽度和高度对我来说有点慢。希望我能自己测量它。尝试覆盖以捕获宽度。如果可以对视图的父视图进行一些假设,还可以在布局之前捕获宽度。你将需要建立一个适当的,包括宽度。这很好。我把一个接收主题在那里火,如果它执行我开始我的负载。谢谢,如果你需要回答,你可以。这个答案真的帮助了我,因为我使用的是一个旧版本的glide,它有一些错误,我必须知道何时实际测量视图。