首页 > 程序开发 > 移动开发 > Android > 正文
Android开源框架PowerfulViewLibrary——PowerfulEditText的介绍和源码解析
2017-03-20 09:34:02       个评论    来源:Chay_Chan的博客  
收藏    我要投稿

Android开源框架PowerfulViewLibrary——PowerfulEditText的介绍

??很高兴自己写的前两篇博客都得到了郭霖(人称郭神)的认可,答应帮我发布在他的微信公众号上,这让我更有决心写好博客。我宁愿一个月一更,也不愿滥竽充数,写博客一方面是为了分享自己的技术和经验,另一方面是为了可以互相学习、交流和进步。最近决定开发一个开源框架,叫做PowerfulViewLibrary,也就是功能强大的View库,主要是为了方便开发,封装一些常用的控件,下面是相关介绍和使用。

PowerfulEditText具有的功能

1.自带清除文本功能

??PowerfulEditText自带清除文本功能,只需在布局文件该View属性中添加funcType,指定为canClear,就可以自带清除文本功能。

运行后,效果如下:

\

??上图所示的删除图标是默认的,当然也可以指定右侧删除按钮的图标,只需添加多drawableRight属性,这里建议使用一个selector,分别为普通状态和按压状态设置一张图片,这样当按压图标的时候,会有一种按压的状态,selector的编写如下:

源码分析:

public class PowerfulEditText extends EditText {

/**普通类型*/

private static final int TYPE_NORMAL = -1;

/**自带清除功能的类型*/

private static final int TYPE_CAN_CLEAR = 0;

/**自带密码查看功能的类型*/

private static final int TYPE_CAN_WATCH_PWD = 1;

public PowerfulEditText(Context context) {

this(context, null);

}

public PowerfulEditText(Context context, AttributeSet attrs) {

//这里构造方法也很重要,不加这个很多属性不能在XML里面定义

this(context, attrs, android.R.attr.editTextStyle);

}

public PowerfulEditText(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

ta = context.obtainStyledAttributes(attrs, R.styleable.PowerfulEditText);

funcType = ta.getInt(R.styleable.PowerfulEditText_funcType, TYPE_NORMAL);

...

init();

}

}

??PowerfulEditText继承于EditText,这里定义了三种类型,分别是普通类型、自带清除功能类型以及自带查看密码的功能,其中第二个构造方法,也就是只有两个参数的构造方法,里面调用该类的第三个构造方法(带三个参数的构造方法),需要传多一个int类型的参数,这里不能像以前定义其他View的时候那样直接传一个0,而是要传android.R.attr.editTextStyle,否则很多属性不能在XML里面定义。自己的逻辑操作init()方法,在第三个构造方法调用即可。

private void init() {

//获取EditText的DrawableRight,假如没有设置我们就使用默认的图片,左上右下

mRightDrawable = getCompoundDrawables()[2];

if (mRightDrawable == null) {

//如果右侧没有图标

if (funcType == TYPE_CAN_CLEAR) {

//有清除功能,设置默认叉号选择器

mRightDrawable = getResources().getDrawable(R.drawable.delete_selector);

}

}

//如果是清除功能,则一开始隐藏右侧默认图标,否则不隐藏右侧默认图标

setRightIconVisible(funcType == 0 ? false : true);

//设置输入框里面内容发生改变的监听

addTextChangedListener(new TextWatcher() {

/**

* 当输入框里面内容发生变化的时候回调的方法

*/

@Override

public void onTextChanged(CharSequence s, int start, int count,

int after) {

//如果是带有清除功能的类型,当文本内容发生变化的时候,根据内容的长度是否为0进行隐藏或显示

if (funcType == 0) {

setRightIconVisible(s.length() > 0);

}

if (textListener != null) {

textListener.onTextChanged(s, start, count, after);

}

}

@Override

public void beforeTextChanged(CharSequence s, int start, int count,

int after) {

if (textListener != null) {

textListener.beforeTextChanged(s, start, count, after);

}

}

@Override

public void afterTextChanged(Editable s) {

if (textListener != null) {

textListener.afterTextChanged(s);

}

}

});

}

/**

* 设置右侧图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去

*

* @param visible

*/

protected void setRightIconVisible(boolean visible) {

Drawable right = visible ? mRightDrawable : null;

setCompoundDrawables(getCompoundDrawables()[0],

getCompoundDrawables()[1], right, getCompoundDrawables()[3]);

}

/**

* 输入框文本变化的回调,如果需要进行多一些操作判断,则设置此listen替代*TextWatcher

*/

public interface TextListener {

void onTextChanged(CharSequence s, int start, int count, int after);

void beforeTextChanged(CharSequence s, int start, int count, int after);

void afterTextChanged(Editable s);

}

??在init()方法中,我们首先获取到输入框右侧的Drawable对象,通过getCompoundDrawables()[2]获取,getCompoundDrawables()方法是用于获取输入框四个方向图标的方法,返回的类型是一个Drawable数组,数组的元素排序分别是左(0)上(1)右(2)下(3)四个Drawable,这里我们需要获取右侧的图标对象,对应的下标为2。先判断右侧图标mRightDrawable是否为空,如果为空,并且当前的功能类型为自带清除功能,则使用默认的清除图标,通过调用getResources().getDrawable()加载对应的selector。

??通过判断功能类型是否属于带有清除功能的类型,设置右侧图标初始化的时候是否显示,接着设置文本内容变化的监听,通过监听文本内容的变化,判断右侧图标是否要显示。由于此处已经设置TextWatcher进行文本的监听,并且在onTextChanged()方法中进行了操作,所以在使用PowfulEditText的时候,如果需要在文本内容监听中做相应操作,则需要使用自己定义的TextListener来进行回调,而不是使用TextWatcher。

??关于输入框右侧图标点击事件的处理,所采用的方法是重写onTouchEvent()方法,对触摸响应进行处理,判断触摸的位置是否落在右侧图标的范围内,如果是,则认为是点击了该图标。

/**

* 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件

* 当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和

* EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向就没有考虑

*/

@Override

public boolean onTouchEvent(MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_UP) {

if (getCompoundDrawables()[2] != null) {

boolean isTouched = event.getX() > (getWidth() - getTotalPaddingRight())

&& (event.getX() < ((getWidth() - getPaddingRight())));

if (isTouched) {

if (onRightClickListener == null) {

if (funcType == TYPE_CAN_CLEAR) {

//如果没有设置右边图标的点击事件,并且带有清除功能,默认清除文本

this.setText("");

} else if (funcType == TYPE_CAN_WATCH_PWD) {

//如果没有设置右边图标的点击事件,并且带有查看密码功能,点击切换密码查看方式

...

}

} else {

//如果有则回调

...

}

}

}

}

return super.onTouchEvent(event);

}

??当按下的x值在EditText的宽度 - (图标到控件右边的间距 + 图标的宽度)(getTotalPaddingRight()) 和 EditText的宽度 - 图标到控件右边的间距之间,则认为是点击了图标(如果为了精确计算,可以考虑y值方向的判断)然后进行相应的操作,如果没有设置右侧图标的点击事件,并且当前属于带有清除功能类型,则默认清除文本。

2.自带密码输入框切换明文密文格式的功能

??PowerfulEditText自带密码输入框切换明文密文格式的功能,目前大多数App密码输入栏一般支持密码明文、密文的显示,如果需要用到该功能,可以将funcType中指定为canWatchPwd,就可以轻松使用这种功能,使用如下:

运行后,效果如下:

\

源码解析:

??同样也是在onTouchEvent()方法中做处理,如果当前的功能类型属于查看密码功能类型,则根据eyeOpen这个标识进行判断,判断当前是否是明文,如果是,点击后则变成密文,否则变成明文。

点击复制链接 与好友分享!回本站首页
上一篇:单例模式在Android中的应用
下一篇:android文件关联之mime type
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做实用的IT技术学习网站