25

I am trying to do a hero transition in Android 5.0 between an image in a ListView to a details page. But for about 50% of my images Android crashes with the exception below. My images are 600x400 but I tried changing them to 200x100 but got the same error. When it works, it looks great but I cannot see the difference between the various images. Really unsure why it claims the layer is too big, anybody got a clue?

private void handleNewsItemClicked(AdapterView<?> arg0, View viewClicked, int arg2) {
    TopNewsItem item = ((TopNewsItem)arg0.getAdapter().getItem(arg2));
        Intent intent = new Intent(getActivity(), TopNewsDetailsActivity.class);
        intent.putExtra(TopNewsDetailsActivity.ARGS_ID, item.getGuid().getId());
        intent.putExtra(TopNewsDetailsActivity.ARGS_IMAGE,  imageUrl);
        if(Build.VERSION.SDK_INT >= 21) {                                 
            ActivityOptions options = ActivityOptions
                    .makeSceneTransitionAnimation(this.getActivity(),
                            viewClicked.findViewById(R.id.image), "article_image");                
            this.getActivity().startActivity(intent, options.toBundle());
        }else
            getActivity().startActivity(intent);
    }
}

W/OpenGLRenderer(18137): Layer exceeds max. dimensions supported by the GPU (1080x4628, max=4096x4096)
D/AndroidRuntime(18137): Shutting down VM
V/GAV3    (18137): Thread[main,5,main]: Tracking Exception: IllegalStateException (@MessageQueue:nativePollOnce:-2) {main}
/AndroidRuntime(18137): FATAL EXCEPTION: main
E/AndroidRuntime(18137): Process: myapp.app, PID: 18137
E/AndroidRuntime(18137): java.lang.IllegalStateException: Unable to create layer for  RelativeLayout
E/AndroidRuntime(18137):    at android.os.MessageQueue.nativePollOnce(Native Method)
E/AndroidRuntime(18137):    at android.os.MessageQueue.next(MessageQueue.java:143)
E/AndroidRuntime(18137):    at android.os.Looper.loop(Looper.java:122)
E/AndroidRuntime(18137):    at android.app.ActivityThread.main(ActivityThread.java:5221)
E/AndroidRuntime(18137):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(18137):    at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime(18137):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
E/AndroidRuntime(18137):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Christer Nordvik
  • 2,518
  • 3
  • 35
  • 52
  • FYI I reported this as a bug in Android: https://code.google.com/p/android/issues/detail?id=167551&thanks=167551&ts=1429258132 – gphilip Apr 17 '15 at 08:37

3 Answers3

50

The Fade transition will use hardware layers when your view does has "hasOverlappingRendering()" return true. This was done for performance. You must have many views all fading out separately.

You have a couple options. One is for your views to have hasOverlappingRendering return false. This may not be possible in all cases, but it may be enough to solve your problem. Remember that this means that the contained views should not overlap!

The second is to transition fewer views separately. You can do this by setting android:transitionGroup="true" on ViewGroups that should be faded out together. For example, if you have a ListView with no background, you'll end up transitioning each element separately. Instead, you can set the ListView's transitionGroup property to true and then they'll transition together.

-- update --

The problem you're encountering is that the incoming Views that are fading in are too large. I tried the following View in the launching Activity:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:onClick="clicked"
    >
    <TextView
        android:id="@+id/hello_world"
        android:transitionName="hello"
        android:text="@string/hello_world"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

Yes, the hello world basic app from android, giving an id and transitionName to the text. The onClick handler just launches the second Activity, passing the hello world View as a shared element. The second Activity has an extremely large TextView, similar to yours:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:transitionGroup="true"
    >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/hello_world"
            android:transitionName="hello"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="@string/hello_world" />
        <TextView
            android:layout_below="@+id/hello_world"
            android:text="Lorem ipsum.... I didn't copy all of my text"
            android:textSize="30sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
    </RelativeLayout>
</ScrollView>

Switching the ScrollView's transitionGroup from false (the default value) to true makes it work because then the ScrollView is being faded in. The ScrollView has a maximum size, while its contents can be enormous.

George Mount
  • 20,708
  • 2
  • 73
  • 61
  • I tried the second option and it still crashed. I don't have many views, I only have the one imageview in the transition. Here is a video of the issue: https://www.youtube.com/watch?v=eq1ntnx7sJU. Can it be something else triggering this? I am loading the images with the Glide library in case that could affect anything. – Christer Nordvik Oct 31 '14 at 10:08
  • Nice app UI, BTW. I don't think the Glide library should be a problem. Now that I look at the error message a little better, I see that you're exceeding the maximum dimensions for a hardware layer. I have to think that the hardware layer it is trying to create is in the calling Activity (the list is growing, I assume). If this is caused by the Fade transition, you can remove it by setting the android:windowExitTransition to @null. You'll still see a cross-fade effect when the incoming activity comes up. You should also consider using a RecyclerView for that scrolling list. – George Mount Oct 31 '14 at 20:17
  • Tried RecyclerView, same issue. So I changed to @null and everything works but the animation isn't very nice anymore. This seems like a bug to me? It is always the same image(s) that crashes, so if I restart the app it will crash the first time I click on that image. If I stick to the working images I can click 20 different articles without an issue. – Christer Nordvik Nov 03 '14 at 10:04
  • I misunderstood where the problem was coming in. If changing android:windowEnterTransition to null fixes the problem, then it is in the detailed page that the problem exists. The RecyclerView won't help in that case. One specific RelativeLayout cannot fade in -- its width is 4628. There is no way to fade such a large view with good performance on most phones, so this is something that you'll have to correct in your application. I suspect that you're doing a layout_width="wrap_content" and your content is very large. Try to find that RelativeLayout and tame it. :-) – George Mount Nov 04 '14 at 17:23
  • I finally found the reason, it is the TextView with the article itself. Didn't really read the error message since it is the height that is the problem and not the width. That explains why some articles had issues and some worked fine. So how do I hack this together? Set the height to 1000dp and then set to wrap_content after the animation has finished or something like that? :-/ – Christer Nordvik Nov 05 '14 at 12:26
  • I actually tried that and it worked using postDelayed, but then it crashed on the exit transition (since the textview is now too big). Should I give up the fade animation? – Christer Nordvik Nov 05 '14 at 12:34
  • You can know when your code is going to leave by overriding the Activity.finishAfterTransition call. Changing the height there will work, but it will also mess up your transition. If you've scrolled down into the article, it is going to show full screen and be centered on the text somewhere other than the top. You'll have to adjust the scroll position of the TextView to compensate. Something much easier to do is set transitionGroup="true" on the ScrollView/RecyclerView containing the article and the shared element. – George Mount Nov 05 '14 at 15:08
  • Should I set the transitionGroup=true on the destination activity or only the source activity? I tried all the combinations I could think of without any success. Can the method described here work better maybe? http://ptrprograms.blogspot.no/2014/08/getting-started-with-android-l.html Where the image is passed in the extras? – Christer Nordvik Nov 05 '14 at 19:25
  • I tried this: http://ptrprograms.blogspot.no/2014/08/getting-started-with-android-l.html Where the image is passed in the extras and transitionGroup is set to false, and it crashed the same way. – Christer Nordvik Nov 05 '14 at 19:31
  • 2
    The problem is that the article is long, not that the image is large, right? I imagine that you have something like this in the detail activity: . If so, you want to set transitionGroup="true" on the ScrollView in the detail activity. I can write up a sample app to demonstrate. – George Mount Nov 07 '14 at 00:54
  • I have no idea what transitionGroup does but it magically solved all the issues! I couldn't find that property documented anywhere? Really appreciate the help :-) – Christer Nordvik Nov 07 '14 at 07:25
  • Enter and exit transitions search for the views that are going to exit separately and tell them to enter or leave the scene individually. Typically this is a Fade transition, but you can use any Visibility transition. The Views that these transitions target are either non-ViewGroups or ViewGroups that have transitionGroup=true. ViewGroups default to true when they have a background. Fade is simple and you could do these all together, but Explode or Slide act on each View individually. – George Mount Nov 09 '14 at 06:50
  • Thank you for this; I had the same issue and it fixed it. Conclusion: when you have a ScrollView containing potentially large elements like a TextView during an Activity Transition, you should always set its transitionGroup property to true. – BladeCoder Mar 24 '15 at 11:15
  • `transitionGroup` fixes it for me! Thank you! – gphilip Apr 15 '15 at 12:55
  • @GeorgeMount The issue is back in Android M :-/ http://stackoverflow.com/questions/32071265/android-m-scene-transition-with-hero-elements-throws-java-lang-illegalstateexce – Christer Nordvik Aug 18 '15 at 11:56
  • @GeorgeMount If my Shared Element is contained within a viewgroup with transitionGroup=true, would this stop the sharedElement from animating separately from it's sibling views? – android_student Sep 25 '15 at 20:40
  • It shouldn't. The shared element should animate separately from its parent when transitionGroup=true. Some transitions make bitmap copies of their contents when transitioning. Those may include the shared element in their bitmap and you'll get a funny effect. In the case of Activity Transitions, I don't think any of the built-in transitions will have the problem. – George Mount Sep 29 '15 at 19:41
  • This answer still saving people's asses, 2 years later. I also had a large TextView in a ScrollView! – Lisa Wray Jan 17 '17 at 20:23
8

The root cause of this issue is indicated in your log on this line:

W/OpenGLRenderer(18137): Layer exceeds max. dimensions supported by the GPU (1080x4628, max=4096x4096).

Your target activity has a height of 4628 which is greater than the maximum supported by the GPU - 4096.

The solution, already mentioned in the other answer, is to create a target activity which is shorter. Similar question and answer here: crash - material design android 5.0

Community
  • 1
  • 1
donturner
  • 17,867
  • 8
  • 59
  • 81
  • many thanks for your explanation. I'm getting `Unable to create layer for RelativeLayout, size 768x7040 max size 8192 color type 4 has context 1` error, which confuses me because the reported height (7040) is smaller than the max size (8192). so why this error occurs? – Soheil Feb 14 '22 at 10:06
1

You can just avoid it if the fade transition isn't a must: see here for detail: https://stackoverflow.com/a/45030173/4334399

Seth
  • 845
  • 8
  • 17