Android学习小Demo(22)带删除按钮的TextView
来源:互联网 发布:java 获取post还是get 编辑:程序博客网 时间:2024/05/29 15:42
很多时候,会有一些很简单的需求,比如你利用一个Button弹出某个页面,选择了某个对象之后,你会将对象的某些属性,比如名称之类,显示在按钮上。
而紧跟着,又会想着,能不能把刚选择的对象给清掉,比如把按钮上的文字给去掉,这个时候,你就会希望,要是按钮后面还能够有多一个图标,一点击,就把当前控件的文字等清除掉就好了,并且还会对应的回调函数,让我们多处理一些事情,那多好。
很可惜,Android并没有提供现成的控件供我们这样使用,但换个角度想想,这又根本不可惜,因为我们可以自己来实现这样的效果呀,这是多有意思的一件事情啊。
即使有时候,实现很简单,只是做多一点点事情,但当我们把它实现了,满足的感觉依然会油然而生啊,对吧!
现在想做的事情就很简单,想自定义一个控件,实现功能如下:
1)实现像Button一样的点击效果
2)又能够在后面添加一个删除小图标,可删除此控件上的内容
3)还要有一个响应函数,能够在删除之后做一些操作。
我们知道,自定义控件有多种方式,我们可以直接继承View,自己去画各种各样的UI,也可以简单地继承已存在的控件,比如Button就是继承TextView的一个简单的控件。
提到Button就是继承TextView的,而TextView又有CompoundDrawable的概念,那很显然,我们就可以利用TextView来实现我们的功能了。
太啰嗦了,还是先上代码吧
public class ClearableTextView extends TextView { public interface OnTextClearListener { public void onTextClear(ClearableTextView v); } private Context mContext; private Drawable mDrawableRight; private Rect mBounds; private OnTextClearListener mOnTextClearListener; public ClearableTextView(Context context) { super(context); initialize(context); } public ClearableTextView(Context context, AttributeSet attrs) { super(context, attrs); initialize(context); } private void initialize(Context context) { mContext = context; mDrawableRight = mContext.getResources().getDrawable(R.drawable.ic_delete); mDrawableRight.setBounds(0, 0, mDrawableRight.getMinimumWidth(), mDrawableRight.getMinimumWidth()); setClickable(true); setMinWidth(120); setGravity(Gravity.CENTER_VERTICAL); setPadding(8, 8, 8, 8); setCompoundDrawablePadding(8); } @Override public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) { if (right != null) { mDrawableRight = right; } super.setCompoundDrawables(left, top, mDrawableRight, bottom); } public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP && mDrawableRight != null) { mBounds = mDrawableRight.getBounds(); final int x = (int) event.getX(); final int y = (int) event.getY(); if (x >= (this.getWidth() - mBounds.width()) && x <= (this.getWidth() - this.getPaddingRight()) && y >= this.getPaddingTop() && y <= (this.getHeight() - this.getPaddingBottom())) { clear(); event.setAction(MotionEvent.ACTION_CANCEL); } } return super.onTouchEvent(event); } public void setTextClearable(CharSequence text) { setText(text); if (text == null || text.length() == 0) { super.setCompoundDrawables(null, null, null, null); } else { super.setCompoundDrawables(null, null, mDrawableRight, null); } } private void clear() { setTextClearable(""); if (mOnTextClearListener != null) { mOnTextClearListener.onTextClear(this); } super.setCompoundDrawables(null, null, null, null); } public void setOnTextClearListener(OnTextClearListener onTextClearListener) { mOnTextClearListener = onTextClearListener; } public void finalize() throws Throwable { mDrawableRight = null; mBounds = null; super.finalize(); }}
我们创建了一个ClearableTextView,继承于TextView,关键的代码如下:
1)设置CompoundDrawables。
我们知道在xml布局中,对于TextView,我们可以利用DrawableLeft, DrawableRight, DrawableTop, DrawableBottom等属性为TextView设置分别处于左右上下的图标,如下:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableBottom="@drawable/ic_delete" android:drawableLeft="@drawable/ic_delete" android:drawableRight="@drawable/ic_delete" android:drawableTop="@drawable/ic_delete" />
所以在我们的初始化中,我们可以自己先定义一个默认的图标,也可以从xml布局中获取。
当在xml布局中设置了上面对应的属性之后,函数setCompoundDrawables就会被调用,我们可在里面处理重新设置我们的mDrawableRight。
@Override public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) { if (right != null) { mDrawableRight = right; } super.setCompoundDrawables(left, top, mDrawableRight, bottom); }
2)必须重载onTouchEvent方法。
这是因为在TextView中设置四边的图标时,并没有提供其对应的点击事件,所以这就需要我们自己去拦截用户的点击事件,判断用户的点击区域,人工的去做对应的处理,如下:
public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP && mDrawableRight != null) { mBounds = mDrawableRight.getBounds(); final int x = (int) event.getX(); final int y = (int) event.getY(); if (x >= (this.getWidth() - mBounds.width()) && x <= (this.getWidth() - this.getPaddingRight()) && y >= this.getPaddingTop() && y <= (this.getHeight() - this.getPaddingBottom())) { clear(); event.setAction(MotionEvent.ACTION_CANCEL); } } return super.onTouchEvent(event); }
逻辑很简单,首先要获取图标的矩形区域,同时获取用户点击的点,只要此点落在此矩形区域内,我们就可以认为用户点击了这个按钮,进行我们自己的逻辑处理,然后将此事件的Action设置为Cancel,再利用系统onTouchEvent去处理这个Cancel事件。
代码中的clear方法就是我们自己去处理的逻辑,这个时候,我们就要考虑了,只是单纯做一些操作就可以,还是需要跟外部进行交互呢?
3)定义一个接口,用来由外部实现,可在图标点击事件时触发
public interface OnTextClearListener { public void onTextClear(ClearableTextView v); }... private void clear() { setTextClearable(""); if (mOnTextClearListener != null) { mOnTextClearListener.onTextClear(this); } super.setCompoundDrawables(null, null, null, null); }
所以,我们在clear方法里面,要判断有没有这样一个接口被实现并传给当前控件,如果存在,我们要调用其方法。
4)为了让文字不存在的时候,删除按钮不出现,我们可以自己定义一个setTextClearable方法,里面包装了TextView的setText方法,但是我们会根据参数内容来判断,要不要显示删除图标。
public void setTextClearable(CharSequence text) { setText(text); if (text == null || text.length() == 0) { super.setCompoundDrawables(null, null, null, null); } else { super.setCompoundDrawables(null, null, mDrawableRight, null); } }
5)当然,最后,在按钮不再存在上下文,即被销毁的时候,我们需要将对应的资源也清空,如下:
public void finalize() throws Throwable { mDrawableRight = null; mBounds = null; super.finalize(); }
到这里,整个的实现就讲解完了,虽然很简单,但是还是有学习的地方的,比如接口定义,很多方法的交互,我们可以通过消息传递,也可以通过回调函数来实现,具体就得考虑工作场景了。
好,接下来,就是在外面放置这样一个控件,来看看效果了。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.clearabletextviewdemo.MainActivity$PlaceholderFragment" > <com.example.clearabletextviewdemo.ClearableTextView android:id="@+id/ctvTest" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /></RelativeLayout>
MainActivity中的代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View rootView = inflater.inflate(R.layout.fragment_main, container,false);mCtvTest = (ClearableTextView) rootView.findViewById(R.id.ctvTest);mCtvTest.setTextClearable("Hello World");mCtvTest.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mCtvTest.setTextClearable("Hello World!");}});mCtvTest.setOnTextClearListener(new OnTextClearListener() {@Overridepublic void onTextClear(ClearableTextView v) {Toast.makeText(getActivity(), "On Text Cleared ", Toast.LENGTH_SHORT).show();}});return rootView;}}
最后,当然就是效果图了,如下:
结束!
- Android学习小Demo(22)带删除按钮的TextView
- Android 带删除图标的EditText清除功能小Demo
- Android学习--Android带删除按钮的ListView
- android带删除按钮的编辑框
- [Android]带删除按钮的EditText
- Android 带删除按钮的EdiText
- 一个带按钮的自定义Android通知栏DEMO
- (一)学习Android自带的demo项目
- 带删除按钮的ListView
- 带删除按钮的EditText
- 带删除按钮的EditText
- 带删除按钮的EditText
- 带删除按钮的EditText
- 带删除按钮的ListView
- 带删除按钮的 EditText
- android自定义控件(组合控件)--带删除按钮的EditText
- Android自定义右边带删除按钮的EditText
- Android输入框带删除按钮的自定义View
- javascript修改CSS
- java图形界面整理(未完成版)
- 将JDBC中的结果集转换为 model
- 提供一个win7可用的sourceInsight地址
- BZOJ 1189 HNOI2007 紧急疏散evacuate 二分答案+最大流
- Android学习小Demo(22)带删除按钮的TextView
- 第14周项目2(2)-带姓名的成绩单
- 对BaseAdapter中ViewHolder编写简化
- c#实现优先级队列
- php程序代码
- 第14周项目2(3)-带姓名的成绩单
- Codeforces Beta Round #4 (Div. 2 Only) B. Before an Exam
- 第十四周项目三(2):多科成绩单
- 第13周oj平台题目汇总