Shared element transition not showing on top - android

I'm trying to run a shared element transition from a recycler view to a detail view containing a pager. Pretty much the same as in this blog post.
Everything works, except that the back-from-detail-to-overview animation is clipped to the overview recycler view cells.
After watching this talk, I learned, that unless setSharedElementsUseOverlay is set to false on the activity's window, the transitions will run on an overlay that's on top of everything - the whole content of the activity if I understood correctly. So it should not be possible that the transition is hidden or clipped.
I searched both for setSharedElementsUseOverlay and windowSharedElementsUseOverlay in my project and didn't find anything. The default is supposed to be true. I also tried setting it explicitly to true, both in the theme and programmatically and nothing... the transition is still clipped!
I tried to cause the clipping with the demo project from the blog post, and also wasn't able to - setting setSharedElementsUseOverlay to false doesn't cause any clipping. I ensured that no view in the whole project has clipChildren or clipPadding set to false.
I have no idea what else to do. I tried debugging Android's sources but the transitions classes are unwieldy and I couldn't even find where the overlay view is used. The only thing that I get working in my project is setting clipChildren and clipPadding to false all the way up in the hierarchy, but this is not what I want - besides of undesired side effects (even when doing it temporarily as it may overwrite non-defaults of parents) it also doesn't cause the effect I want without further tweaking, as now overlay views of the shared element appear on top during the transition.
Well, I can step by step modify the example project until it's the same as my actual project, but this is a very tedious task as the actual project is very large and complex. I have done some changes that seem relevant, like adding intermediate views and so on. No success so far.
I simply want to use the overlay. What can be the reason for it not working? Or at least how can I debug this?
I've reproduced this so far on Android M and N. Haven't tested on any other versions.

Related

Android Studio & Constraint Layout Editor Problems

I have watched numerous videos, including Google's own, and i'm really struggling with ConstraintLayout, it simply doesn't work for me, like it works in the online videos.
When I drop a textview onto the constraint layout editor, it jumps to the top right of the form. In the demo videos, it stays where it's dropped, and it's easy for those people to set up the relationships by dragging handles. For me, It's all up in the top right, and I can only get to 2 of the handles.
It gets worse if I then drop two more text views into the form, they are all now all the same size and all overlapped at the top. Whenever I use constraint layout, I end up tearing my hair out, and then giving up and going back to an older layout.
I really want to use constraintlayout, but clearly I am missing something really obvious here, but I can't figure out what.
Yes the drag and drop doesn't work well. For me I just use several steps to add a new view:
1. drag new view to the end of the view list window (not on the design view! design view will add unnecessary properties and is not clean)
2. select the new view, and name it! name is very important to constraint layout.
3. set the layout_constraint_xxx attributes from the property window
then it goes to the expected places.
Try disabling the experimental render engine and re enable it again

MotionLayout breaks the redrawing of (nested) subviews

I'm having problems with views not refreshing in MotionLayout.
Seems like at some point the refresh/redraw mechanism of MotionLayout becomes broken and the subviews (including the nested ones) are having random problems updating themselves on the screen. What I have experienced so far:
RecyclerView is not refreshed sometimes. This happens when new data is available, I'm using Paging library to fill the data. I have fixed it with a workaround of scrolling 1 pixel when I got new data there - recyclerView.smoothScrollBy(0,1). After that the RecyclerView starts redrawing itself just fine.
When the keyboard is opened it randomly messes the nested subview redrawing. There is an issue in github โ here where a guy reproduces all this by adding an EditText to official MotionLayout examples. Some examples of the problems that I'm seeing:
I'm using TextInputLayout with app:endIconMode="clear_text" in MotionLayout -> ConstraintLayout -> TextInputLayout and the X button is sometimes not shown when I start typing (also after closing the keyboard).
TextView is redrawn partially! I'm showing "No Results" or "No Posts" text in a TextView, switching between them based on some logic, but instead of refreshing the whole text only "No" is shown in the UI. I have debugged it, Layout Inspector says everything is fine, the text view value is "No Results", but I don't see it on the screen.
Some other animations are broken, like indeterminate progress animation of nested SwipeRefreshLayout
IMPORTANT: All the refresh/redraw issues are fixed when I do a transition! When I come to some messed state where 3 nested subviews are frozen/partially drawn, then I just need to press a button that triggers my transition, and all of them are happily redrawing themselves!
Please let me know if this is a known problem and if there is a workaround for this. I could do invisible 1 pixel transition maybe, but I cannot even detect when the MotionLayout refreshing becomes broken, handling keyboard and new data of RecyclerView doesn't seem to cover all the cases. Otherwise, I will have to move back to ConstraintLayout and think on implementing the amazing OnSwipe functionality myself (if that is even possible in ConstraintLayout).
I am also experiencing issues with update of nested subviews and MotionLayout. Google please fix this issue with MotionLayout.
Using requestLayout() on the nested subviews will often update the Views.
By default during transition motionLayout does not honor requestlayout() during transitions.
Add layoutDuringTransition=honorRequest during the transition
<Transition ... motion:layoutDuringTransition="honorRequest" ... \>
Not really an answer, but too long for a comment:
Since you are facing multiple problem with possibly multiple root causes, I would suggest to create a Sandbox project and reproduce each problem at a time in a safe and simple environment.
To me it seem like you have one problem with the paging lib (not with motionLayout in this case) and another problem with the EditText.
You should check your paging code without ML and check your EditText problem without any scrolling views. I know this is not much of a help, but maybe a guide how to tackle these problems. Mind that MotionLayout is still in beta and especially release 2.0.0-beta02 and beta03 was pretty messy with regression errors. Update to the newest version (beta04 as of now) or continue using a stable version.
Sometimes it also helps to search the official tickets for MotionLayout

Activity Return Transitions - Shared Elements - Killed Activity

Library used: appcompat-v7:22.2.1,design:22.2.1
Theme used:
Devices/Android versions reproduced on: Nexus 6
Issue: Return activity quickly redraws/appears then fades in with desired behaviour, only with "Don't keep activities alive".
I am wondering if this is a bug or expected behaviour. I have a very simple setup. Activity A contains a toolbar wrapped in an AppbarLayout and CoorindinatorLayout. The toolbar contains a Cardview and a TextView. Upon click of the TextView, Activity A launches Activity B. I am using shared elements and passing them through as Option's via ActivityCompat.StartActivity(bundle, options);
My shared elements work perfectly, even after device rotation. After reading about how I can PostPoneEnterTransition and combo it up with PreDrawListeners I am able to successfully achieve the desired transition even after rotation. My actual activity contains a Viewpager / TabLayout and 2+ fragments but for simplicity sake, I've stripped it back in the video as well as to see if something else was causing this issue.
While dealing with rotation and postponing of the enter transition back to Activity A, I decided to open developer options and check "Don't keep activities alive". The video depicts the app running with that option enabled. If you look closely, you can see upon return to Activity A, it is completely drawn and hidden very quickly and then the fade in occurs as well as the shared element transition.
I've also excluded the navigation bar and status bar in the animations so that I don't see those flicker (redraw redundantly).
My questions are:
Is this a bug, or am I missing a step in order to prevent this.
Why would the app/transitions behave differently with "Don't keep activities alive" vs a plain old device rotation (destroy/recreate).
I've noticed by playing around with some google apps, this behaviour does not occur, or at least that I could find. Is there a way to concretely check if the activity I am returning too is "completely destroyed" so I can cancel the animation? Or do something different?
I can include specifics and code samples if required but my setup is very simple, and reflects a bunch of boilerplate examples from the Android documentation / Stack-overflow.
Sorry I meant to respond to this earlier. What I ended up doing was recreating the example in a completely fresh project following code samples and tutorials as best I could. First making it work with a single image view, and then of course adding my custom layout which was a floating search bar. Everything worked as expected. I went back and reviewed my actual project source (which was littered with different attempts and commented out code while trying to debug this issue) and cleaned it up. I can't say for sure, but I believe it came down to two possible issues:
"Unless you do something unusual..." - Most likely I "was" doing something unusual by the time I created this issue do to my debugging efforts and lack of full comprehension of the shared elements transition framework and lifecycle.
I think what was happening was the shared element transition was failing do to views not being mapped properly. I was excluding the statusBarBackground inside a transition defined in XML. My statusBarBackground was set to transparent so that I had the nice overlay effect for an expanded drawer layout. I found out that while trying to add the statusbarbackground as a shared element via code, the view was actually null resulting in a crash (NPE). As well as I had set a background color (instead of transparent) to my drawer layout. I can't say for sure, but a combination of these mistakes lead to the strange behaviour.
To conclude, I would say that this issue should be closed and everything is working as intended. It would be nice to get a little more insight on handling a transparent status bar as a shared element.
Is this a bug, or am I missing a step in order to prevent this?
No. Everything is working as intended.
Why would the app/transitions behave differently with "Don't keep activities alive" vs a plain old device rotation (destroy/recreate)?
It doesn't. When everything is setup proper and your timing and mapping of shared elements is correct, "Don't keep activities alive" is a concrete way to test your transitions against configuration changes.
I've noticed by playing around with some google apps, this behaviour does not occur, or at least that I could find. Is there a way to concretely check if the activity I am returning too is "completely destroyed" so I can cancel the animation? Or do something different?
This is because the Google dev's did it right :)
For anyone struggling with shared elements, here is a bit of advice.
Start small. Use a single view first and confirm you are getting the correct behaviour in all circumstances, even after rotation and config changes, then you can add complexity.
Use SharedElementCallback to debug your transitions. You can check which views are mapped, which view failed etc.

Android xml:onclick from a layout with a glsurfaceview causes image drawables on previous activity to render as black

This is an odd problem that took me quite awhile to reproduce reliably.
I have a menu activity that is very simple; just some buttons defined in xml.
I have an activity with a layout with a GLSurfaceView and some buttons defined in xml.
These buttons have onClick attributes defined. This activity is accessed from the menu activity.
In the OpenGL activity there are the associated onClick functions "onFoo(View view)".
When I navigate back to the menu activity using the native Back button nothing interesting happens; however, when I click ANY of the xml defined buttons with an onClick attribute and then navigate back some of the ImageViews on the menu activity appear as black but otherwise in their correct locations, sizes, etc. Their xml defined onClick functions work correctly as well.
I am having all of the images on the menu activity re-exported (to eliminate any export setting flaws since the assets were originally exported at various times), but while I wait for that to happen I figured maybe someone out there has run into this problem before.
For the purpose of limiting variables in this problem I even commented out the function's contents in the OpenGL activity to make sure nothing in the onClick functions was causing a conflict.
e.g.
public void onMainMenu (View view)
{
}
So, to clarify, if I click a button defined in xml with an onClick attribute e.g.
android:onClick="onMainMenu" with the above empty method, then press the native back button the issue occurs, but not when skipping the clicking of the onMainMenu button.
I can't be sure if it is always the same set of ImageViews that turn black, but one ImageView does seem to consistently survive with the correct Drawable; this is odd because the ImageViews are defined identically other than their src attribute. They are all relatively the same size and not large at all.
I originally thought it had something to do with the EGL context (Android displays black rectangles instead of drawable images after opening openGL context) (and it still may be the case), but then I discovered how to reproduce it 100% of the time by pressing a button with an onClick attribute before navigating backwards. Memory usage is in control and I am lost for a possible solution or trail to one.
I can reproduce this on the three devices I have: an HTC One, Droid Bionic, Galaxy Tab 2 7.
The Application is minSdk:14, target:17. Hardware acceleration is on.
I tried playing with hardware acceleration settings with the following results:
If I turn off hardware acceleration for the application, and add it to just the OpenGl activity the main menu issue does not appear, but the same issue starts occurring in the OpenGL activity. In the case of this activity some ImageView's drawable resources are switched out at run-time. The switched in resources display correctly, but when switched back to the same resource that the was defined for that ImageView in xml it renders black.
To clarify the switching: in one such case I have views with a drawable-state-selector for their backgrounds. When switching between the two states (they function like tabs i.e. their default states as defined in xml are opposite) the default state always displays as black but the secondary state displays correctly.
If I turn off hardware acceleration for the application AND the OpenGL activity, the problem appears to go away completely.
I worry about using that as a solution though as I can't be sure of any performance problems that may occur on devices I do not have to test with.
Removing hardware acceleration from the OpenGL activity breaks a view that overlays the GLSurfaceView on at least the Droid Bionic, so I'd rather not use this pseudo-solution.
This is the first time I have posted a question on Stack Overflow. I always find a solid lead searching, but just could not find a solution or even a problem with similar circumstances in this case.
Thanks for any help and wisdom the community can provide!
The problem came down to a call to GLES20.glDeleteTextures(int size, int[] textureNames, int offset). I was calling this during onPause() which was somehow causing a conflict. I am not sure how it was related to touching a UI item outside of the GLSurfaceView. Removing the one call somehow prevents the issue.

Children of FrameLayout not clickable on some devices

I have designed a menu that consists of a few buttons in several different LinearLayouts all placed over an animated GLSurfaceView within a FrameLayout. When the user clicks a button in the interface, I set the current layout's visibility to GONE before making the next layout VISIBLE When the user selects a level, then game play starts and all layouts are GONE (apart from a control bar on the right of the screen, but that is not contained inside the FrameLayout)
On most phones the menu works like a charm, but I did a quick test on an Xperia Ray only to find that I couldn't go anywhere because the buttons wouldn't click. I have Log.d tags set up in most of my onClick Listeners, and in this case they aren't showing in the Logcat so it doesn't seem like the Listeners are firing at all. I also noticed that the GLSurfaceView wasn't returning anything from it's own TouchEventListener. Even though the functions triggered by tapping the GLSurfaceView are disabled while on the top menu, I normally still get a message in the Logcat.
I thought it could be something to do with the way I have used the FrameLayout. The documentation says it should only have one child, but another article I read on android developers demonstrated captioning images by displaying text over ImageViews inside a FrameLayout.
On a final note, I'll also say that I've tested in the emulators and I found that both android v2.3 and android v4 display the same behaviour as the ray. Currently those are the only ones I am sure of, aside from android v2.2 which runs my app perfectly. I am hesitant to trust the results of testing on the emulators.
I am personally stumped seeing as there is no error message to go on, but can anybody suggest a solution?
I found the solution.
Turns out that I had a stray ScrollView hanging around in my layout that was both above my root layout in z-order and visible by default. Instead of toggling the visibility of this view, I was doing so for it's child layout. Oops.
On most devices I have tested on, the stray ScrollView has not effected the functionality of my app, probably because the empty layout was allowing buttons behind it to be clicked. However it turns out that some devices, such as the Xperia Ray, are a little more strict on whether clicks can be passed down through layouts (possibly a performance decision).
The ScrollView was a required part of the layout so I couldn't just remove it. Instead I gave the the android:visibilty attribute to the ScrollView so that it would be GONE until it is needed by the interface and it won't block the user from clicking buttons.

Categories

Resources