Doing it in Layout
This can be fixed using ConstraintLayout
with:
packed
horizontal chain
- 0 horizontal bias.
- Enable constraintWidth
<?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>
Doing it dynamically
If you still need to use LinearLayout
, then you can do it programmtically. As you need to wrap_content
both the TextView
and Button
in the same width, so logically this is not achievable because when the sum of widths is greater than the screen width, some view will be greedy on the other.
Therefore you decided to do that wrap_content
until the button takes wraps its width without going off the end of the screen.
But now the TextView
width shouldn't be wrap_content
; instead it should be some fixed size; because if it still wrap_content
it'll be greedy on the Button
, and kick it off the screen or being squeezed like in your case.
So, we need to do some effort programmatically to know the screen width, so we will limit the TextView
to the equation:
TextView_maxWidth = screenWidth - buttonWidth
Solution 1: Using LinearLayout
If we set the TextView
text on the layout, now the button will be squeezed, and we couldn't determine the wrap_content
size of the Button programmatically, so in this solution the textView text is set programmatically after we got the Button size.
layout (Nothing fancy):
<?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>
Behavior:
@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");
}
});
}
Solution 2: Using ConstraintLayout
Unlike LinearLayout
, ConstraintLayout
can force the button size to be wrap_content
without being squeezed, and therefore we can set the text of the TextView
on layout.
Layout:
<?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>
Behavior:
@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);
}
});
}
Previews: