如何让View高度随宽度自动调整?FrameLayout高度设为宽度70%
Hey there! Let's break down these two Android layout adaptation questions—they’re super common, so I’ll walk you through the most practical solutions for each.
There are a few reliable ways to achieve this, depending on your layout setup:
Use ConstraintLayout's dimension ratio constraint (most straightforward)
Wrap your target View in a ConstraintLayout, set its width/height to0dp(match_constraint), then useapp:layout_constraintDimensionRatioto define the width-to-height ratio. For example:<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <View android:id="@+id/adaptive_view" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintDimensionRatio="H,1:1" <!-- H = height based on width; 1:1 means square --> app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>Note: Use
Hto base height on width, orWto base width on height. Adjust the ratio (e.g.,2:1for height = 50% of width) as needed.Custom View with overridden
onMeasure
If you can’t use ConstraintLayout, create a custom View that calculates its height manually inonMeasure:public class AdaptiveHeightView extends View { private float widthToHeightRatio = 1.0f; // Default 1:1 public AdaptiveHeightView(Context context) { super(context); } public AdaptiveHeightView(Context context, AttributeSet attrs) { super(context, attrs); // Optional: Add custom attributes to set the ratio via XML TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.AdaptiveHeightView); widthToHeightRatio = ta.getFloat(R.styleable.AdaptiveHeightView_ratio, 1.0f); ta.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); int calculatedHeight = (int) (measuredWidth * widthToHeightRatio); setMeasuredDimension(measuredWidth, calculatedHeight); } }Then use this custom View in your layout—its height will automatically match the width based on your set ratio.
Use AndroidX's AspectRatioFrameLayout
Google’s AndroidX library provides a dedicated layout for this use case:<androidx.aspectratio.widget.AspectRatioFrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:aspectRatio="1.77" <!-- 16:9 ratio, for example --> app:aspectRatioEnabled="true"> <!-- Your child View goes here --> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"/> </androidx.aspectratio.widget.AspectRatioFrameLayout>
Given your existing FrameLayout (width set to match_parent), here’s how to make its height 70% of its width:
Option 1: Use ConstraintLayout (simplest approach)
Wrap your FrameLayout in a ConstraintLayout, adjust its height to 0dp, and set the dimension ratio to 10:7 (since 7/10 = 70%):
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <FrameLayout android:id="@+id/fiew" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp" app:layout_constraintDimensionRatio="H,10:7" <!-- Height = 70% of width --> app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
Option 2: Custom FrameLayout
If you prefer not to use ConstraintLayout, create a custom FrameLayout that overrides onMeasure:
public class RatioFrameLayout extends FrameLayout { private final float heightToWidthRatio = 0.7f; // 70% public RatioFrameLayout(Context context) { super(context); } public RatioFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); int calculatedHeight = (int) (measuredWidth * heightToWidthRatio); // Update height measure spec to our calculated value heightMeasureSpec = MeasureSpec.makeMeasureSpec(calculatedHeight, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
Then replace your original FrameLayout with this custom one in XML:
<com.yourpackage.RatioFrameLayout android:id="@+id/fiew" android:layout_width="match_parent" android:layout_height="wrap_content" <!-- This will be overridden by onMeasure --> android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp"> </com.yourpackage.RatioFrameLayout>
内容的提问来源于stack exchange,提问作者D T

