不使用Google Material库,如何为EditText实现底部边框高亮效果?
嘿,我来帮你搞定这个底部边框高亮的需求!不用依赖官方Material Design库,也不一定非得写自定义View,有几种实用方案都能实现你要的效果,而且全部支持API 19及以上~
方案一:原生Drawable组合(最简单高效)
这个方案完全用Android原生的Drawable实现,不用写Java/Kotlin代码,直接通过XML配置就能搞定。核心思路是用layer-list和selector来切换聚焦/非聚焦状态的样式。
步骤1:创建默认状态的底部边框Drawable
在res/drawable下新建edittext_bottom_border.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 透明背景,避免覆盖EditText的默认交互效果 --> <item> <shape android:shape="rectangle"> <solid android:color="@android:color/transparent" /> </shape> </item> <!-- 底部灰色边框,上下左右只保留底部 --> <item android:top="-2dp" android:left="-2dp" android:right="-2dp"> <shape android:shape="rectangle"> <stroke android:width="2dp" android:color="#CCCCCC" /> </shape> </item> <!-- 默认隐藏的高亮条 --> <item android:gravity="bottom"> <shape android:shape="rectangle"> <solid android:color="#2196F3" /> <!-- Material蓝,可自行替换 --> <size android:height="2dp" /> </shape> </item> </layer-list>
步骤2:创建聚焦状态的Drawable
新建res/drawable/edittext_bottom_border_selected.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="rectangle"> <solid android:color="@android:color/transparent" /> </shape> </item> <!-- 聚焦时边框变高亮色 --> <item android:top="-2dp" android:left="-2dp" android:right="-2dp"> <shape android:shape="rectangle"> <stroke android:width="2dp" android:color="#2196F3" /> </shape> </item> <!-- 聚焦时显示高亮条 --> <item android:gravity="bottom"> <shape android:shape="rectangle"> <solid android:color="#2196F3" /> <size android:height="2dp" /> </shape> </item> </layer-list>
步骤3:创建状态选择器
新建res/drawable/edittext_border_selector.xml,用来根据焦点状态切换样式:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/edittext_bottom_border_selected" android:state_focused="true" /> <item android:drawable="@drawable/edittext_bottom_border" /> </selector>
步骤4:在布局中使用
把这个选择器设为EditText的背景即可:
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/edittext_border_selector" android:padding="16dp" android:textColor="@android:color/black" />
这个方案零代码,完全原生,API 19完美兼容,是最推荐的方案。
方案二:自定义View(灵活扩展)
如果你需要更个性化的效果(比如高亮条从中间展开的动画、动态修改颜色等),可以自定义一个EditText,通过重写onDraw来绘制边框和高亮条。
自定义View代码(Java)
public class CustomBorderEditText extends androidx.appcompat.widget.AppCompatEditText { private Paint borderPaint; private Paint highlightPaint; // 默认样式参数 private int borderColor = Color.parseColor("#CCCCCC"); private int highlightColor = Color.parseColor("#2196F3"); private int borderWidth = 2; private int highlightHeight = 2; private boolean isFocused = false; public CustomBorderEditText(Context context) { super(context); init(); } public CustomBorderEditText(Context context, AttributeSet attrs) { super(context, attrs); init(); // 支持通过XML自定义属性 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomBorderEditText); borderColor = ta.getColor(R.styleable.CustomBorderEditText_borderColor, borderColor); highlightColor = ta.getColor(R.styleable.CustomBorderEditText_highlightColor, highlightColor); borderWidth = ta.getDimensionPixelSize(R.styleable.CustomBorderEditText_borderWidth, borderWidth); highlightHeight = ta.getDimensionPixelSize(R.styleable.CustomBorderEditText_highlightHeight, highlightHeight); ta.recycle(); } private void init() { // 初始化画笔 borderPaint = new Paint(); borderPaint.setColor(borderColor); borderPaint.setStrokeWidth(borderWidth); borderPaint.setStyle(Paint.Style.STROKE); highlightPaint = new Paint(); highlightPaint.setColor(highlightColor); highlightPaint.setStyle(Paint.Style.FILL); // 去掉默认背景,避免冲突 setBackground(null); setPadding(16, 16, 16, 16); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制底部边框 canvas.drawLine(0, getHeight() - borderWidth, getWidth(), getHeight() - borderWidth, borderPaint); // 聚焦时绘制高亮条 if (isFocused) { canvas.drawRect(0, getHeight() - highlightHeight, getWidth(), getHeight(), highlightPaint); } } @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(focused, direction, previouslyFocusedRect); isFocused = focused; invalidate(); // 焦点变化时重绘视图 } }
添加自定义属性
在res/values/attrs.xml中添加自定义属性,方便在XML中配置样式:
<declare-styleable name="CustomBorderEditText"> <attr name="borderColor" format="color" /> <attr name="highlightColor" format="color" /> <attr name="borderWidth" format="dimension" /> <attr name="highlightHeight" format="dimension" /> </declare-styleable>
布局中使用
<com.yourpackage.CustomBorderEditText android:layout_width="match_parent" android:layout_height="wrap_content" app:borderColor="#CCCCCC" app:highlightColor="#2196F3" app:borderWidth="2dp" app:highlightHeight="2dp" />
这个方案可以轻松扩展动画效果(比如用ValueAnimator实现高亮条的展开动画),完全控制绘制逻辑,API 19也能完美支持。
方案三:轻量第三方库(可选)
如果你不想自己写代码,又无法使用官方Material库,可以考虑一些轻量的第三方Material风格控件库,比如com.github.florent37:materialtextfield:1.0.7,这个库体积小,支持API 16+,提供了类似Material Design的输入框样式。不过这个方案需要依赖第三方库,如果你有不能引入第三方库的限制,还是优先前两种方案。
内容的提问来源于stack exchange,提问作者Artem Griukov

