Android 4.4(KitKat)中AppCompatTextView的android:gravity=center失效问题
android:gravity="center" 在 AppCompatTextView 不生效的解决方案 刚好之前处理过一模一样的KitKat兼容性问题,给你整理几个靠谱的思路和方案:
首先先还原你提到的布局代码:
<androidx.appcompat.widget.AppCompatTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:layout_alignTop="@+id/iv_security_code" android:layout_alignBottom="@+id/iv_security_code" app:drawableLeftCompat="@drawable/ic_refresh_black_24dp" android:gravity="center" />
问题根源分析
这个bug只出现在Android 4.4(API 19),Lollipop及以上完全正常。核心问题是:当AppCompatTextView在RelativeLayout中通过layout_alignTop和layout_alignBottom强制和另一个视图等高时,KitKat的系统布局逻辑没有把这个强制拉伸后的高度作为gravity="center"的计算基准,反而还是只参考TextView自身wrap_content算出的内容高度,导致内部的drawable和文字没法真正居中。
临时修复方案
你提到的改成固定高度确实能快速解决,比如把高度设成和iv_security_code一致的固定值:
android:layout_height="48dp" <!-- 替换为目标视图的实际高度 -->
这种方式让TextView的高度明确,系统能正确识别gravity的生效范围,缺点是如果目标视图高度动态变化的话会失效。
彻底兼容解决方案
如果不想固定高度,可以试试这几个更稳妥的方法:
1. 用LinearLayout包裹TextView做中转
把TextView放在LinearLayout里,让LinearLayout去和目标视图对齐,TextView自身设match_parent高度,借助LinearLayout的gravity来辅助居中:
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/iv_security_code" android:layout_alignBottom="@+id/iv_security_code" android:gravity="center"> <androidx.appcompat.widget.AppCompatTextView android:layout_width="wrap_content" android:layout_height="match_parent" android:clickable="true" app:drawableLeftCompat="@drawable/ic_refresh_black_24dp" android:gravity="center" /> </LinearLayout>
这种方式绕过了TextView自身在KitKat的bug,兼容性很强。
2. 自定义AppCompatTextView重写测量逻辑
针对KitKat版本手动调整内边距,确保内容居中:
public class CenteredAppCompatTextView extends AppCompatTextView { public CenteredAppCompatTextView(Context context) { super(context); } public CenteredAppCompatTextView(Context context, AttributeSet attrs) { super(context, attrs); } public CenteredAppCompatTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 仅在KitKat及以下版本处理兼容性 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { int parentHeight = MeasureSpec.getSize(heightMeasureSpec); // 手动计算上下内边距,让内容居中 int verticalPadding = (parentHeight - getMeasuredHeight()) / 2; setPadding(getPaddingLeft(), verticalPadding, getPaddingRight(), verticalPadding); } } }
然后布局里直接用这个自定义View替换原生AppCompatTextView即可。
3. 切换到ConstraintLayout布局
如果项目已经在用ConstraintLayout,直接用它的约束系统来实现对齐和居中,ConstraintLayout在低版本的布局计算逻辑更稳定:
<androidx.appcompat.widget.AppCompatTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" app:drawableLeftCompat="@drawable/ic_refresh_black_24dp" android:gravity="center" app:layout_constraintTop_toTopOf="@+id/iv_security_code" app:layout_constraintBottom_toBottomOf="@+id/iv_security_code" />
这种方式不需要额外嵌套或自定义View,代码更简洁。
内容的提问来源于stack exchange,提问作者Shanki Bansal

