您的位置:首页 > 移动开发 > Android开发

Android视图状态及重绘流程

2016-06-18 22:41 417 查看
当手指按在视图上的时候,视图的状态就已经发生了变化,此时视图的pressed状态是true.每当视图状态有发生翻遍的时候,就会回调View的drawableStateChanged()方法。

protected void drawableStateChanged() {
Drawable d = mBGDrawable;
if (d != null && d.isStateful()) {
d.setState(getDrawableState());
}
}


mBGDrawable会在setBackgoundDrawable()方法中会将传入的 Drawable对象赋值给mBGDrawable。本地布局文件通过android:background属性指定的selector文件,效果等同于调用setBackgroundResourse()方法.

public void setBackgroundResource(int resid) {
if (resid != 0 && resid == mBackgroundResource) {
return;
}
Drawable d= null;
if (resid != 0) {
d = mResources.getDrawable(resid);
}
setBackgroundDrawable(d);
mBackgroundResource = resid;
}


接下来drawableStateChanged()方法会调用getDrawableState()方法来获取视图状态

在这里首先会判断当前视图的状态是否发生了改变,如果没有改变就直接返回当前的视图状态,如果发生了改变就调用onCreateDrawableState()方法来获取最新的视图状态。视图的所有状态会以一个整型数组的形式返回。

public final int[] getDrawableState() {
if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
return mDrawableState;
} else {
mDrawableState = onCreateDrawableState(0);
mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
return mDrawableState;
}
}


这里会调用Arrays.equals()方法来判断视图状态的数组是否发生了变化,如果发生了变化则调用onStateChange()方法,否则就直接返回false。但你会发现,Drawable的onStateChange()方法中其实就只是简单返回了一个false

public boolean setState(final int[] stateSet) {
if (!Arrays.equals(mStateSet, stateSet)) {
mStateSet = stateSet;
return onStateChange(stateSet);
}
return false;
}


在这里会判断当前视图的状态是否发生了改变,如果没有改变就直接返回当前的视图状态,如果发生了改变就调用onCreateDrawableState()方法来获取最新的视图状态。

@Override
protected boolean onStateChange(int[] stateSet) {
int idx = mStateListState.indexOfStateSet(stateSet);
if (DEBUG) android.util.Log.i(TAG, "onStateChange " + this + " states "
+ Arrays.toString(stateSet) + " found " + idx);
if (idx < 0) {
idx = mStateListState.indexOfStateSet(StateSet.WILD_CARD);
}
if (selectDrawable(idx)) {
return true;
}
return super.onStateChange(stateSet);
}


View的视图重绘

ViewRoot是继承字Handler的,调用sendEmptyMessage()方法出的消息,还在ViewRoot的handleMessage()方法中接收到。

public void handleMessage(Message msg) {
switch (msg.what) {
case DO_TRAVERSAL:
if (mProfile) {
Debug.startMethodTracing("ViewRoot");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
break;
......
}


调用视图的invalidate()方法后确实会走到performTraversals()方法中,然后重新执行绘制流程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: