自定义ViewGroup的知识点总结-持续更新
1、child.getMeasuredWidth()中会包含child的padding值
child的margin的值需要自行适配。
2、在onMeasure方法中:
需要先对child进行measure,然后才能获取到measuredWidth和measureHeight。
常用的测量方法有两个:
①ViewGroup#measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec))
但是measureChildWithMargins))有个缺陷,它内部的MarginLayoutParams是类型强转而来的,没有添加非空判断和类型判断,如果我们是自定义ViewGroup,这里会就有可能导致空指针和类型转换异常,为了解决这个问题,我自定义了一个方法,具体请看下面的measureChildWithMarginsAndUsedSpace
方法。
3、测量child时,考虑到measureChildWithMargins的缺陷,这里自行实现了一个方法:measureChildWithMarginsAndUsedSpace
protected void measureChildWithMarginsAndUsedSpace(View child,
int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
// 兜底,不会发生
if (child.getLayoutParams() == null) {
return;
}
final LayoutParams lp = child.getLayoutParams();
int paddingH = getPaddingLeft() + getPaddingRight() + widthUsed;
int paddingV = getPaddingTop() + getPaddingBottom() + heightUsed;
if (child.getLayoutParams() instanceof MarginLayoutParams) {
final MarginLayoutParams mlp = (MarginLayoutParams) child.getLayoutParams();
paddingH += mlp.leftMargin + mlp.rightMargin;
paddingV += mlp.topMargin + mlp.bottomMargin;
}
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, paddingH, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, paddingV, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
4、自定义ViewGroup时,必须考虑自身的padding,以及child的padding、margin等。
如果child也是自定义ViewGroup,那么也需要考虑因素。
5、如何方便的支持child的margin数据?重写ViewGroup#generateLayoutParams方法即可
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
ViewGroup只提供了ViewGroup.LayoutParams,MarginLayoutParams是各个ViewGroup自行继承实现的。
我们的ViewGroup要支持MarginLayoutParams最好的方式,就是重写ViewGroup#generateLayoutParams方法。
6、对于一些需要限制宽度的操作,可以在onMeasure中操作。
先测量出实际宽度,如果超出了预期,再根据其最大长度进行二次测量即可。
常见的FlowLayout等自定义布局,都可以这么实现。
未完待续,敬请期待。