【问题标题】:LinearLayout: prevent last child from getting pushed out or squeezed by large textview before itLinearLayout:防止最后一个孩子被前面的大文本视图推出或挤压
【发布时间】:2021-09-05 03:53:12
【问题描述】:

我有一个LinearLayout,里面有两个孩子。第一个是带有动态内容的TextView,第二个是按钮。我的问题是按钮被推出其父级或被挤压到不再可见的程度。我希望TextView 认识到它的父母与第二个孩子一起没有更多的空间,并开始新的一行而不是窃取第二个孩子所需的空间。然而,按钮应该在文本旁边,而不是默认情况下一直到右侧。

我尝试了很多不同的方法,但都没有成功,在下面的代码中,我只是发布了我想要工作的最小示例,没有我已经尝试过的不同更改。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="sdrndesfntzrfndtzmufzksbnsfdn stnbhdsfbns sth st ömcfz,frznz"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />
</LinearLayout>

总而言之:我希望 TextView 占用几行而不是占用 Button 的空间。行数当然应该是动态的,具体取决于视图内的文本。 Button 应直接位于 textview 旁边,并随着文本变大而向右移动。

这是我想要的视觉表示:

这是我得到的。

设置 textview 的 maxwidth 是一个简单的解决方案,但在更复杂和动态的布局中,您并不总是知道最大宽度是多少。所以最好有一个没有硬编码 maxWidths 的解决方案。

【问题讨论】:

  • 为您的文本视图使用静态或 maxWidth,例如 120dp
  • 我用它作为一种解决方法,计算代码中 textview 的 maxWidth,但我希望能找到更好的解决方案。这里的例子当然是简化的。在实际代码中,计算 TextView 的 maxWidth 有点棘手
  • 给我看你想要什么和你得到什么的截图,以便更好地理解
  • @UsamaAltaf 我编辑了这个问题。如果您指的是我项目中的实际示例:其中有几种情况,将来我可能会遇到更多。我试图用上面的例子来提炼这个问题,这个问题的解决方案应该适用于我项目中的所有其他事件。
  • 设置按钮的固定宽度,这样按钮宽度就可以了,比如 40dp

标签: android xml android-layout android-linearlayout android-constraintlayout


【解决方案1】:

你可以试试FlexboxLayout:https://github.com/google/flexbox-layout

<com.google.android.flexbox.FlexboxLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:alignItems="center"
    app:alignContent="center"
    app:flexDirection="row"
    app:flexWrap="nowrap">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="sdrndesfntzrfndtzmufzksbnsfdn stnbhdsfbns sth st ömcfz,frznz dfgsfsdfsdf"
        app:layout_flexShrink="10000"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"/>
</com.google.android.flexbox.FlexboxLayout>

app:layout_flexShrink="10000" 是正确调整元素大小的原因。

EDTbuild.gradle 配置:

allprojects {
  repositories {
    ...
    maven { url "https://maven.google.com" }
  }
}

dependencies {
  ...
  implementation 'com.google.android.flexbox:flexbox:3.0.0'
}

【讨论】:

    【解决方案2】:

    您可以将 TextView 和 Button 的宽度设置为 0dp 并设置权重,如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:text="sdrndesfntzrfndtzmufzksbnsfdn stnbhdsfbns sth st ömcfz,frznz"/>
        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Button" />
    </LinearLayout>
    

    在本例中,TextViews 宽度为 3/4s,Buttons 宽度为 Parent 宽度的 1/4,但您可以通过使用权重将其设置为您想要的任何值。

    【讨论】:

    • “按钮应该直接在文本视图旁边,并随着文本变大向右移动”此代码不会提供。该按钮将始终位于右端。
    【解决方案3】:

    使用 RelativeLayout 以获得更好的结果

    <RelativeLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toStartOf="@id/btn"
                android:layout_marginEnd="5dp"
                android:text="sdrndesfntzrfndtzmufzksbnsfdn stnbhdsfbns sth st ömcfz,frznz"/>
        
            <Button
                android:id="@+id/btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:text="Button" />
        </RelativeLayout>
    

    【讨论】:

    • 感谢您的回答,不幸的是,它不适用于较小的文本。它确实符合我的书面条件,但我希望 TextView 从左侧开始,就像我发布的第一张图片中一样
    【解决方案4】:

    在布局中进行

    这可以使用ConstraintLayout 修复:

    • packed横链
    • 0 水平偏差。
    • 启用约束宽度
    <?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:layout_width="wrap_content"
        android:layout_height="wrap_content">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="sdrndesfntzrfndtzmufzksbnsfdn stnbhdsfbns sth st ömcfz,frznz"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/button"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/textView"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    动态执行

    如果您仍然需要使用LinearLayout,那么您可以通过编程方式进行。由于您需要wrap_content TextViewButton 在相同的宽度上,所以从逻辑上讲这是无法实现的,因为当宽度的总和大于屏幕宽度时,某些视图会贪婪。

    因此,您决定这样做wrap_content,直到按钮在不超出屏幕末端的情况下换行。

    但是现在TextView 的宽度不应该是wrap_content;相反,它应该是一些固定大小;因为如果它仍然是wrap_content,它会在Button 上变得贪婪,并将其踢出屏幕或像你的情况一样被挤压。

    因此,我们需要以编程方式做一些工作来了解屏幕宽度,因此我们将 TextView 限制为等式:

    TextView_maxWidth =  screenWidth - buttonWidth
    

    解决方案 1:使用LinearLayout

    如果我们在布局上设置TextView 文本,现在按钮将被挤压,我们无法以编程方式确定按钮的wrap_content 大小,因此在此解决方案中,textView 文本在我们之后以编程方式设置获得了 Button 的大小。

    布局(没什么花哨的):

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />
    </LinearLayout>
    

    行为:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        LinearLayout root = findViewById(R.id.root);
        
        root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    root.getViewTreeObserver()
                            .removeOnGlobalLayoutListener(this);
                }
                int width = root.getWidth();
                Button button = findViewById(R.id.button);
                int buttonWidth = button.getWidth();
                int maxTextWidth = width - buttonWidth;
    
                TextView textView = findViewById(R.id.textView);
                textView.setMaxWidth(maxTextWidth);
                textView.setText("drndesfntzrfndtzmufzksbnsfdn stnbhdsfbns sth st ömcfz,frznz");
    
            }
        });
    }
    

    解决方案 2:使用ConstraintLayout

    LinearLayout不同,ConstraintLayout可以强制按钮大小为wrap_content而不被挤压,因此我们可以在布局上设置TextView的文本。

    布局:

    <?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/root"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="sdrn desf ntzrf ndtz mufzk sbnsf dn sdrnde sf ntzrfn dtz mufzks bns fdn sd rn de sfnt zrf ndtzmufzk sbnsfdnstn bhdsfbns sth st ömcfz, frznz"
            app:layout_constrainedWidth="true"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            app:layout_constraintStart_toEndOf="@id/textView"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    行为:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        ConstraintLayout root = findViewById(R.id.root);
        root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    root.getViewTreeObserver()
                            .removeOnGlobalLayoutListener(this);
                }
                
                int width = root.getWidth();
                Button button = findViewById(R.id.button);
                int buttonWidth = button.getWidth();
                int maxTextWidth = width - buttonWidth;
                
                TextView textView = findViewById(R.id.textView);
                textView.setMaxWidth(maxTextWidth); 
    
            }
        });
    }
    

    预览:

    【讨论】:

      猜你喜欢
      • 2023-01-28
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 2019-02-07
      • 2023-03-12
      • 1970-01-01
      • 2011-11-10
      • 2019-11-09
      相关资源
      最近更新 更多