LinearLayout:防止最后 child 被前面的大文本视图推出或挤压
LinearLayout: prevent last child from getting pushed out or squeezed by large textview before it
我有一个LinearLayout
,里面有两个children。第一个是带有动态内容的 TextView
,第二个是一个按钮。我的问题是按钮被推出 parent 或被挤压到不再可见的程度。我希望 TextView
认识到它的 parent 中没有更多的 space 和第二个 child,并开始一个新行而不是窃取 space 需要第二个 child。但是,按钮应该位于文本旁边,而不是默认情况下一直位于右侧。
我尝试了很多不同的方法,但都没有用,在下面的代码中,我只是发布了我想要工作的最小示例,没有我已经尝试过的不同更改。
<?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 的 space。行数当然应该是动态的,具体取决于视图中的文本。 Button 应该紧挨着 textview 并随着文本变大而向右移动。
这是我想要的视觉表示:
这是我得到的。
设置文本视图的 maxwidth
是一个简单的解决方案,但在更复杂和动态的布局中,您并不总是知道最大宽度是多少。所以最好有一个没有 hard-coded maxWidths 的解决方案。
您可以将 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,但您可以通过调整权重将其设置为任何您想要的值。
使用 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>
你可以试试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"
是正确调整元素大小的方法。
EDT build.gradle
配置:
allprojects {
repositories {
...
maven { url "https://maven.google.com" }
}
}
dependencies {
...
implementation 'com.google.android.flexbox:flexbox:3.0.0'
}
在布局中进行
这可以使用 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
TextView
和 Button
的宽度相同,因此从逻辑上讲这是无法实现的,因为当宽度之和大于屏幕宽度时,某些视图将会贪心。
因此你决定这样做 wrap_content
直到按钮在不超出屏幕末端的情况下环绕其宽度。
但是现在 TextView
宽度不应该是 wrap_content
;相反,它应该是一些固定大小;因为如果它仍然 wrap_content
它会在 Button
上贪婪,然后将它踢出屏幕或像你的情况一样被挤压。
因此,我们需要以编程方式做一些努力来了解屏幕宽度,因此我们将 TextView
限制为等式:
TextView_maxWidth = screenWidth - buttonWidth
解决方案 1:使用 LinearLayout
如果我们在布局上设置 TextView
文本,现在按钮将被挤压,我们无法以编程方式确定按钮的 wrap_content
大小,因此在此解决方案中,textView在我们获得按钮大小后以编程方式设置文本。
布局(没什么花哨的):
<?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);
}
});
}
预览:
我有一个LinearLayout
,里面有两个children。第一个是带有动态内容的 TextView
,第二个是一个按钮。我的问题是按钮被推出 parent 或被挤压到不再可见的程度。我希望 TextView
认识到它的 parent 中没有更多的 space 和第二个 child,并开始一个新行而不是窃取 space 需要第二个 child。但是,按钮应该位于文本旁边,而不是默认情况下一直位于右侧。
我尝试了很多不同的方法,但都没有用,在下面的代码中,我只是发布了我想要工作的最小示例,没有我已经尝试过的不同更改。
<?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 的 space。行数当然应该是动态的,具体取决于视图中的文本。 Button 应该紧挨着 textview 并随着文本变大而向右移动。
这是我想要的视觉表示:
这是我得到的。
设置文本视图的 maxwidth
是一个简单的解决方案,但在更复杂和动态的布局中,您并不总是知道最大宽度是多少。所以最好有一个没有 hard-coded maxWidths 的解决方案。
您可以将 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,但您可以通过调整权重将其设置为任何您想要的值。
使用 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>
你可以试试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"
是正确调整元素大小的方法。
EDT build.gradle
配置:
allprojects {
repositories {
...
maven { url "https://maven.google.com" }
}
}
dependencies {
...
implementation 'com.google.android.flexbox:flexbox:3.0.0'
}
在布局中进行
这可以使用 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
TextView
和 Button
的宽度相同,因此从逻辑上讲这是无法实现的,因为当宽度之和大于屏幕宽度时,某些视图将会贪心。
因此你决定这样做 wrap_content
直到按钮在不超出屏幕末端的情况下环绕其宽度。
但是现在 TextView
宽度不应该是 wrap_content
;相反,它应该是一些固定大小;因为如果它仍然 wrap_content
它会在 Button
上贪婪,然后将它踢出屏幕或像你的情况一样被挤压。
因此,我们需要以编程方式做一些努力来了解屏幕宽度,因此我们将 TextView
限制为等式:
TextView_maxWidth = screenWidth - buttonWidth
解决方案 1:使用 LinearLayout
如果我们在布局上设置 TextView
文本,现在按钮将被挤压,我们无法以编程方式确定按钮的 wrap_content
大小,因此在此解决方案中,textView在我们获得按钮大小后以编程方式设置文本。
布局(没什么花哨的):
<?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);
}
});
}