天天记录 - Android refreshDrawableState源码及流程简单分析
来源:互联网 发布:公司如何开淘宝店 编辑:程序博客网 时间:2024/05/16 05:43
有多种因素会导致触发refreshDrawableState,当前只考虑其中一种setPressed即设置视图是否处于被按下状态。其他会触发此方法的有focusChanged等。
原理是定义不同状态的图片,系统进行状态监听例如在onTouchEvent中判断当前在什么状态,再根据之前提供的图片进行设置并重绘显示效果。
以下是根据代码一个具体的流程,其中解释的并不是太多,当前也都比较简单都是直接的方法调用顺序。
先来看看View.setPressed源码
public void setPressed(boolean pressed) { if (pressed) { mPrivateFlags |= PRESSED ; } else { mPrivateFlags &= ~PRESSED; } refreshDrawableState(); dispatchSetPressed(pressed); }
其中调用了View.refreshDrawableState,下面查看一下相关代码View.refreshDrawableState与 View.drawableStateChanged:
一
public void refreshDrawableState() {// 用于判断是否发生状态变化 mPrivateFlags |= DRAWABLE_STATE_DIRTY ; // 状态改变后进行绘制 drawableStateChanged(); ViewParent parent = mParent; if (parent != null) { // 父视图如果存在的话执行 parent.childDrawableStateChanged( this); } } // 仅在ViewGroup覆写 protected void drawableStateChanged() { // 当前视图的背景图 Drawable d = mBGDrawable; if (d != null && d.isStateful()) { // 为当前drawable设置当前drawable状态索引 d.setState(getDrawableState()); } } // 获取视图的当前状态 public final int[] getDrawableState() { if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) { return mDrawableState; } else { // 将视图状态转换为一个int[]数组 // DrawableState可以识别此数组 mDrawableState = onCreateDrawableState(0); mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY; return mDrawableState; } }
二 以上在View中调用Drawable相应方法Drawable.setState 和 Drawable.onStateChange
public boolean setState(final int[] stateSet) { if (!Arrays.equals( mStateSet, stateSet)) { mStateSet = stateSet; return onStateChange(stateSet); } return false ; } protected boolean onStateChange (int[] state) { return false; }
三 步骤二中的调用的方法是一个回调,其具体实现在其子类中,此处仅罗列针对其子类StateListDrawable的具体实现代码StateListDrawable.onStateChange和 StateListDrawable.selectDrawable
@Override protected boolean onStateChange( int[] stateSet) { int idx = mStateListState.indexOfStateSet(stateSet); if (idx < 0) { idx = mStateListState.indexOfStateSet(StateSet.WILD_CARD); } if (selectDrawable(idx)) { return true ; } return super .onStateChange(stateSet); } public boolean selectDrawable( int idx) { ...... // 触发绘制请求 invalidateSelf(); return true ; }
四 StateListDrawable以上方法流程中调用的方法invalidateSelf,由其父类中进行具体实现Drawable.Callback.invalidateSelfe和Drawable.Callback.invalidateDrawable
public void invalidateSelf(){// mCallback是在何处赋赋值? if (mCallback != null) { mCallback.invalidateDrawable(this); }}// 全局搜索发现此处对其值进行赋值,那何处引用了此方法呢?public final void setCallback(Callback cb) { mCallback = new WeakReference<Callback>(cb);}public void invalidateDrawable (Drawable who);
五 以上步骤需要调用其setCallback传入cb才行,具体什么地方传入的呢?具体是在View.setBackgroundDrawable中
@Deprecated public void setBackgroundDrawable(Drawable background) { ... // 此处设置Callback,当前View就是其Callback background.setCallback(this); ... mBGDrawable = background; }
六 从步骤五可以获知drawable中的Callback就是当前View自身,View实现Drawable.Callback
public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,AccessibilityEventSource { public void invalidateDrawable(Drawable drawable) { if (verifyDrawable(drawable)) { final Rect dirty = drawable.getBounds(); final int scrollX = mScrollX; final int scrollY = mScrollY; // 看到了熟悉的invalidate,之后就是走正常的invalidate流程 invalidate(dirty. left + scrollX, dirty.top + scrollY, dirty. right + scrollX, dirty.bottom + scrollY); } } }
第六步中进行具体的请求刷新
参考资料:
《Android 内核剖析》 柯元丹 著 13.6.3 refreshDrawableList
Android中View(视图)绘制不同状态背景图片原理深入分析以及StateListDrawable使用详解
代码实现ColorStateList及StateListDrawable
- 天天记录 - Android refreshDrawableState源码及流程简单分析
- 天天记录 - Android requestLayout源码简单分析
- 天天记录 - Android 使用dmeo和源码分析invalidate流程
- 天天记录 - Android invalidate流程分析-图文
- 天天记录 - Android ListView onTouchEvent源码分析
- 天天记录 - Android addView源码分析
- 天天记录 - Android setVisibility参数VISIBLE, GONE, INVISIBLE与源码简单分析
- 天天记录 - Android Activity 启动流程简单整理
- 天天记录 - Android invalidate流程方法调用堆栈分析
- 天天记录 - Android ListView itemType使用Holder原理简单分析
- Android View系统源码分析(七)—— View.refreshDrawableState()
- android Retrofit简单使用及源码分析
- 天天记录 - 编译Android 4.1.2源码遇到问题解决
- 天天记录 - Eclipse导入Android 4.1.2源码工程
- 天天记录 - Windows 使用GIT下载Android Framework源码
- 天天记录 - Android创建应用窗口分析1
- 天天记录 - Android创建应用窗口分析2
- 天天记录 - Android创建应用窗口分析3
- 我的单片机学习生涯开始了
- Remote Desktop Connection
- 《2013年工作半年记》
- vc++命名规范
- ffmpeg 一些好资源
- 天天记录 - Android refreshDrawableState源码及流程简单分析
- Hoj 1604 Cable Master
- Linux命令-screen
- 如何确保项目流程被贯彻和执行
- (一)洞悉linux下的Netfilter&iptables:什么是Netfilter?
- OpenCV之像素访问优化
- Spring.jar包详解
- java获取中文拼音首字母工具类
- socket地址解析相关的几个函数inet_addr,inet_ntoa,gethostname,gethostbyname