Android开发分享android自定义view程序员

android 自定义ViewGroup

2016-05-04  本文已影响197人  Trace_Li

上文讲述了自定义的几个基本步骤,这篇接着上文讲述一下如何自定义viewgroup 。

代码参见 * https://github.com/lijing01/AndroidDemo

ViewGroup 定义

is a special view that can contain other views (called children.) The view group is the base >class for layouts and views containers. This class also defines theViewGroup.LayoutParams
class which serves as the base class for layouts parameters.
Also see ViewGroup.LayoutParams
for layout attributes.

ViewGroup 作用

根据子view 的测量模式给出建议的宽高,决定子view 的位置,为什么是建议的宽高,因为子view 和viewGroup 的宽高都可以设置warp_content,这样需要计算出子view 的宽高才能获取到viewGroup的宽高。给其他view或viewGroup 给出 layoutparamas 的基类。

ViewGroup 自定义过程

我们通过实现一个horizonal viewGroup 来演示这些功能。这个custom viewGroup 有些类似与下面的LinearLayout
<code><LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"/></code>

<com.tracelijing.androiddemo.customview.CustomViewGroup
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/darkgoldenrod">
    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/colorPrimary"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"/>
    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/colorAccent"
        android:layout_marginLeft="10dp"/>
</com.tracelijing.androiddemo.customview.CustomViewGroup>

onmesure

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int desireWidth = 0, desireHeight = 0;
        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View childView = getChildAt(i);
            if (childView.getVisibility() != View.GONE) {

                MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();
                //将measureChild改为measureChildWithMargin
                measureChildWithMargins(childView, widthMeasureSpec, 0,
                        heightMeasureSpec, 0);
                //这里在计算宽度时加上margin
                desireWidth += childView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
                desireHeight = Math
                        .max(desireHeight, childView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
            }
        }
        desireWidth += getPaddingLeft() + getPaddingRight();
        desireHeight += getPaddingTop() + getPaddingBottom();

        // see if the size is big enough
        desireWidth = Math.max(desireWidth, getSuggestedMinimumWidth());
        desireHeight = Math.max(desireHeight, getSuggestedMinimumHeight());

        setMeasuredDimension(resolveSize(desireWidth, widthMeasureSpec),
                resolveSize(desireHeight, heightMeasureSpec));
    }

这里我们通过通过viewGroup 的测量模式,测量出子view 宽高,因为这里我们customVieewGroup 的宽高设置的是 warp_content, 并且是类似于水平方向的ViewGroup, 所以我们可以根据子view 的大小计算出viewGroup 的大小。

onlayout

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int parentLeft = getPaddingLeft();
    int parentTop = getPaddingTop();

    int left = parentLeft;
    int top = parentTop;

    int count = getChildCount();
    for (int i = 0; i < count; i++) {
        View view = getChildAt(i);
        if (view.getVisibility() != View.GONE) {
            MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
            left += lp.leftMargin;
            final int childWidth = view.getMeasuredWidth();
            final int childHeight = view.getMeasuredHeight();
            view.layout(left, top+lp.topMargin, left + childWidth, top + childHeight+lp.bottomMargin);
            left += childWidth + lp.rightMargin;
        }
    }
}

onlayout 的左右是对所有的子view 进行定位。代码很简单,我们循环遍历每个子view并把前一个view 的结束位置作为它的起始位置。参数为:

生成LayoutParams

public MarginLayoutParams generateLayoutParams(AttributeSet attrs)
    {
        return new MarginLayoutParams(getContext(), attrs);
    }

这里我们先使用ViewGroup 的marginLayoutParams,这样我们就可以使用如上面xml 中给子view 添加margin 的效果。

Paste_Image.png

运行效果如图,我们实现了带margin 效果的水平的类LinearLayout的效果。

自定义view 相关文章
android 自定义view

Reffer

上一篇 下一篇

猜你喜欢

热点阅读