3

lots of button will be added in my viewgroup, so I need my viewgroup'height is wrap_content, but whatever I set height in code or xml, it doesn't work, the viewgroup'height always match_parent, so what's wrong with it? how can I set the height is wrap_content?

CustomViewGroup:

public class CustomViewGroup extends ViewGroup {

private final static String TAG = "CustomViewGroup";

private final static int VIEW_MARGIN = 2;

public CustomViewGroup(Context context) {
    super(context);
}

public CustomViewGroup(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    Log.d(TAG, "widthMeasureSpec = " + widthMeasureSpec
            + " heightMeasureSpec" + heightMeasureSpec);

    for (int index = 0; index < getChildCount(); index++) {
        final View child = getChildAt(index);
        // measure
        child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
    }

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
    Log.d(TAG, "changed = " + arg0 + " left = " + arg1 + " top = " + arg2
            + " right = " + arg3 + " botom = " + arg4);
    final int count = getChildCount();

    int row = 0;// which row lay you view relative to parent
    int lengthX = arg1; // right position of child relative to parent
    int lengthY = arg2; // bottom position of child relative to parent
    for (int i = 0; i < count; i++) {

        final View child = this.getChildAt(i);
        int width = child.getMeasuredWidth();
        int height = child.getMeasuredHeight();

        Log.i(TAG, "width = " + width + " height = " + height);
        lengthX += width + VIEW_MARGIN;
        lengthY = row * (height + VIEW_MARGIN) + VIEW_MARGIN + height
                + arg2;
        Log.i(TAG, "lengthX = " + lengthX + " lengthY = " + lengthY + " row = " + row);
        // if it can't drawing on a same line , skip to next line
        if (lengthX > arg3) {
            lengthX = width + VIEW_MARGIN + arg1;
            row++;
            lengthY = row * (height + VIEW_MARGIN) + VIEW_MARGIN + height
                    + arg2;

        }

        child.layout(lengthX - width, lengthY - height, lengthX, lengthY);
    }

}

}

public class ViewGroupTest extends Activity {

CustomViewGroup vg;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_view_group_test);
    LinearLayout l = (LinearLayout) findViewById(R.id.lllll);
    Button b1 = new Button(this);
    b1.setId(1);
    b1.setText("hello");
    vg = new CustomViewGroup(this);
    LinearLayout.LayoutParams pr = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,200);
    vg.setBackgroundColor(Color.BLUE);
    vg.setLayoutParams(pr);
    vg.addView(b1);
    Button b2 = new Button(this);
    b2.setId(2);
    b2.setText("world");
    vg.addView(b2);

    Button b3 = new Button(this);
    b3.setId(3);
    b3.setText("world 33333");
    vg.addView(b3);

    Button b4 = new Button(this);
    b4.setId(4);
    b4.setText("world44444444");
    vg.addView(b4);
    b3.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            Button b = new Button(ViewGroupTest.this);
            b.setText("world");
            vg.addView(b);
        }
    });

}

}

4

2 回答 2

0

I made it, but I still don't know why the height can't be wrap_content; I directly set the viewgroup's real height, and then use callback function to change the height; in the CustomViewGroup add the Interface

public void setCallBack(CallBack c) {
    mCallBack = c;
}

public interface CallBack {
    public void callBack(int height);
}

then in onlayout

if (lengthX > arg3) {
            Log.i("CustomViewGroup", "yes wrap");
            lengthX = width + VIEW_MARGIN + arg1;
            row++;
            lengthY = row * (height + VIEW_MARGIN) + VIEW_MARGIN + height
                    + arg2;
            if (mCallBack != null) {
                mCallBack.callBack(lengthY);
            }
        }

in the Activity implement the callback

private CallBack mCallBack = new CallBack() {

    @Override
    public void callBack(int height) {
        Log.i("CustomViewGroup", "callback");

        LayoutParams lp = (LayoutParams) vg.getLayoutParams();
        Log.i("CustomViewGroup", "vg height = " + lp.height + " height = " + height);
        lp.height = height;
        Log.i("CustomViewGroup", "vg height = " + lp.height + " height = " + height);
        vg.setLayoutParams(lp);
        vg.post(new Runnable() { //must be use post, if you dircetly vg.requestLayout, can't work, who can explain, appreciated!
            public void run() {
                vg.requestLayout();
            }
        });
        Log.i("CustomViewGroup", "vg height = " + vg.getHeight() + " height = " + height);

    }
};
于 2012-12-01T03:05:06.383 回答
0

I have solved this problem by copying ViewPager code from the support library and modifying it a bit.

What I did is this:

  1. Copied viewpager's code into my class CustomViewPager

  2. Extended CustomViewPager and override onMeasure method

Inside this method i've measured the height of first child and set height of ViewPager to be the same as from first child

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mInLayout = true;
        populate();
        mInLayout = false;

        int firstChildHeight = 0;
        int firstChildWidth = 0;

        int size = getChildCount();

        for (int i = 0; i < size; ++i) {
            final View child = getChildAt(i);

            if (child.getVisibility() != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);

                if (i == 0) {
                    firstChildHeight = child.getMeasuredHeight();
                    firstChildWidth = child.getMeasuredWidth();
                }

                child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
            }
        }

        setMeasuredDimension(firstChildWidth, firstChildHeight);
    }
于 2013-01-31T20:33:08.237 回答