一个对使用过Android和xml的经验丰富的人的问题,以解释一个谜 [英] A question for anyone experienced with Android and xml to explain a mystery

查看:65
本文介绍了一个对使用过Android和xml的经验丰富的人的问题,以解释一个谜的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发一个应用程序,并且遇到了一个错误,即两个 EditTexts 不会包裹在约束布局中.我尽一切努力解决了这个问题.放置 LinearLayouts 来尝试增强高度,添加 CardViews ,添加链等,等等.我知道使项目包装在 ConstraintLayout 中的方法是使用 app:layout_constrainedHeight ="true" 并将高度设置为 android:layout_height ="wrap_content" ,但即使这样也无法正常工作.花费大量的文字时间试图解决问题,昨天我刚走了出去,碰巧在xml文件中移动,突然间它开始工作.

I am currently developing an app and I came across a bug where two EditTexts just would not wrap inside a constraint layout. I tried everything to fix the problem. placing LinearLayouts to try enforce height adding CardViews, adding chains etc, etc. I know the way to make an item wrap inside a ConstraintLayout is using app:layout_constrainedHeight="true" and setting the height to android:layout_height="wrap_content", but even this wasn't working. Spent literal days trying to solve the problem, when yesterday I just lucked out and happened to move around my xml file and all of a sudden it started working.

正在工作 fragment_layout_text_to_morse

Working fragment_layout_text_to_morse

<?xml version="1.0" encoding="utf-8"?>
<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/decoder_text_to_morse_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/blue"
    tools:context=".Fragments.DecoderFragment">

    <include
        android:id="@+id/include_morse"
        layout="@layout/layout_edit_text_morse"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/decode_changer_fab" />

    <TextView
        android:id="@+id/header_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/sixteen_dp"
        android:layout_marginEnd="@dimen/sixteen_dp"
        android:text="Text"
        android:textColor="@color/white"
        app:layout_constraintBottom_toBottomOf="@id/decode_changer_fab"
        app:layout_constraintEnd_toStartOf="@+id/decode_changer_fab"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/decode_changer_fab" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/decode_changer_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/eight_dp"
        android:src="@drawable/ic_arrow"
        app:layout_constraintBottom_toTopOf="@id/include_morse"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/include_text" />


    <TextView
        android:id="@+id/header_morse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/sixteen_dp"
        android:layout_marginEnd="@dimen/sixteen_dp"
        android:text="Morse"
        android:textColor="@color/white"
        app:layout_constraintBottom_toBottomOf="@id/decode_changer_fab"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toEndOf="@+id/decode_changer_fab"
        app:layout_constraintTop_toTopOf="@id/decode_changer_fab" />

    <include
        android:id="@+id/include_text"
        layout="@layout/layout_edit_text_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@+id/decode_changer_fab"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />
</androidx.constraintlayout.widget.ConstraintLayout>

layout_edit_text_morse

layout_edit_text_morse

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/darkGreen">

    <androidx.appcompat.widget.AppCompatEditText
        android:id="@+id/edit_text_morse"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Morse"
        android:inputType="textMultiLine"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

layout_edit_text_text

layout_edit_text_text

<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/red"
       >

        <androidx.appcompat.widget.AppCompatEditText
            android:maxHeight="128dp"
            android:inputType="textMultiLine"
            android:id="@+id/edit_text_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:hint="text"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

结果

一切正常.当 EditTexts 为空时,它们将在屏幕顶部占据尽可能小的空间.当用户输入内容时,红色的 EditText 会增长到其极限,绿色的 EditText 会占据其余空间.如果键盘处于打开状态,它们都可以正确包装其内容

Everything works as expected. When the EditTexts are empty they occupy as little space as possible at the top of the screen. When the user types into them the red EditText grows to its limit and the green EditText occupies the rest of the space. They also both wrap their content correctly for if the keyboard is open

图片

但这是开始变得奇怪的地方.只需简单地交换xml中布局顶部和底部include语句的位置即可

But this is where thing start to get strange. Simply but swapping the position of the top and bottom include statements in the xml the layout breaks

损坏的 fragment_layout_text_to_morse

Broken fragment_layout_text_to_morse

<?xml version="1.0" encoding="utf-8"?>
<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/decoder_text_to_morse_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/blue"
    tools:context=".Fragments.DecoderFragment">


    <include
        android:id="@+id/include_text"
        layout="@layout/layout_edit_text_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@+id/decode_changer_fab"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <TextView
        android:id="@+id/header_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/sixteen_dp"
        android:layout_marginEnd="@dimen/sixteen_dp"
        android:text="Text"
        android:textColor="@color/white"
        app:layout_constraintBottom_toBottomOf="@id/decode_changer_fab"
        app:layout_constraintEnd_toStartOf="@+id/decode_changer_fab"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/decode_changer_fab" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/decode_changer_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/eight_dp"
        android:src="@drawable/ic_arrow"
        app:layout_constraintBottom_toTopOf="@id/include_morse"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/include_text" />


    <TextView
        android:id="@+id/header_morse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/sixteen_dp"
        android:layout_marginEnd="@dimen/sixteen_dp"
        android:text="Morse"
        android:textColor="@color/white"
        app:layout_constraintBottom_toBottomOf="@id/decode_changer_fab"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toEndOf="@+id/decode_changer_fab"
        app:layout_constraintTop_toTopOf="@id/decode_changer_fab" />

    <include
        android:id="@+id/include_morse"
        layout="@layout/layout_edit_text_morse"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/decode_changer_fab" />

</androidx.constraintlayout.widget.ConstraintLayout>

现在绿色的 EditText 将红色的按钮和按钮推离屏幕

Now the Green EditText pushes the red one and the buttons off screen

我的问题是xml的区别是什么?我了解xml是从上到下解析的,但是如何移动include语句产生如此不同呢?当然可以理解 LinearLayout ,但是为什么 ConstraintLayout 会这样?它不消耗整个xml,然后计算约束吗?我担心的是,就像我之前说的那样,我很幸运要解决此问题,因为我永远不会以这种方式格式化我的代码,使最高视图位于xml的底部,更不用说链的头部位于尾部以下了.任何可以解释为什么会这样的人都会是我的英雄:)

My question is what's the difference in terms of the xml? I understand that xml is parsed from top to bottom, But how is moving the include statements making such a difference? Sure in a LinearLayout I could understand but why is ConstraintLayout behaving this way? Doesn't it consume the entire xml and then calculate the constraints? My worry is, like I said earlier I just lucked out to solve this as I would never format my code this way, having the top most view at the bottom of the xml let alone the head of a chain being below the tail. Anyone that can explain why this is happening will be my hero :)

PS:我在项目中使用导航组件,因此 fragment_layout_text_to_morse 膨胀为 MainActivity androidx.fragment.app.FragmentContainerView >.我还设置了 android:screenOrientation ="portrait" android:windowSoftInputMode =" adjustResize"不确定是否其中任何相关内容,但是请注意:)

PS: I am using navigation components in the project so the fragment_layout_text_to_morse is inflated into the androidx.fragment.app.FragmentContainerView of the MainActivity. I am also setting the android:screenOrientation="portrait" and the android:windowSoftInputMode="adjustResize" Not sure if any of this is pertinent but hey extra info :)

推荐答案

之所以出现此问题,是因为为两个包含文件都指定了 app:layout_constrainedHeight ="true" .仅兑现第一个 app:layout_constrainedHeight ="true" ,而不兑现第二个.

The issue comes about because app:layout_constrainedHeight="true" is specified for both of the include files. Only the first app:layout_constrainedHeight="true" is honored and the second is not.

下面是一个简化的布局来演示该问题:

Here is a simplified layout to demonstrate the problem:

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/decoder_text_to_morse_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.appcompat.widget.AppCompatEditText
        android:id="@+id/include_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/red"
        android:hint="Text"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@+id/include_morse"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <androidx.appcompat.widget.AppCompatEditText
        android:id="@+id/include_morse"
        layout="@layout/layout_edit_text_morse"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/darkGreen"
        android:hint="Morse"
        android:inputType="textMultiLine"
        app:layout_constrainedHeight="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/include_text" />

</androidx.constraintlayout.widget.ConstraintLayout>

由于只有第一个具有 app:layout_constrainedHeight ="true" 的视图才被接受,因此顺序很重要.您可以在上面的布局中尝试此标志的各种组合,以了解我的意思.(使用的是ConstraintLayout版本2.0.4.)

Since only the first view with app:layout_constrainedHeight="true" is honored, then the order will matter. You can try various combinations of this flag in the above layout to see what I mean. (ConstraintLayout version 2.0.4 is used.)

我希望两个标志都将得到尊重,而不仅仅是一个,但是这是很难辨别是缺陷还是局限性的情况之一.

I would expect both flags to be honored instead of just one, but this is one of those cases where it is difficult to discern whether it is a defect or just a limitation.

为两个视图设置 app:layout_constrainedHeight ="false" 并依靠垂直链来完成其工作效果会更好一些,但是布局会在状态和导航栏下方滑动一些模拟器.

Setting app:layout_constrainedHeight="false" for both views and relying on the vertical chain to do its job works a little better, but the layout slides a little beneath the status and navigation bars on the emulator.

这篇关于一个对使用过Android和xml的经验丰富的人的问题,以解释一个谜的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆