Forced re-arrangement in a viewing group, including all its children

I am writing a custom layout (which extends FrameLayout ) that can be scaled up. All of his children are also regular representations, which actually get a scale factor from their parent using the getter method and scale accordingly, setting scaled sizes such as

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); float scaleFactor = ((CustomLayout) getParent()).getCurrentScale(); setMeasuredDimension((int) (getMeasuredWidth() * scaleFactor), (int) (getMeasuredHeight() * scaleFactor)); } 

I use ScaleGestureDetector to detect pinch to zoom gestures and scaleFactor layout changes. Then I format the layout on the custom layout by calling requestLayout . Unfortunately, this does not affect children. The onMeasure and onLayout never called, even if the parent goes through a dimension and layout cycle. But, if I directly call requestLayout on one of the children, only this child gets the scaling in accordance with the scaling factor set in the parent !!

It seems that if requestLayout not only called only in the view, it no longer measures itself and uses some kind of cache instead. This can be seen from the source code for the 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 to make children also measure themselves again when calling requestLayout on their parent?

+5
source share
1 answer

This will force the child elements of the view to be relayed (given that the view of its own width and height does not need to be changed)

 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()); } 
+4
source

Source: https://habr.com/ru/post/1203338/


All Articles