一、需求:
由于项目中要用到带下滑线的EditTextView(大体如下图,这也是本demo的效果图),本来说做一个背影图片放置即可,最后一想还是练习一下自定义view吧,反正自己的自定义view很烂。索性就自定义一个。
二、动手之前:
动手去做之前,先简单说一下思路,关于自定义view的步骤这里不说明,以后会写相关文章来说明的。这里我们选择继承EditText来自定义我们的View。无非就是画一条直线而已,画的时候x从0到view.getWidth(),y人view.getHeight到view.getHeight()即可。当然线的颜色和线的高度我们可以设置自定义属性来让xml去动态加载。
三、直接动手:
1、先自定义我们要属性,大概要一个下滑线的颜色和高度就可以了。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 定义自定义属性 -->
<attr name="line_color" format="color"/>
<attr name="line_height" format="dimension"/>
<!-- 声明自定义属性 -->
<declare-styleable name="edittext_bg">
<attr name="line_color"/>
<attr name="line_height"/>
</declare-styleable>
</resources>
2、获取自定义属性,一般在三个参数的构造方法中取,当然也可以在两个参数的构造方法中去取。
public class CusTomLineEditText extends EditText {
/**下滑线的颜色**/
private int line_corlor ;
/**下滑线的高度**/
private int line_height ;
/**画笔**/
private Paint mPaint ;
public CusTomLineEditText(Context context){
//调用两个参数的构造方法
this(context,null) ;
}
/**
* 加载xml的时候调用这个构造方法
* @param context
* @param attrs
*/
public CusTomLineEditText(Context context, AttributeSet attrs){
//调用三个参数的构造方法
this(context,attrs,0) ;
}
public CusTomLineEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initTypeArray(context, attrs, defStyle);
initPaint();
}
/**初始化Paint***/
private void initPaint() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(line_height) ;
mPaint.setColor(line_corlor);
}
/***
* 初始化TypedArray
* @param context
* @param attrs
* @param defStyle
*/
private void initTypeArray(Context context, AttributeSet attrs, int defStyle) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.edittext_bg, defStyle, 0) ;
int n = a.getIndexCount() ;
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i) ;
switch (attr) {
case R.styleable.edittext_bg_line_color:
//从xml取得下滑线的颜色 默认是绿色
line_corlor = a.getColor(attr, Color.GREEN) ;
break;
case R.styleable.edittext_bg_line_height:
//从xml取得下滑线的高 默认是1dip dip to px
line_height = a.getDimensionPixelSize(attr, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics())) ;
break ;
}
}
//使用完一定要recycle 保证资源回收
a.recycle() ;
}
代码都很简单,注释也详细,不做细致的解析,相信都能看懂。
3、我们这里不需要重写OnMeasure(),直接重写Ondraw()即可
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 画底线
canvas.drawLine(0, this.getHeight(), this.getWidth(),this.getHeight(), mPaint);
}
经过以上三步就可以制作属于我们的带下滑线的自定义EditText了。
4、使用自定义EditText.
首先在布局文件中一般在根布局中指定我们自定义view的全名空间,以致于我们能找到自定义的属性。
<pre name="code" class="html"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:jun="http://schemas.android.com/apk/res/com.jun.customlineedittext"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip" >
<TextView
android:id="@+id/tv_user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="User:" />
<com.jun.customlineedittext.view.CusTomLineEditText
android:layout_width="match_parent"
android:layout_height="40dip"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/tv_user"
android:background="@null"
android:gravity="center_vertical"
jun:line_color="#7ac943"
jun:line_height="2dip" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip" >
<TextView
android:id="@+id/pass_user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Pass:" />
<com.jun.customlineedittext.view.CusTomLineEditText
android:layout_width="match_parent"
android:layout_height="40dip"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/pass_user"
android:background="@null"
android:gravity="center_vertical"
android:hint="asdfasdf"
jun:line_color="#7ac943"
jun:line_height="2dip" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginTop="15dip"
android:gravity="center" >
<Button
android:id="@+id/cancel"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Cancel" />
<Button
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dip"
android:layout_toRightOf="@+id/cancel"
android:text="Save" />
</RelativeLayout>
</LinearLayout>
这样就完成了我们开头需求中给出的图例demo了。
5、测试
直接运行手机跑起项目,发现EditText点击不起作用,键盘弹不出来,what the fk?尼玛,我是继承EditText的杂会没有EditText的原有属性呢?难道要让我拿代码硬把键盘调出来?(本人亲测,用代码硬调,还是出不来键盘。)其实解决这个问题一只需要改动一行代码即可,具体说一个常量即可。还记得我们的CustomLineEditText的两个参数的构造方法吗,是这样写的this(context,attrs,0)直接调用三个参数的构造方法。第三个参数是默认的样式属性,我们只需要把this(context,attrs,0)改成this(context,attrs,android.R.attr.editTextStyle)即可让我们的EditText弹出键盘了。
6、以上就完成了一个自定义带下线的EditText.如果有什么不对,欢迎指正。