Layout width and height are ignored

I have a dialog with a layout inside and a SurfaceTexture with a video stream. When I get the width and height from the video, I resize my layout as follows:

 private void resizeView(final VideoFormatInfo info) { final Size size = calculateSize(info.getWidth(), info.getHeight()); mActivity.runOnUiThread(new Runnable() { @Override public void run() { final ViewGroup.LayoutParams layoutParams = mInnerLayout.getLayoutParams(); layoutParams.width = size.x; layoutParams.height = size.y; Log.i(TAG, String.format("run: setting innerlayout bounds to %d,%d", size.x, size.y)); mInnerLayout.setLayoutParams(layoutParams); } }); } 

Now I have a full-screen button that should resize the layout to full screen. But when I click it, the layout remains in a small area of ​​the screen.

When I check the log, the correct value on size.x and size.y is (screen borders), but the layout does not change properly.

The internal output is added to the customView named "VideoPlayer". I set the background color of the video player to red, so when I switch to full screen mode, the entire screen turns red, except for the video stream in the middle. This means that the main view is correctly changed, but innerLayout is not for any reason.

Funny, I have another layout over video rendering that creates a “flash effect” to simulate a camera flash when taking a picture. When this flash effect is triggered, the video changes to full screen.

So this is my layout tree:

 VideoPlayerView (CustomView, not VideoView) innerLayout (RelativeLayout) videoSurfaceTexture (SurfaceTextureView) flashLayout (RelativeLayout) 

I also set this for debugging:

  @Override public void onSurfaceTextureSizeChanged(final SurfaceTexture surfaceTexture, final int width, final int height) { Log.d(TAG, "onSurfaceTextureSizeChanged size=" + width + "x" + height + ", st=" + surfaceTexture); Log.i(TAG, String.format("innerlayout bounds are %d,%d", mInnerLayout.getLayoutParams().width, mInnerLayout.getLayoutParams().height)); } 

The values ​​in the internal layout are the correct values ​​(of the entire screen) when you click on full-screen mode, but the layout does not change. I can say that the layout was not changed because I changed its background color to green and added some addition, and I see it in the center of the screen, taking up a small space.

It seems that the view does not update with a layout change.

I'm running out of ideas here. I tried invalidate() , postInvalidate() and forceLayout() , but they do not work.

+6
source share
3 answers
 final ViewGroup.LayoutParams layoutParams = mInnerLayout.getLayoutParams(); layoutParams.width = size.x; layoutParams.height = size.y; Log.i(TAG, String.format("run: setting innerlayout bounds to %d,%d", size.x, size.y)); ViewGroup parent = ((ViewGroup)mInnerLayout.getParent()); parent.removeView(mInnerLayout); mInnerLayout.setLayoutParams(layoutParams); parent.addView(mInnerLayout);//you might need to get the index so you slot it in there. 

It will be done. - (all thoughts)

EDIT

I did not want to add an explanation, because these were all thoughts, and I had to check if this would work.

But the explanation for my LayoutParam code is what Parent uses to build their children, so it’s only useful when building momentum or time. Changing the layoutParams object makes the View object dirty, other factors must be fulfilled before the dirty View is unloaded, so the values ​​change and the View is not changed.

you could also just call View.invalidate() and View.requestLayout() on that particular View or Parent , and it will also solve your problem, but calling View.invalidate() will not be done instantly for you. eg,

 layoutParams.width = size.x; layoutParams.height = size.y; Log.i(TAG, String.format("run: setting innerlayout bounds to %d,%d", size.x, size.y)); //re-setting the layout params is also not neccessary mInnerLayout.invalidate(); mInnerLayout.requestLayout(); 

The reason the first approach solves your problem is because the View is removed and added, which causes Laying out processing to be processed

:) also you should just accept it and give an expiration :)

+2
source

You missed one important part of forceLayout() :

This method does not call requestLayout() or forceLayout() for the parent.

So do the parent layout as well:

 mInnerLayout.setLayoutParams(layoutParams); mInnerLayout.forceLayout(); mInnerLayout.getParent().requestLayout(); 
+4
source

use inflator like

 View view = inflater.inflate( R.layout.item /* resource id */, MyView.this /* parent */, false /*attachToRoot*/); 

for additional verification Layout parameters of loaded view are ignored

+1
source

All Articles