I'm trying to add a DrawerLayout to my application for navigation, and I'm testing my application with Robolectric (I've seen this problem both with Robolectric 2.1.1 and 2.1-SNAPSHOT - 2.2-20130712.161723-17)
I'm using the following xml for the base of my drawer layout. I encounter the error in Robolectric when I have the andioid:layout_width or android:layout_height set to be "match_parent" on the Drawer Layout.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#D8D8D8"
android:dividerHeight="1dp"
android:background="#F2F2F2"/>
</android.support.v4.widget.DrawerLayout>
Here's the stack trace of the error I'm encountering:
java.lang.IllegalArgumentException: DrawerLayout must be measured with MeasureSpec.EXACTLY.
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:591)
at android.view.View.measure(View.java:15172)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4816)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at android.view.View.measure(View.java:15172)
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:4214)
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$FrameHandler.handleMessage(Choreographer.java:657)
at org.robolectric.shadows.ShadowHandler.routeMessage(ShadowHandler.java:125)
at org.robolectric.shadows.ShadowHandler.access$100(ShadowHandler.java:25)
at org.robolectric.shadows.ShadowHandler$1.run(ShadowHandler.java:110)
at org.robolectric.util.Scheduler$PostedRunnable.run(Scheduler.java:162)
at org.robolectric.util.Scheduler.runOneTask(Scheduler.java:107)
at org.robolectric.util.Scheduler.advanceTo(Scheduler.java:92)
at org.robolectric.util.Scheduler.advanceToLastPostedRunnable(Scheduler.java:68)
at org.robolectric.util.Scheduler.unPause(Scheduler.java:25)
at org.robolectric.shadows.ShadowLooper.unPause(ShadowLooper.java:219)
at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:258)
at org.robolectric.shadows.ShadowViewGroup.addView(ShadowViewGroup.java:32)
at android.view.ViewGroup.addView(ViewGroup.java)
at android.view.ViewGroup.addView(ViewGroup.java:3225)
at android.view.LayoutInflater.inflate(LayoutInflater.java:497)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at org.robolectric.tester.android.view.RoboWindow.setContentView(RoboWindow.java:82)
at org.robolectric.shadows.ShadowActivity.setContentView(ShadowActivity.java:273)
at android.app.Activity.setContentView(Activity.java)
at com.taskrabbit.droidrabbitstaging.TRRootDrawerActivity.onCreate(TRRootDrawerActivity.java:35)
at com.taskrabbit.droidrabbitstaging.ui.routes.EmptyRouteActivity.onCreate(EmptyRouteActivity.java:34)
at com.taskrabbit.droidrabbitstaging.ui.routes.EmptyRouteActivityTest.setUp(EmptyRouteActivityTest.java:62)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:241)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:177)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
I've tried setting these to a hard-coded value (of say 400dp) and that clears up the problems in the test. However, I then have trouble getting the width & height to be match_parent for my app installed on my phone. Is there any way that I can set the width and height of my Robolectric device? Or has anyone encountered this and come up with some other work around?
It appears to be related to this issue: https://code.google.com/p/android/issues/detail?id=55611 Note, the other side effect of this issue is that Design View is broken.
After some digging, I found a solution. It seems that Robolectric is somehow misscalculating the MeasureSpecs, which leads to this issue. In my case I could fix this problem by extending the DrawerLayout, and overriding onMeasure() :
public class CustomDrawerLayout extends DrawerLayout {
public CustomDrawerLayout(Context context) {
super(context);
}
public CustomDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
widthMeasureSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Update your Support Library jar: http://developer.android.com/tools/support-library/setup.html
And make sure that your project refers the latest one: How do I add a library (android-support-v7-appcompat) in IntelliJ IDEA
Example path to the lib: [adt-bundle-windows]\sdk\extras\android\support\v4\android-support-v4.jar
Just run your program on your android device. It runs perfectly. Just some problem in Eclipse i guess.
来源:https://stackoverflow.com/questions/17687173/in-robolectric-how-do-i-get-around-drawerlayout-must-be-measured-with-measuresp