I have developed some custom behaviours for a TextView that changes position and size based on the height of the AppBarLayout inside a CoordinatorLayout. This is so that the title appears large and in the centre of the fully expanded Toolbar when open, but in the normal title position when the ToolBar is fully collapsed.
Take a look at the videos to see it on a Lollipop device (not working correctly) and a JellyBean device (working fine).
The issue occurs (I believe, based on my tests) on Lollipop devices only, and it seems to be linked to the fact that the status bar is an overlay on the Lollipop device, but not on the JellyBean one. This is reflected in my code as well, where to calculate the final y positions I need to do the following for the final position to be correct:
if (mFinalYPosition == 0) {
mFinalYPosition = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
? (((mContext.getResources().getDimensionPixelOffset(R.dimen.abc_action_bar_default_height_material)/2)) + getStatusBarHeight())
: ((mContext.getResources().getDimensionPixelOffset(R.dimen.abc_action_bar_default_height_material)/2));
}
The best solution for me would be if I could have Lollipop devices treat the status bar in the same as earlier Android versions, i.e. in a locked position, and not as an overlay.
How would I go about achieving this?
I was able to resolve this issue by removing all android:fitsSystemWindows elements from my layout xml file. In addition, it may be clear from the video I posted that some views disappeared during the animations on my Lollipop device then reappeared later. I was able to fix this by setting the elevation on certain Views to ensure they didn't vanish behind others during animation.
Related
It seems that selectableItemBackground is broken all over my app for pre Lollipop devices. Not sure if this is a broke in a support library update. All widgets like Buttons, CardViews, RadioButtons, etc that show a selected state are showing this strange black borders when being pressed
radio button
cards in recyclerview
And it happens in more scenarios like the back arrow of the Toolbar that shows by default. Note that API >= 21 devices shows the nice ripple effect in all the scenarios mentioned above.
I am using support lib v23.4.0 (I have already tried to downgrade to v23.3.0, v23.2.1 and v23.2.0 with the same results). My theme inherits from Theme.AppCompat.Light.NoActionBar and it does not set a custom drawable for selectableItemBackground. I looked at the source code and I was able to determine that the theme inherits from Base.V7.Theme.AppCompat.Light whose selectableItemBackground is set to #drawable/abc_item_background_holo_light state list drawable which in turn uses
#drawable/abc_list_selector_background_transition_holo_light to set the #drawable/abc_list_pressed_holo_light as its drawable for the pressed state. The 9-patch image (drawable-hdpi-v4/abc_list_pressed_holo.light.9.png) shows this black borders, which seems to be the ones showing in the app.
I am seeing this behaviour in both an emulator and device (Samsung Galaxy S4) running API 19 (Android 4.4.2)
Any help would be appreciated
I have an app that has a minSdk of 15 and I'm working out all the bugs that came with the lollipop upgrade. Our software is very complex and it dynamically creates views using custom ViewGroups and then an array of elements that are explicitly sized and placed inside the group. I'm running into an issue where for example I'll have a ViewGroup and the first child object is a Button...this button is sized to fill the view (not clickable). The second child is a FrameLayout containing a single view. This single view is a video object. In all prior versions of Android this works just fine. The FrameLayout is layered over the button (that is acting as a background) and the video is inside the framelayout. You can interact with the video without any issues.
Something changed in lollipop - suddenly, even though the button is showing up as the 0 index element, it is laying OVER the rest of the children...so I cannot get to the video underneath. If I remove that button element, the video renders and plays just fine...I have no issues interacting with it.
I ran the app in UI Automator Viewer just to make sure I was really setting up the UI as I expected (keep in mind the entire view is dynamically rendered at runtime using image/video assets and xml config files).
I'm not able to share code since this is proprietary software, but I am working on a little test project to see if I can manually recreate the issue with static objects. Once I get that up and running I'll be sure to update this ticket. For now, here is a screenshot of the hierarchy:
https://goo.gl/photos/a8on9CJDnN66XYnV6
Notice the highlighted object, this is the custom ViewGroup, the children below it are what I am describing above.
Does anyone know of a change in Lollipop that would effect the ordering of things? I found earlier that if you have a disabled object but don't have a disabled state drawable assigned to that object it would become invisible, previous versions just used one of the other state drawables..okay that makes sense and it was very easy to fix, but this object is not invisible...so it must be something different.
Any direction would be greatly appreciated.
~A
UPDATE -- FIXED
With the help of #alanv and #BladeCoder I figured out this functionality was due to the new elevation feature of Material design. I was able to fix my particular issue by first checking what version of android the device was using, and if lollipop, I just add this new property to the button:
android:stateListAnimator="#null"
This prevents my explicit child hierarchy from being overridden by the OS.
Lollipop introduced elevation as a way to position the elements on the Z axis and cast shadows between them depending on their difference of elevation.
Enabled buttons have a default elevation of 2dp (and it increases when you press them). So, your button has a higher elevation than the FrameLayout (0dp by default) so it will be drawn on top of it.
Disabled buttons have an elevation of 0dp. That's why disabling the button solved your issue.
Using buttons as backgrounds looks like a bad idea (why not setting a custom Drawable background on your FrameLayout instead?) but if you really need that, you can disable the button like you did and, just to be sure, enforce its elevation to 0dp. Another workaround is to increase the elevation of the FrameLayout but then it may cast a big shadow under Lollipop if it has a background, and maybe that's not what you want.
Okay, UPDATE! I figured out how to fix the issue, although I'm still not sure (even after pouring over the diffs between several classes in grepcode) what changed in lollipop that is causing a change in how this works.
If the button is enabled...and you are placing it using something equivalent to AbsoluteLayout (We have our own ViewGroup we created called Explicit layout, but it does pretty much the same thing as AbsoluteLayout), it will always be on top of anything else in the stack that isn't also a button of some sort (at least that's what I'm finding...I didn't test through every possible widget).
Setting the button that is acting purely as a background image to enabled=false solves this issue. I know, it doesn't make sense that we use Buttons as background images, but our code uses it for dynamic element creation so there are many possible states and uses for each element.
Anyway, not sure if anyone else would even run into this issue, but just in case you do...here it is.
Thanks!
Background
I've made an "app manager" alternative app, and I wish to add translation for RTL (right to left) languages.
Since I know that as of certain Android version, things got flipped to let words and sentences align correctly, I decided to first switch to such a language and then continue with the translation
The problem
After switching to an RTL language (Hebrew in my case), I've found out that the action bar's up button has the "<" image flipped horizontally:
So now it shows ">" instead.
The question
How do I fix it? It doesn't make sense to see it this way...
What worked for me was to let the system use the default theme, and not specify Holo. If you can live with that, the Up button will be oriented correctly. Unfortunately this cannot be done if you use AppCompat of course.
To make this even more annoying: the flipping of the up button is device specific. It occurs on Samsung devices but not on Google's. The supportsRtl flag is only for API 17 and above, so older Samsung phones cannot be fixed.
The issue is apparently the Holo implementation on Samsung devices. Be careful with flipping the icon since on Google phones it will be flipped wrong.
See this: https://code.google.com/p/android/issues/detail?id=68476
Well, you can access that ActionBar "up" affordance by calling Resources.getIdentifier and View.findViewById. After that you could rotate it.
final int upId = getResources().getIdentifier("up", "id", "android");
final View up = findViewById(upId);
// Call this to just rotate the icon 180°
if (getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
up.setRotation(180f);
}
I use adjustPan to automatically pan my application to make the EditText field visible when the softkeyboard appears. So far this has worked well but in the latest Android 4.4 Kitkat versions the actionbar pans up as usual but a white box is left behind. I've tried debugging this with the Eclipse View Hierarchy tool but it ignores the box. I've also experimented with v19 styling with no luck. This happens on a variety of Kitkat Nexus devices and emulators.
I'm happy to leave the actionbar on screen or remove it completely when the windows pans. Any help would be appreciated removing the box.
I found that this only happens with the applications hardware acceleration is set to true in the manifest file.
I want to keep the hardware acceleration turned on so I wrote this snippet inside my onCreate method to turn it off just the action bar container.
if(Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
Resources res = Resources.getSystem();
int id = res.getIdentifier("action_bar_overlay_layout", "id", "android");
ViewGroup overlayLayout = (ViewGroup) this.findViewById(id);
overlayLayout.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
UPDATE
This issue has been fixed in Android L preview API 20. Please note that the above code will cause an exception in Android L and so the version condition needs to be explicit to Kitkat.
if(Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
I'm currently creating a custom status bar notification to notify the user of progress through an event. I have the custom notification working fine, but having a progress bar requires that I pass my own set of RemoteViews to the notification through the contentView field.
This is fine, except that I want to be able to base this layout off the default one. I am targeting API 10, and so it must work with both Gingerbread and ICS. Gingerbread is fine, as I can just put an icon on the left of the layout and the notification fits in with other default ones. In ICS however, the notification icons all have the striped square on the left that contains the icon (it effectively forms a UI "handle" to help indicate that the notification can be swiped to dismiss it).
Does anyone know how I can either get the default layout in code, and then edit it (this is hard with remoteViews), or somehow get access to default layout view (probably during runtime), then copy it, and substitute the notification text for my progress bar?
I have seen examples where people have created a notification and cloned the layout, but to do anything useful with that you have to know quite a lot about the layout. I would rather get the layout files from the android versions you are interested in. Here you have the JB one, you should not have any problems finding the others.
If the only reason you want a custom layout is to get a progress bar, you could look at
NotificationCompat.Builder.setProgress(). It'll be easier than playing with custom notification layouts. If you do decide to use custom layouts, they changed only slightly between API v14 and API v17, and I have no idea what they're like for Honeycomb but they're unlikely to be much different. What that means is that you should be able to use one custom notification layout in a layout-v11 folder, and one in your default layout folder, and you'll catch most cases (except for the icon background from Honeycomb upwards, I haven't gotten that part working in my own custom notifications yet) and only have to maintain two different layouts. See the answer above for the location of the default layout; note that it's called status_bar_latest_event_content.xml in earlier versions of Android.
Since setProgress() is available from Honeycomb upwards at least, and it looks like it works on earlier versions too (the docs don't say otherwise), then you should probably use that if you don't have any other custom requirements.