Android自定义View之点击效果
来源:互联网 发布:主播过度劳累猝死知乎 编辑:程序博客网 时间:2024/05/06 00:53
最近在做新版本,各种UI效果都需要自定义,而自定义View点击效果问题一直困扰着我。各种找资料也没有找到自己想要的东西,可能是我关键字打的不对吧。最后在查看TextView的源码时解决了我的问题,由于源码功能太多,不易查询,特此提取记录。
UI效果
默认效果
点击效果
ClickEffectView代码
public class ClickEffectView extends View { private ColorStateList mTextColorList = ColorStateList.valueOf(Color.GRAY); private String mContextText; private Drawable mBgDrawable; private int mCurTextColor; private Paint mTextPaint; private Rect mRect; public ClickEffectView(Context context) { this(context,null); } public ClickEffectView(Context context, AttributeSet attrs) { this(context, attrs,0); } public ClickEffectView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); /*绑定StyleAble自定义属性,使ClickEffectView支持XML赋值属性值*/ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ClickEffectView); ColorStateList color = null; color = typedArray.getColorStateList(R.styleable.ClickEffectView_cev_TextColor); if (color != null) { setTextColor(color); } String text = typedArray.getString(R.styleable.ClickEffectView_cev_Text); setText(text); mBgDrawable = typedArray.getDrawable(R.styleable.ClickEffectView_cev_Background); typedArray.recycle(); mTextPaint = createPaint(); mTextPaint.setTextSize(30); mRect = new Rect(); } protected Paint createPaint() { Paint paint = new Paint(); paint.setAntiAlias(true); paint.setDither(true); paint.setFilterBitmap(true); paint.setXfermode(null); return paint; } @Override protected void drawableStateChanged() { super.drawableStateChanged(); updateState(); } @Override protected void onDraw(Canvas canvas) { int width = canvas.getWidth(); int height = canvas.getHeight(); if(mBgDrawable != null){ mBgDrawable.setBounds(0,0,width,height); mBgDrawable.draw(canvas); } //在绘制之前,重新设置颜色,以保证是根据getDrawableState()得到的值 mTextPaint.setColor(mCurTextColor); mRect.set(0 , 0, width, height); Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt() ; int baseline = (mRect. bottom + mRect.top - fontMetrics.bottom - fontMetrics.top ) / 2; // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX() mTextPaint.setTextAlign(Paint.Align. CENTER); canvas.drawText(TextUtils. isEmpty( mContextText ) ? "" : mContextText , mRect.centerX() , baseline, mTextPaint); } public void setTextColor(ColorStateList textColor) { this.mTextColorList = textColor; updateState(); } public void setText(String text) { if(TextUtils.isEmpty(text)){ this.mContextText = ""; } this.mContextText = text; } private void updateState() { boolean invalidate = false; //获取View当前状态 int[] states = getDrawableState(); //获取状态对应的颜色 int textColor = mTextColorList.getColorForState(states, 0); if(textColor != mCurTextColor){ mCurTextColor = textColor; invalidate = true; } if(mBgDrawable != null){ mBgDrawable.setState(states); invalidate = true; } if(invalidate){ invalidate(); } }}
自定义属性
/res/values/attrs.xml
<declare-styleable name="ClickEffectView"> <!--文字颜色--> <attr name="cev_TextColor" format="color"/> <!--文本内容--> <attr name="cev_Text" format="string"/> <!--背景--> <attr name="cev_Background" format="reference"/></declare-styleable>
思考
上面View是在按下时改变View的背景以及文字颜色来实现的,要想达到上面的效果,那么问题来了。
1.怎么侦听View的点击状态呢?
答:侦听View的点击状态可以实现View的drawableStateChanged()函数,当View的状态改变时都会调用这个函数来通知View。比如说:按下状态(pressed),聚焦状态(focused),选中状态(selected)。
2.这么多状态都会通知drawableStateChanged()函数,那怎么知道当前View是什么状态呢?
答:View通过 int[] getDrawableState() 函数来获取获取当前的状态。
3.那么我们要怎么去存储View的这些动态UI特征,又怎么通过一个int[]的View状态信息来读取这些特征?
答:Android已经为我们提供了方法了,像颜色的动态特征存储及读取可使用ColorStateList类,而背景的动态特征存储及读取则可使用Drawable类。
ColorStateList
存储,在/res/color目录下创建资源文件
<?xml version="1.0" encoding="utf-8"?><?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <!--按下后的绿色--> <item android:color="#00ff00" android:state_pressed="true"/> <!--默认的灰色--> <item android:color="#666666"/></selector>
读取:
//获取View当前状态int[] states = getDrawableState();//获取状态对应的颜色int textColor = mTextColorList.getColorForState(states, 0);
Drawable
存储,在/res/drawable目录下创建资源文件
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <!--按下的绿色矩形--> <item android:drawable="@drawable/shape_rectangle_bg_green_border_green_press" android:state_pressed="true" /> <!--默认的灰色矩形--> <item android:drawable="@drawable/shape_rectangle_bg_gray_border_gray_normal"/></selector>
读取:
//获取View当前状态int[] states = getDrawableState();//Drawable会根据当前状态来改变mBgDrawable.setState(states);
4.状态侦听及信息存储都已搞定了,那么View怎么去及时的更新View呢?
答:我们只要在drawableStateChanged()函数中通过getDrawableState(),去改变我们想要改变的属性,然后调用View的invalidate()函数,则会调用onDraw()去重绘View了,不过不要忘了在onDraw()函数中绘制时,将这些动态属性赋值,这样才能保证每次重绘的时候拿到的是根据getDrawableStae()获取的值。
5.怎么在XML文件中设置这些属性?
答:要想在XML中设置这些属性,则需要根据属性绑定styleable自定义属性。这里就不详细讲了。
源码地址
- Android自定义View之点击效果
- Android之自定义点击效果 .
- Android自定义View之仿去哪儿ImageView标签点击效果
- Android之Button自定义点击效果
- Android之Button自定义点击效果
- Android之Button自定义点击效果
- Android之Button自定义点击效果
- Android之Button自定义点击效果
- Android之Button自定义点击效果
- Android自定义View之刮刮卡效果
- Android之自定义view-加载效果
- Android自定义View之奖券效果
- android 自定义view之侧滑效果
- Android 自定义View之加载进度条效果
- Android 自定义View之放大镜效果
- Android自定义View之Flipboard效果
- android自定义View之自定义侧滑删除效果
- 自定义View之自定义按键圆角边框背景添加点击效果
- Linux下vi命令大全
- java学习笔记之Spring依赖注入和控制反转
- c++ 读入字符的函数简介
- Servlet是如何实现MVC的
- 如何修改android studio背景色(包括project view的背景色)保护眼睛人人有责
- Android自定义View之点击效果
- SpringMVC的各种参数绑定方式
- 字对齐与半字对齐
- 在项目里交叉使用Swift和OC
- 基础算法-冒泡排序
- Linux 网卡配置
- 练习2————1002
- c#中的快捷键
- Qt- “信号-槽”机制之连接类型 部分文档翻译