如何用ConstraintLayout适配多屏幕并解决视图布局异常问题
解决ConstraintLayout适配小屏幕及AdView隐藏后的布局问题
我来帮你搞定这两个布局适配的问题,咱们先分析问题根源,再给出调整后的完整布局代码:
问题根源分析
- 小屏幕ImageView被AdView遮挡:原来的顶部内容没有和底部布局设置明确的约束关系,导致小屏幕上内容高度超出屏幕,底部的AdView会往上覆盖顶部的ImageView。
- AdView隐藏后SpeedDialView位置异常:底部用了RelativeLayout,通过
layout_above="@id/mAdView"定位SpeedDialView,但当AdView隐藏时,这个依赖关系失效,RelativeLayout无法自动调整位置。
调整后的布局代码
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.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="match_parent" android:layout_height="match_parent" android:background="@drawable/home_bg"> <!-- 顶部图片 --> <ImageView android:id="@+id/topImage" android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginTop="20dp" android:contentDescription="@string/app_name" android:src="@drawable/splash_heading" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <!-- 结果标题 --> <TextView android:id="@+id/tvAllOverResult" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:text="@string/allover_result" android:textColor="@color/colorBlue" android:textSize="20sp" android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/topImage" /> <!-- 左侧SeekBar卡片 --> <android.support.v7.widget.CardView android:id="@+id/firstCardView" android:layout_width="60dp" android:layout_height="wrap_content" android:layout_marginEnd="10dp" app:cardElevation="5dp" app:layout_constraintBottom_toBottomOf="@+id/tvVs" app:layout_constraintEnd_toStartOf="@+id/tvVs" app:layout_constraintTop_toTopOf="@+id/tvVs"> <abak.tr.com.boxedverticalseekbar.BoxedVertical android:id="@+id/firstSeekBar" android:layout_width="match_parent" android:layout_height="250dp" android:layout_gravity="center" app:backgroundColor="@android:color/white" app:defaultImage="@drawable/ic_play" app:imageEnabled="true" app:max="100" app:maxImage="@drawable/ic_play" app:minImage="@drawable/ic_play" app:progressColor="@color/colorGreen" app:textEnabled="false" app:touchDisabled="false" /> </android.support.v7.widget.CardView> <!-- 左侧分数标签 --> <TextView android:id="@+id/tvOneScore" android:layout_width="0dp" android:layout_height="wrap_content" android:background="@android:color/white" android:gravity="center" android:text="Streak" android:textColor="@color/colorBlue" android:textSize="12sp" android:textStyle="bold" app:layout_constraintEnd_toEndOf="@+id/firstCardView" app:layout_constraintStart_toStartOf="@+id/firstCardView" app:layout_constraintTop_toBottomOf="@+id/firstCardView" /> <!-- VS文本 --> <TextView android:id="@+id/tvVs" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="V/S" android:textColor="@color/colorBlue" android:textSize="40sp" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <!-- 右侧SeekBar卡片 --> <android.support.v7.widget.CardView android:id="@+id/secondCardView" android:layout_width="60dp" android:layout_height="250dp" android:layout_marginStart="10dp" app:cardElevation="5dp" app:layout_constraintBottom_toBottomOf="@+id/tvVs" app:layout_constraintStart_toEndOf="@+id/tvVs" app:layout_constraintTop_toTopOf="@+id/tvVs"> <abak.tr.com.boxedverticalseekbar.BoxedVertical android:id="@+id/secondSeekBar" android:layout_width="match_parent" android:layout_height="250dp" android:layout_gravity="center" app:backgroundColor="@android:color/white" app:defaultImage="@drawable/ic_play" app:imageEnabled="true" app:max="100" app:maxImage="@drawable/ic_play" app:minImage="@drawable/ic_play" app:progressColor="@color/colorGreen" app:textEnabled="false" app:touchDisabled="false" /> </android.support.v7.widget.CardView> <!-- 右侧分数标签 --> <TextView android:id="@+id/tvTwoScore" android:layout_width="0dp" android:layout_height="wrap_content" android:background="@android:color/white" android:gravity="center" android:text="Steps" android:textColor="@color/colorBlue" android:textSize="12sp" android:textStyle="bold" app:layout_constraintEnd_toEndOf="@+id/secondCardView" app:layout_constraintStart_toStartOf="@+id/secondCardView" app:layout_constraintTop_toBottomOf="@+id/secondCardView" /> <!-- Win文本 --> <TextView android:id="@+id/tvWin" android:layout_width="0dp" android:layout_height="wrap_content" android:background="@android:color/white" android:gravity="center" android:padding="10dp" android:text="@string/str_win" android:textColor="@color/colorBlue" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tvTwoScore" /> <!-- Play按钮 --> <ImageView android:id="@+id/tvPlayGame" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginBottom="20dp" android:scaleType="fitXY" android:src="@drawable/ic_play" app:backgroundTint="#0b961e" app:layout_constraintBottom_toTopOf="@id/bottomLayout" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tvWin" /> <!-- 底部布局替换为ConstraintLayout --> <android.support.constraint.ConstraintLayout android:id="@+id/bottomLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="20dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"> <com.leinardi.android.speeddial.SpeedDialOverlayLayout android:id="@+id/speedDialOverlayLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#81000000" app:clickable_overlay="true" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <com.leinardi.android.speeddial.SpeedDialOverlayLayout android:id="@+id/speedDialOverlayLayout2" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#81000000" app:clickable_overlay="true" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <!-- 设置goneMargin,当AdView隐藏时自动贴底部 --> <com.leinardi.android.speeddial.SpeedDialView android:id="@+id/speedDial" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" app:backgroundTint="@android:color/white" app:layout_behavior="@string/speeddial_scrolling_view_snackbar_behavior" app:layout_constraintBottom_toTopOf="@id/mAdView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_goneMarginBottom="8dp" app:sdExpansionMode="top" app:sdMainFabAnimationRotateAngle="90" app:sdMainFabClosedBackgroundColor="@android:color/white" app:sdMainFabClosedSrc="@drawable/ic_settings" app:sdMainFabOpenedBackgroundColor="#4e4c4c" app:sdMainFabOpenedSrc="@drawable/ic_close" app:sdUseReverseAnimationOnClose="true" /> <com.leinardi.android.speeddial.SpeedDialView android:id="@+id/langSpeedDial" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" app:layout_behavior="@string/speeddial_scrolling_view_snackbar_behavior" app:layout_constraintBottom_toTopOf="@id/mAdView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_goneMarginBottom="8dp" app:sdExpansionMode="top" app:sdMainFabAnimationRotateAngle="90" app:sdMainFabClosedBackgroundColor="@android:color/white" app:sdMainFabClosedSrc="@drawable/ic_language" app:sdMainFabOpenedBackgroundColor="#4e4c4c" app:sdMainFabOpenedSrc="@drawable/ic_close" app:sdUseReverseAnimationOnClose="true" /> <com.google.android.gms.ads.AdView android:id="@+id/mAdView" android:layout_width="match_parent" android:layout_height="wrap_content" app:adSize="BANNER" app:adUnitId="@string/bannerID" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>
关键修改说明
- 修复顶部内容与底部布局的约束:给
tvPlayGame添加了app:layout_constraintBottom_toTopOf="@id/bottomLayout",确保顶部所有内容始终在底部布局的上方,不会被AdView遮挡,小屏幕上会自动留出底部空间。 - 替换底部RelativeLayout为ConstraintLayout:ConstraintLayout的
goneMargin属性可以完美处理View隐藏后的布局调整。给两个SpeedDialView设置了app:layout_constraintBottom_toTopOf="@id/mAdView"和app:layout_constraintBottom_toBottomOf="parent",同时添加app:layout_goneMarginBottom="8dp",这样当AdView显示时,它们在AdView上方;当AdView隐藏时,会自动贴到底部并保留margin。 - 清理无效约束:移除了原布局中冲突的约束(比如
topImage里的app:layout_constraintStart_toEndOf="parent"),避免布局计算异常。
这样调整后,你的布局就能适配所有屏幕尺寸,并且AdView显示/隐藏时都能保持正确的布局效果啦!
内容的提问来源于stack exchange,提问作者Goku
相关产品推荐
相关产品推荐

