开发者

Fragment without a view crashes on configuration change

I have an UI where I need a Fragment to be displayed (with a view) in landscape mode but not in portrait mode. In portrait mode it should still be available but will display its result using ListPopupWindow instead.

I figured I could handle this by using the <fragment /> tag for the landscape layout while creating the fragment programmatically if it wasn't started (in the case when we are in portrait).

This works fine as long as you start out in landscape, if you start in portrait where the fragment is created programmatically your application will crash when you rotate the emulator when it tries to attach the fragment to your layout:

java.lang.IllegalStateException: Fragment did not create a view. at android.app.Activity.onCreateView(Activity.java:4095)

The docs for Fragment.isInLayout() seems to hint that it should be able to handle it this way:

Return true if the layout is included as part of an activity view hierarchy via 开发者_JS百科the tag. This will always be true when fragments are created through the tag, except in the case where an old fragment is restored from a previous state and it does not appear in the layout of the current state.

So the question is how to do this correctly or if there is something I'm missing?

UPDATE:

Seems like isInLayout() isn't behaving as it should currently as well. It returns false if you have added a Fragment to a container manually.

Also, if you add a Fragment manually to a container and then rotate (the device) to a layout that does not contain that layout it will crash:

Caused by: java.lang.IllegalArgumentException: No view found for id 0x7f060011 for fragment SearchFragment{4042f868 #2 id=0x7f060011 SearchFragment} at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:722)


Have you come up with an answer to this? I was having a similar problem, and managed to come up with a solution. You can easily do what you are attempting as follows:

Create two different layouts one in the layout directory, one in the layout-land directory. The one in the layout-land directory will be used in landscape mode. As a placeholder, where you want your fragment to go, use s FrameLayout element, and id it, say with the id "my_fragment". The layout in the layout directory should not contains any element with that id.

In your onCreate method, use findViewById(R.id.my_fragment) to locate the fragment placeholder. If it exists, you are in landscape mode and should add your fragment (if it does not exist already): add(R.id.my_fragment, new MyFragment, "myFragment). If you get null, you are in portrait mode and should not create the fragment.

Be very careful that you never replace a fragment created using a tag, with one that you create dynamically in your program. A fragment for which isInLayout returns true is a completely different beast, that one for which it returns false. Their lifecycles are entirely different. Replacing one with the other will lead to the dreaded IllegalStateException "Fragment did not create a view" problem.

-blake


Your problem can also be due to not having a lanscape layout for the fragment you are using. You might have one for the portrait and so your program runs fine but when you rotate your device, the OS probably looks for the view in the landscape folder and doesnt find the view so declares it as missing. Check that you have view both in the folder "layout" and "layout-land".

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜