The widgets that can shrink/expand would be added into ConstraintLayout
Flow to adjust their right placement "in the same row/line if they can fit to a single line, or to flow to next row(s)/line(s) if they are expanded enough".
In your layout you'd add the two large buttons into the flow, and constraint these buttons with the head widget to be centered vertically.
Here is a demo:
<?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:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/head_view"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:src="@drawable/ic_android_black_24dp"
app:layout_constraintBottom_toBottomOf="@+id/view2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/view1" />
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/flow"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
app:constraint_referenced_ids="view1,view2"
app:flow_horizontalBias="0"
app:flow_horizontalGap="10dp"
app:flow_horizontalStyle="packed"
app:flow_maxElementsWrap="2"
app:flow_verticalGap="10dp"
app:flow_wrapMode="chain"
app:layout_constraintBottom_toBottomOf="@+id/head_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/head_view"
app:layout_constraintTop_toTopOf="@+id/head_view" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#6C08FB"
android:padding="12dp"
android:text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
android:textColor="@android:color/black"
app:layout_constrainedWidth="true" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0BDAC6"
android:padding="12dp"
android:text="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
app:layout_constrainedWidth="true" />
</androidx.constraintlayout.widget.ConstraintLayout>
Preview:
Edit
In my case, if they don't fit in the same line, i must break the line in two and make them fit the entire width available ( i see that you put a wrap_content as width). I always need to fit the entire width of the screen also!
In case of 2 lines, if the widths of view1
& view2
are constrained with 0dp
to fill the parent width, this will never make them expand to the next line; they will stick to width constraints and will expand towards the bottom side by side which you didn't need as well.
This is because currently these views expand/shrink based on their content. and that will make the flow lines actually work. If their widths is 0dp
they won't expand but instead will stick to the constraints regardless of the size of the their content.
What you want to do can be achieved programmatically with a workaround by having a conditional minimum width for view1
& view2
whenever there are two lines.
To decide if the contents requires two lines, we can sum up the occupied view & margin widths and compare that to the Flow width:
Flow flow = findViewById(R.id.flow);
TextView view1 = findViewById(R.id.view1);
TextView view2 = findViewById(R.id.view2);
flow.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
flow.getViewTreeObserver().removeOnGlobalLayoutListener(this);
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) flow.getLayoutParams();
int leftMargin = params.leftMargin;
int flowHorizontalGap = (int) convertDpToPixel(10f, MainActivity.this);
int occupiedSpace = leftMargin + view1.getWidth() + flowHorizontalGap + view2.getWidth();
// Checking if the content need to expand to two lines
if (occupiedSpace > flow.getWidth()) {
int width = flow.getWidth() ;
view1.setMinWidth(width);
view2.setMinWidth(width);
}
}
});
public static float convertDpToPixel(float dp, Context context) {
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}