7

I am writing up a custom layout (which extends FrameLayout) that can be zoomed in. All its children are also custom views which would actually get the scale factor from their parent via a getter method and scale accordingly by setting the scaled dimensions like

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    float scaleFactor = ((CustomLayout) getParent()).getCurrentScale();
    setMeasuredDimension((int) (getMeasuredWidth() * scaleFactor), (int) (getMeasuredHeight() * scaleFactor));
}

I am using a ScaleGestureDetector to detect the "pinch to zoom" gesture and change the layout's scaleFactor. Then I force a layout on the custom layout by calling requestLayout. Unfortunately this doesn't seem to have any effect on its children. The children's onMeasure & onLayout are never called even though the parent goes through its measure & layout cycle. But, if I directly call requestLayout on one of the children, just that child gets scaled according to the scale factor set in the parent!!

It seems that unless requestLayout is exclusively called on a view, it doesn't actually measure itself again and instead uses some kind of cache. This is evident from the source code for view which says

if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
        // Only trigger request-during-layout logic if this is the view requesting it,
        // not the views in its parent hierarchy
        ViewRootImpl viewRoot = getViewRootImpl();
        if (viewRoot != null && viewRoot.isInLayout()) {
            if (!viewRoot.requestLayoutDuringLayout(this)) {
                return;
            }
        }
        mAttachInfo.mViewRequestingLayout = this;
    }

How do I force the children also to go measure themselves again on calling requestLayout on their parent?

user3846994
  • 113
  • 1
  • 4

1 Answers1

7

This will force relayout the view's children (given that view's own width and height does not need to change)

private static void relayoutChildren(View view) {
    view.measure(
        View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY),
        View.MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(), View.MeasureSpec.EXACTLY));
    view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
}
BoD
  • 10,838
  • 6
  • 63
  • 59
Helin Wang
  • 4,002
  • 1
  • 30
  • 34