开始
在开发中有两种是我们比较常做的是适配和兼容.
适配一般是解决分辨率的问题,多发生在 xml 文件中.
兼容是指解决的是系统版本不同导致的结果不一致或者不工作的问题.
今天讲一个 xml兼容上面的问题, 我们都知道一份 xml 会在不同的分辨率下展示的样式可能有差,但是一份 xml 会不会在相同手机不同系统版本展示不同呢?
我们来看一个例子.下面的截图为一开始的布局xml.两者使用相同的布局xml,展示却有所不同.
4.0 上的效果
5.0 上的效果
View 层级逻辑
5.0 以前 靠编写时候View 的顺序. 最先写的 View 的层级是在最下面.
5.0 以后 引入一个Z 轴的概念.Z 轴越高层级越高,相同 Z轴,再比较编写时候的顺序,而 Button 天生高个.
分析
ViewGroup 的绘制是由dispatchDraw(Canvas canvas)
触发的.
@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 来保证布局在不同系统版本下的一致性.因为 TextView 的 Z轴跟 LinearLayout 是一样的.