開始
在開發(fā)中有兩種是我們比較常做的是適配和兼容.
適配一般是解決分辨率的問題,多發(fā)生在 xml 文件中.
兼容是指解決的是系統(tǒng)版本不同導致的結果不一致或者不工作的問題.
今天講一個 xml兼容上面的問題, 我們都知道一份 xml 會在不同的分辨率下展示的樣式可能有差,但是一份 xml 會不會在相同手機不同系統(tǒng)版本展示不同呢?
我們來看一個例子.下面的截圖為一開始的布局xml.兩者使用相同的布局xml,展示卻有所不同.
4.0 上的效果
5.0 上的效果
View 層級邏輯
5.0 以前 靠編寫時候View 的順序. 最先寫的 View 的層級是在最下面.
5.0 以后 引入一個Z 軸的概念.Z 軸越高層級越高,相同 Z軸,再比較編寫時候的順序,而 Button 天生高個.
分析
ViewGroup 的繪制是由dispatchDraw(Canvas canvas)
觸發(fā)的.
@Override
protected void dispatchDraw(Canvas canvas) {
...
List = usingRenderNodeProperties
? null : buildOrderedChildList();
...
}
在dispatchDraw(Canvas canvas)
中調用了buildOrderedChildList
對 childView 進行重新排序.
/**
* Populates (and returns) mPreSortedChildren with a pre-ordered list of the View's children,
* sorted first by Z, then by child drawing order (if applicable). This list must be cleared
* after use to avoid leaking child Views.
*
* Uses a stable, insertion sort which is commonly O(n) for ViewGroups with very few elevated
* children.
*/
ArrayList<View> buildOrderedChildList() {
final int count = mChildrenCount;
if (count <= 1 || !hasChildWithZ()) return null;
if (mPreSortedChildren == null) {
mPreSortedChildren = new ArrayList<View>(count);
} else {
mPreSortedChildren.ensureCapacity(count);
}
final boolean useCustomOrder = isChildrenDrawingOrderEnabled();
for (int i = 0; i < mChildrenCount; i++) {
// add next child (in child order) to end of list
int childIndex = useCustomOrder ? getChildDrawingOrder(mChildrenCount, i) : i;
View nextChild = mChildren[childIndex];
float currentZ = nextChild.getZ();
// insert ahead of any Views with greater Z
int insertIndex = i;
while (insertIndex > 0 && mPreSortedChildren.get(insertIndex - 1).getZ() > currentZ) {
insertIndex--;
}
mPreSortedChildren.add(insertIndex, nextChild);
}
return mPreSortedChildren;
}
修正方法
我們可以通過修改 Button為 TextView 來保證布局在不同系統(tǒng)版本下的一致性.因為 TextView 的 Z軸跟 LinearLayout 是一樣的.