维护维护在维护,改版改版复改版!
最近项目在改版,UI给了如下的一张新界面:
首先拿到界面时,美工说为了防止界面显得太长,当图片List小于4个的时候则就竖直排列,如果大于或等于5个的时候的第一到第五的子view会左右排列。思考了一会感觉也不是非常的复杂,于是就欣然动笔画起来伪代码:
这样大概画好之后,就有了一点的思绪,首先我们先无脑的自定义一个viewgroup再说:
public class HomeMealLayout extends ViewGroup {
private int childWidth;
private int childHeight;
private int childCount;
private Context context;
public HomeMealLayout(Context context) {
this(context,null);
}
public HomeMealLayout(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public HomeMealLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context=context;
}
然后我们要开始对子view的高度和viewgroup进行测量:
首先我们布局的图片大小和比例都是固定的,所以我们只需要宽度铺满,高度自适应的Imageview即可,然后我们的第一到第五的子View的高度和宽度是正常布局的1/2,所以我们首先确定正常布局下的childWidth,然后除以2则是1-5的子view的宽高。接下来我们看代码:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!isInEditMode())
mHelper.adjustChildren();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
childCount = getChildCount();
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if(childCount ==0){
return;
}else if(childCount <5){
for (int i=0;i=5){
for (int i=0;i=1 && i<=4){
measureChild(child,widthMeasureSpec,heightMeasureSpec);
childWidth = child.getMeasuredWidth();
childHeight = child.getMeasuredHeight();
MealLayoutParams lp =(MealLayoutParams) child.getLayoutParams();
lp.width=childWidth/2;
lp.height=childHeight/2;
child.setLayoutParams(lp);
}else {
measureChild(child,widthMeasureSpec,heightMeasureSpec);
childWidth = child.getMeasuredWidth();
childHeight = child.getMeasuredHeight();
}
}
}
if(childCount<5){
setMeasuredDimension(resolveSize(childWidth,widthMeasureSpec),resolveSize(childHeight*childCount,heightMeasureSpec));
}else {
setMeasuredDimension(resolveSize(childWidth,widthMeasureSpec),resolveSize(childHeight*(childCount-3),heightMeasureSpec));
}
}
整体的逻辑还算比较清晰,MealLayoutParams 是继承的marginlayoutparams,这里大家只需要写marginlayoutparams即可,因为我们使用了marginlayoutparams 所以别忘了在viewgroup中加上这行代码:
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MealLayoutParams(getContext(),attrs);
}
这样我们子view和父控件的宽高都已经测量好了,接下来就到最重要的部分了,我们要开始在onLayout中摆放我们的子view了,其实onlayout的逻辑跟onmeasure的逻辑相似,只是onlayout要开始具体的进行摆放子View,我们直接上代码:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if(childCount<5){
for(int i=0;i=5){
for (int i=0;i=1 && i<5){
getChildAt(1).layout(0,space+childHeight,childWidth/2,childHeight/2+space+childHeight);
getChildAt(2).layout(childWidth/2+space,space+childHeight,childWidth,childHeight+space+childHeight/2);
getChildAt(3).layout(0,space*2+childHeight+childHeight/2,childWidth/2,childHeight+space*2+childHeight);
getChildAt(4).layout(childWidth/2+space,space*2+childHeight+childHeight/2,childWidth,childHeight+space*2+childHeight);
}else {
getChildAt(i).layout(0,space*(i-2)+childHeight*(i-3),childWidth,space*(i-1)+(i-2)*childHeight);
}
}
}
}
这里的代码应该是比较清晰的,当childCount小于5的时候,我们就依次的向下排列,当childCount>=5的时候我们就要做判断,因为中间的子View只有4个,所以我也并没有做特殊的判断,直接全部写了上去,也比较清晰,至此我们的viewgroup已经写的差不多了,可以通过for循环来进行addview了,但是这明显不符合我们的习惯,所以我们要对他进行再一次的封装,但是因为别人的代码写得更好,而且逻辑梳理也比我强,所以发一波传送门,未来的大神:http://blog.csdn.net/zxt0601/article/details/52494665 里面讲解了如何对自定义的viewgroup进行封装,大家可以前去膜拜!
至此,这篇博客就算写完了。写的不好的地方,希望大家多多指正!