0

I wrote the following ViewGroup

public class myViewGroup extends ViewGroup{

List<View> qResult;
List<Point> qLoc;
ImageView qImage;


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

public QueryViewLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public QueryViewLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    qResult = new LinkedList<View>();
    qLoc = new LinkedList<Point>();
    qImage = null;
}

public void addMainView(ImageBorderView view){
    qImage = view;
    super.removeAllViews();
    super.addView(view);
}

public void addResultView(View result, Point loc){
    super.addView(result);
    qResult.add(result);
    qLoc.add(loc);
}

/**
 * Any layout manager that doesn't scroll will want this.
 */

@Override
public boolean shouldDelayChildPressedState() {
    return false;
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int count = getChildCount();

    // Measurement will ultimately be computing these values.
    int maxHeight = 0;
    int maxWidth = 0;
    int childState = 0;



    // Only main view affects the layouts measure

    if (qImage != null) {
        if (qImage.getVisibility() != GONE) {
            // Measure the child.
            qImage.measure(widthMeasureSpec, heightMeasureSpec);
            maxWidth = qImage.getMeasuredWidth();
            maxHeight = qImage.getMeasuredHeight();
            childState = qImage.getMeasuredState();
        }
    }

    for (View child:qResult){
        if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED)
            child.measure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST),
                    MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST));
    }

    maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
    maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());

    // Report our final dimensions.
    setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
            resolveSizeAndState(maxHeight, heightMeasureSpec,
                    childState << MEASURED_HEIGHT_STATE_SHIFT));


}


@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    final int count = getChildCount();

    int parentLeft = left + getPaddingLeft();
    int parentRight = right - getPaddingRight();

    final int parentTop = top + getPaddingTop();
    final int parentBottom = bottom - getPaddingBottom();

    if (qImage == null) return;

    qImage.layout(parentLeft, parentTop, parentRight, parentBottom);


    Iterator<Point> loc = qLoc.iterator();
    for (View child:qResult) {
        Point p = loc.next();
        if (child.getVisibility() != GONE) {

            int width = child.getMeasuredWidth();
            int height = child.getMeasuredHeight();
            Point locOnView = qImage.projectOnView(p);

            width = (width < (int) Math.max(parentRight - (int) locOnView.x, locOnView.x - parentLeft)) ?
            width : (parentLeft + parentRight)/2;
            height = (height < (int) Math.max(parentBottom - (int) locOnView.y, locOnView.y - parentTop)) ?
            height : (parentBottom + parentTop)/2;

            int x = (width < (parentRight - (int) locOnView.x)) ? (int) locOnView.x : (parentRight - width);
            int y = (height < parentBottom - (int) locOnView.y) ? (int) locOnView.y : (parentBottom - height);


            // Place the child.
            child.layout(x, y, x + width, y + height);
        }
    }

}

}

It is supposed to show some arbitrary view on top of an image, given a location for that view, when I use a GridView as the arbitrary view, even though I have defined a certain width for the GridView it is forced to have a width as large as the frame. In the measure phase I changed the mode to

MeasureSpec.AT_MOST

for both width and height of the overlay view, but this does not seem to work, can someone please help.

here is the xml where I, inflate the GridView from

<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/result_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:columnWidth="@dimen/result_view_column_width"
android:numColumns="2"
android:verticalSpacing="2dp"
android:horizontalSpacing="2dp"
android:stretchMode="none"
android:gravity="center"
android:layout_margin = "2dp"
android:background="@drawable/solid_with_shadow" />
stopBugs
  • 351
  • 3
  • 10

1 Answers1

0

After a lot of trial and error, replacing

child.measure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST),
                MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST));

with

measureChild(child, MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST),
                MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST));

worked for me, I am not sure why, but a wild guess would be calling measure on a child does not read all the xml props, but measureChild(child, ...) does.

stopBugs
  • 351
  • 3
  • 10