提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
1.前言
谷歌给我们提供了大量优美的控件,但在实际开发中,我们常常会遇到很多自带控件无法实现的功能,这个时候我们可以通过自定义View来实现需求。本文将自定义一个带前缀的EditText,并通过此控件实现漂亮的UI效果。
效果如下:
一、自定义PretextEditText
- 首先继承EditText\TextInputEditText\AppCompatEditText(三者是继承关系)
- 重写三个构造函数
- 在styles自定义属性:前缀文字preText、前缀文字颜色pre_color、前缀文字大小pre_size
- 在onMeasure()方法获取控件的宽高
- 在onDraw()方法下绘制前缀文字
- .在value包下创建attr.xml,设置自定义属性
- 创建方法为画笔初始化和接收xml设置的属性
步骤如上,这是一个很简单的自定义View,因为没有考虑到很多情况,所以在使用时也会有很多限制。
自定义View代码如下
// 实现带前缀的EditText
public class PretextEditText extends TextInputEditText {
private Paint paint = new Paint();
private String mPreText; // 前缀文字
private int mPreTextColor;// 前缀文字颜色
private float mPreTextSize;// 前缀文字大小
private int mWidth;// 控件宽度
private int mHeight;// 控件高度
public PretextEditText(@NonNull Context context) {
super(context);
}
public PretextEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAttrs(attrs);
init();
}
public PretextEditText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getMeasuredWidth();// 836
mHeight = getMeasuredHeight();
}
private void initAttrs(AttributeSet attrs) {
TypedArray mTypedArray = getContext().obtainStyledAttributes(attrs, R.styleable.PretextEditText);
mPreText = mTypedArray.getString(R.styleable.PretextEditText_pre_text);
mPreTextColor = mTypedArray.getColor(R.styleable.PretextEditText_pre_text_color,Color.parseColor("#002424"));
mPreTextSize = mTypedArray.getDimension(R.styleable.PretextEditText_pre_text_size,16);
mTypedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText(mPreText,DensityUtil.dip2px(getContext(),12),(mHeight/2)+(DensityUtil.dip2px(getContext(),15)/2),paint);
}
/**
* 为画笔初始化
*/
private void init() {
paint = new Paint();
paint.setColor(mPreTextColor);
paint.setTextSize(mPreTextSize);
}
}
在资源包下创建属于你自己的自定义属性
values-attrs.xml
<declare-styleable name="PretextEditText">
<!--前缀文字-->
<attr name="pre_text" format="string"/>
<attr name="pre_text_color" format="color"/>
<attr name="pre_text_size" format="dimension"/>
</declare-styleable>
二、搭配TextInputLayout使用
步骤一也说过,因为项目赶,没有考虑到很多情况出现,所以在使用时防止bug出现,需要多种限制。
这里我采取的是嵌套在TextInputLayout
里面使用。
因为没考虑也原有的text文字冲突的原因,我采取了将文字长度和位置限制。
细致的同学大概能发现将控件在嵌套在TextInputLayout布局里,前缀文字和原有文字在高度上似乎有点不齐,这个也是我的疏漏点,后续会加以改进。
使用技巧:
- 将原有文字设置在末尾:
android:gravity="end"
- 将原有文字限制长度:android:maxLength=“30”
- 在嵌套后,对布局进行样式设置:
style="@style/TextInputLayout"
1.xml代码如下
<androidx.constraintlayout.widget.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"
tools:context=".PreTextActivity">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="22dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
style="@style/TextInputLayout">
<com.itaem.viewtest.PretextEditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="16sp"
android:textColor="#002424"
android:maxLength="30"
app:pre_text="前缀文字:"
app:pre_text_color="#002424"
app:pre_text_size="16sp"
android:gravity="end"/>
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
2.TextInputLayout的样式style="@style/TextInputLayout"
代码
<style name="TextInputLayout" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">match_parent</item>
<item name="android:minHeight">52dp</item>
<item name="android:layout_marginLeft">16dp</item>
<item name="android:layout_marginRight">16dp</item>
<item name="boxCornerRadiusBottomEnd">12dp</item>
<item name="boxCornerRadiusBottomStart">12dp</item>
<item name="boxCornerRadiusTopEnd">12dp</item>
<item name="boxCornerRadiusTopStart">12dp</item>
<item name="hintEnabled">false</item>
<item name="boxBackgroundColor">#F8F8F8</item>
<item name="android:focusable">false</item>
<item name="passwordToggleEnabled">true</item>
<item name="passwordToggleTint">#94A3AB</item>
<item name="boxStrokeWidth">0dp</item>
<item name="boxStrokeWidthFocused">0dp</item>
<item name="layout_constraintVertical_bias">0.0087</item>
</style>
3.总结
这个自定义View是个残缺品,这点我相信大家看完文章后大概都有这个想法,我也是这样想的,后续在项目做完后我会对此自定义View尽我所能进行完善。
当然如果有同学有改进想法也可以拿下使用,相关demo如下