View绘制流程(五) - view状态

1. 视图状态


1>:enable:是否可用,setEnable(),true可用,false不可用,区别在于不可用的view不能响应 onTouch;
2>:focused:是否获取焦点,如EditText,focuseable && focuseable in touch mode 成立,可以获取焦点;
3>:selected:是否选中,setSelected(),true选中,false未选中;
4>:pressed:是否按下,setPressed(),true按下,false未按下;

2. 源码分析


对于pressed:手指按下,pressed=true,
view.drawableStateChanged__getDrawableState__onCreateDrawableState__
drawable.setState__onStateChange
StateListDrawable.onStateChange__selectDrawable

手指按下后,pressed=true,会调用 view.drawableStateChanged

   protected void drawableStateChanged() {
        // 获取当前 view 状态的 int[] 数组
        final int[] state = getDrawableState();
        boolean changed = false;

        // 把 mBackground 赋值给 Drawable ,mBackground 就是自己在drawable下边创建的 selector文件
        final Drawable bg = mBackground;
        if (bg != null && bg.isStateful()) {
            // 获取当前 view 的状态的 int[] 数组后,调用 setState() 更新状态
            changed |= bg.setState(state);
        }
    }


    public final int[] getDrawableState() {
        // 首先判断当前view状态 是否发生变化,如果没有改变,就直接返回当前view状态
        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
            return mDrawableState;
        } else {
            // 如果当前view状态改变了,调用 onCreateDrawableState() 获取最新状态,
            // 所有状态会以 int[] 数组返回
            mDrawableState = onCreateDrawableState(0);
            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
            return mDrawableState;
        }
    }


    public boolean setState(@NonNull final int[] stateSet) {
        // 用 Arrays.equals()判断 view状态的int[] 数组是否发生变化,如果变化就调用 onStateChange,
        // 如果没有变化,就返回 false , Drawable 中的 onStateChange 只返回false,没有任何逻辑,
        // 因为 mBackground 是通过 selector创建的,而通过 selector创建的 drawable对象 是
        // StateListDrawable实例对象,这里的 onStateChange() 就是 StateListDrawable 的 onStateChange
        if (!Arrays.equals(mStateSet, stateSet)) {
            mStateSet = stateSet;
            return onStateChange(stateSet);
        }
        return false;
    }


    @Override
    protected boolean onStateChange(int[] stateSet) {
        // indexOfStateSet:获取当前 view对应的 Drawable 下标
        int idx = mStateListState.indexOfStateSet(stateSet);
        // selectDrawable:把下标传入,此方法 就会把当前 view 背景设置为 当前状态对应的图片
        return selectDrawable(idx) || changed;
    }

分析上边源码:
1>:一个view 手指按下,pressed=true,会调用 view.drawableStateChanged,在此方法中:

  • 首先判断当前view状态,如果没有变化,直接返回当前view状态;如果变了,获取当前 view 状态的 int[] 数组;
  • 然后 把 mBackground赋值给 Drawable对象,然后调用 setState();
    2>:在 setState 中,判断 view状态的int[] 数组是否变化,如果变化,调用 onStateChange,如果没有变,返回 false;
    3>:Drawable 中的 onStateChange 只返回 false,没有任何逻辑,因为 mBackground 是通过 selector 创建的,而通过 selector创建的 drawable对象 是 StateListDrawable 实例,所以 Drawable中的 onStateChange其实就是 调用 StateListDrawable中的 onStateChange;
    4>:在 onStateChange中: indexOfStateSet() 获取当前 view 对应的 Drawable 下标, selectDrawable 把当前 view 背景设置为 当前状态对应的图片;

你可能感兴趣的:(View绘制流程(五) - view状态)