SurfaceView onMeasure() did not set the measured dimension by calling setMeasuredDimension()

4

I have a SurfaceView. I just draw on it manually from an other Thread.

It runs nicely. But after 10-20 minutes of running in average I get this exception:

01-14 08:51:25.000    3740-3740/com.myPackage E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.IllegalStateException: onMeasure() did not set the measured dimension by calling setMeasuredDimension()
            at android.view.View.measure(View.java:15200)
            at android.widget.RelativeLayout.measureChild(RelativeLayout.java:602)
            at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:415)
            at android.view.View.measure(View.java:15195)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4823)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:15195)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4823)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1390)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
            at android.view.View.measure(View.java:15195)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4823)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2340)
            at android.view.View.measure(View.java:15195)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1850)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1102)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1275)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4216)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
            at android.view.Choreographer.doCallbacks(Choreographer.java:555)
            at android.view.Choreographer.doFrame(Choreographer.java:525)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
            at android.os.Handler.handleCallback(Handler.java:615)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4813)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:559)
            at dalvik.system.NativeStart.main(Native Method)

Android Documention says:
Measure the view and its content to determine the measured width and the measured height. This method is invoked by measure(int, int) and should be overriden by subclasses to provide accurate and efficient measurement of their contents.

As I think the original implementation from google is this:

@Override
    protected void More ...onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(mRequestedWidth, widthMeasureSpec);
        int height = getDefaultSize(mRequestedHeight, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

I don't know what I else should I implement here.

I think the size of the surface view never changes.

NOTE:
My SurfaceView is contained in a RelativeLayout.
The exception is called by a child, but it's a view (line 3 in the exception)

Please help me if you know how could I solve this annoying bug.

EDIT:
In Activity's onCreate I set the size of my view (that extended form SurfaceView) from code

Answear to comment:
This is how I set some public fields for the required size:

Parameters.initialize(getResources().getDisplayMetrics().widthPixels,
                getResources().getDisplayMetrics().heightPixels);

The Parameters.initialize:

public static void initialize(int screenWidth, int screenHeight){
    FIELD_WIDTH = screenWidth;
    FIELD_HEIGHT = (int)(0.92f * screenHeight);
}

MyView is written in the xml.
Then I set something on it:

public class MyViewManager {
    protected MyView mMyView;

    public FieldPainterComp(MainActivity activity) {
        super(activity);
        initialize();
    }

    private void initialize(){
        mMyView= (MyView) activity.findViewById(R.id.vMyView);
        mMyView.getLayoutParams().height = Parameters.FIELD_HEIGHT;
        mMyView.getLayoutParams().width = Parameters.FIELD_WIDTH;
    }
}

This whole process happens ones in the beginning.

android:screenOrientation="landscape"

Screen never goes dark. Game is running, and simply the exception is coming.
Should I call measure somewhere?
I don't understand why is it happaning after a long time

Some other exception that must be in connected with this:

01-19 11:53:39.812  29666-31881/com.mypackage V/GAV4﹕ Thread[disconnect check,5,main]: Disconnecting due to inactivity
01-19 11:53:39.812  29666-31881/com.mypackage V/GAV4﹕ Thread[disconnect check,5,main]: Disconnected from service
01-19 11:57:17.732  29666-29666/com.mypackage D/AndroidRuntime﹕ Shutting down VM
01-19 11:57:17.732  29666-29666/com.mypackage W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x420face0)
01-19 11:57:17.812  29666-29666/com.mypackage V/GAV4﹕ Thread[main,5,main]: Tracking Exception: IllegalStateException (@View:measure:16533) {main}
01-19 11:57:17.832  29666-29666/com.mypackage V/GAV4﹕ Thread[main,5,main]: Dispatch call queued. Dispatch will run once initialization is complete.
01-19 12:19:27.982  29666-29670/com.mypackage I/dalvikvm﹕ threadid=3: reacting to signal 3
01-19 12:19:28.262  29666-29670/com.mypackage I/dalvikvm﹕ Wrote stack traces to '/data/anr/traces.txt'
01-19 12:19:32.452  29666-29666/com.mypackage A/libc﹕ Fatal signal 6 (SIGABRT) at 0x0000025a (code=0), thread 29666 (ames.adaptation)

The GAV -is the Google Analytics stuff.

I launched an other question about the ANR: ANR with 3 threads - using locks

android
surfaceview
onmeasure
asked on Stack Overflow Jan 19, 2015 by Tomi • edited May 23, 2017 by Community

4 Answers

3
setMeasuredDimension()

Must be called inside of your onMeasure() method. I had a similar problem where the logic wasn't reaching setMeasuredDimension(). I resolved it forcing the call of setMeasuredDimension() no matter what the if/else statements preceded it.

answered on Stack Overflow Nov 8, 2015 by IgorGanapolsky
0

You use Fragment and don't write this line at the first

super.onCreate(savedInstanceState);
answered on Stack Overflow Jan 9, 2017 by Moeen Kashisaz
-1

private double aspectRatio = 1.0;

private boolean isCalledRecreate = true;

in onMeasure ::- double localRatio = aspectRatio;

    if (localRatio == 0.0) {
        super.onMeasure(widthSpec, heightSpec);

    } else {
        int lockedWidth = MeasureSpec.getSize(widthSpec);
        int lockedHeight = MeasureSpec.getSize(heightSpec);

        if (lockedWidth == 0 && lockedHeight == 0) {

            widthSpec = MeasureSpec.makeMeasureSpec((int) (basicWidth), MeasureSpec.AT_MOST);
            heightSpec = MeasureSpec.makeMeasureSpec((int) (basicHeight), MeasureSpec.AT_MOST);

            lockedWidth = MeasureSpec.getSize(widthSpec);
            lockedHeight = MeasureSpec.getSize(heightSpec);

            Log.i(TAG, "onMeasure: onMeasure");

            callForRecreate();
        }

        // Get the padding of the border background.
        int hPadding = getPaddingLeft() + getPaddingRight();
        int vPadding = getPaddingTop() + getPaddingBottom();

        // Resize the preview frame with correct aspect ratio.
        lockedWidth -= hPadding;
        lockedHeight -= vPadding;

        if (lockedHeight > 0 && (lockedWidth > lockedHeight * localRatio)) {
            lockedWidth = (int) (lockedHeight * localRatio + .5);
        } else {
            lockedHeight = (int) (lockedWidth / localRatio + .5);
        }

        // Add the padding of the border.
        lockedWidth += hPadding;
        lockedHeight += vPadding;

        // Ask children to follow the new preview dimension.
        super.onMeasure(MeasureSpec.makeMeasureSpec(lockedWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(lockedHeight, MeasureSpec.EXACTLY));

Note :- callForRecreate() in that you have to create or restart activity

answered on Stack Overflow Jun 11, 2019 by Bhaven Shah
-1

Make sure to call super.onMeasure(widthMeasureSpec,heightMeasureSpec); //e.g @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec,heightMeasureSpec); //then your code }

answered on Stack Overflow Sep 30, 2020 by Rohit Patil

User contributions licensed under CC BY-SA 3.0