xml drawable does not works properly on Lollipop API21 - android

EDITED
Decided to delete all of the previous question, since I made a standalone app just for solving this issue.
Problem: xml drawable does not works properly on API21, when defined as a background of a Button. and works on all other API's. Including API22 which is still Lollipop. really strange..
After making this standalone app, I realize that it might really be an API21 bug related to xml gradients. So in this app I put just a button on it in which I set the background to a drawable xml selector that changes the background drawable file depending on the state of the Button.
From what I could understand was that on API21 it only uses the start color of the gradient.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
>
<Button
android:layout_width="200dp"
android:layout_height="200dp"
android:id="#+id/imageView"
android:background="#drawable/key_pressed_selector"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
background_key_default.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#color/grey"
android:endColor="#color/grey"
/>
<corners android:radius="15dp"/>
background_yellow.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:type="radial"
android:gradientRadius="100"
android:startColor="#color/dark_blue"
android:endColor="#color/yellow"
/>
<corners android:radius="15dp"/>
</shape>
background_pressed_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/background_yellow"
android:state_pressed="true"/>
<item android:drawable="#drawable/background_key_default"/>
</selector>
res/values/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="yellow">#ffff39</color>
<color name="dark_blue">#332ff2</color>
<color name="grey">#b1b2b6</color>
</resources>

Solved! To me there is a bug with this xml attribute android:gradientRadius on version API21.
The way I solved this was to create a drawable-v21 folder and copy all of my xml drawable that have this xml attribute and use one of this appendix: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size), in (inches), mm (millimeters).
While leaving the default drawable folder without appendix.
otherwise I was not able to make it work, when it worked on API21 it didn't on all others API's and when it worked on all others API's it didn't on API21.
To me it worked like this.
ex:
drawable
android:gradientRadius="110"
drawable-v21
android:gradientRadius="55%p"

you do not have to override onTouch() method
simply try giving your selector xml file to the button's background.
EXAMPLE
<Button
android:id="#+id/id_Login_login_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="#drawable/your_selector_xmlfile"
android:text="Login" />

Related

centered element in background doesn't match centered element in foreground

I'm working on an Android application where I want to create a windowBackground with a centered element and a layout also with a centered element. I want these elements to be in the exact same position, with the layout overlapping the background. The problem I'm having is that the layout and the background seem to be calculating center differently (see image). Why is this happening, and what can I do to line the elements up?
This is what I see right now. The red box is created by the background and the green box is created by the foreground. Screenshot was created with a Nexus 5X API 26 emulator.
Foreground layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:background="#color/foreground_box"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_centerInParent="true" />
</RelativeLayout>
Background Drawable (applied via android:windowBackground in my theme)
<?xml version="1.0" encoding="UTF-8" ?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/background" />
<item android:gravity="center">
<shape
android:gravity="center"
android:shape="rectangle">
<solid android:color="#color/background_box" />
<size android:width="10dp"
android:height="10dp" />
</shape>
</item>
</layer-list>
For clarity, my colors file is
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<color name="background">#ffffff</color>
<color name="background_box">#AAFF0000</color>
<color name="foreground_box">#AA00FF00</color>
</resources>
Full source for this sample project is available at https://github.com/HofmaDresu/AndroidCenteredTest
The reason windowBackground includes both the heights 1) statusBar and 2) actionBar
Modify below line in your background.xml
<item android:gravity="center" android:top="80dp"> // 56 actionBarSize + 24 statusBarHeight
You may need to manage this programatically as statusBarHeight and actionBarSize varies based on device API/resolution.
Here is the result. For testing, have resized background size bit bigger so that overlapping between views and background become visible.
It is probably because of the extra space taken up by the ActionBar in the foreground.
To fix this, you can add a margin to your View in the foreground layout as:
android:layout_marginBottom="?android:attr/actionBarSize"
After test it in AS, I can say you that the right code for you background_drawable is this:
<?xml version="1.0" encoding="UTF-8" ?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/background" />
<item android:gravity="center" android:bottom="48dp">
<shape
android:gravity="center"
android:shape="rectangle">
<solid android:color="#color/background_box" />
<size
android:width="10dp"
android:height="10dp" />
</shape>
</item>
using android:top, the red square go more down than center. Need to use android:bottom instead to center background. By my tests results that 48dp is the right value.

How to make a ripple effect over a linear layout, without overriding the background color on its children?

I have a LinearLayout that looks like this.
I want each row to be clickable. The LinearLayout code for a row looks like this:
<LinearLayout
style="#style/home_menu_item_container"
android:id="#+id/home_menu_acronyms_button"
>
<ImageView
style="#style/home_menu_item_left"
android:background="#color/greyLight"
/>
<TextView
style="#style/home_menu_item_right"
android:text="#string/home_menu_option_2"
android:background="#color/grey"
/>
</LinearLayout>
How can I add a ripple effect that expands over the entire row (parent) - not just one child view in the row? The tricky part here is to let the ripple go over the two colored row.
So far, I found out the easiest way to do so is define a <ripple> in your drawable and then set the background of the LinearLayout to this drawable resource.
Define your drawable-v21/item_selector.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/your_background_color">
<item android:id="#android:id/mask"
<!--color here doesn't matter-->
android:drawable="#android:color/white" />
</ripple>
Set the background of your LinearLayout to drawable/item_selector.
<LinearLayout
style="#style/home_menu_item_container"
android:background="#drawable/item_selector"
android:id="#+id/home_menu_acronyms_button" >
...
</LinearLayout>
Besides, if you don't have your own background color, then there is no need to define a item_selector at all. You can simply define background as android:background="?android:attr/selectableItemBackground" for your LinearLayout.
It is a little bit complicated for that what you need but I don't think there is another way,...
You need to put your ImageView's into a ListView so that every ImageView is a ListItem and then you can set the ripple but you also need to set drawSelectorOnTop="true" otherwise it won't work correctly
I too faced this problem, finally found a simple solution
In linear Layout just add android:clickable="true";
and set background with ur ripple effect as
android:background="#drawable/ripple_effect"
code:
<LinearLayout
android:clickable="true"
android:background="#drawable/ripple_effect"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Add your child views here -->
</LinearLayout>
add ripple_effect.xml in drawable
ripple_effect.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="#f87d05c2"
tools:targetApi="lollipop">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#f87d05c2" />
</shape>
</item>
</ripple>
<RelativeLayout
android:id="#+id/rll_privacy_policy"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical">
<TextView
android:id="#+id/txt_privacy_policy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/layout_margin_16"
android:text="#string/privacy_policy"
android:layout_centerVertical="true"
android:textColor="#color/link_acc"
android:textSize="#dimen/txt_title_20" />
</RelativeLayout>
Another option is to make the ripple's background color transparent. This way only the ripple can be seen. The ripple's xml file (in your drawable-v21/ folder) is thus:
<-- Ripple in some ghastly color, like bright red so you can see it -->
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/red"
>
<!-- background color uses a transparent mask set to full #ffffff (white) -->
<item
android:id="#android:id/mask"
android:drawable="#android:color/white"
/>
Note that if you are supporting pre-lollipop devices, you need to have a dummy file with the same name in your drawable/ folder. An empty selector is sufficient for that file. And remember that those older devices will not ripple.
answer above dont work for me,
here is my solution:
ripple.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
>
...put het your design
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/ripple" />
</FrameLayout>

Inset drawable not working as described in documentation

As described on Android Developer site:
A drawable defined in XML that insets another drawable by a specified
distance. This is useful when a View needs a background that is
smaller than the View's actual bounds.
http://developer.android.com/guide/topics/resources/drawable-resource.html#Inset
Instead of just moving the background and leaving the content in place in my case the inset is also moving the TextView.
This is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg_inset"
android:orientation="horizontal" >
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some text"
android:textSize="23sp" />
</LinearLayout>
This is the bg_inset drawable
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#android:color/darker_gray"
android:insetLeft="100dp" />
And this is the result I get:
By default, setting a background drawable also applies that drawable's padding to the view. Set the padding explicitly if you don't want it to match the background drawable.
Try to use shape with left-padding instead of inset:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#android:color/darker_gray"/>
<padding android:left="100dp"/>
</shape>
Another option: if you want to use DP instead of PX, try my suggestion below. From my experience, InsetDrawable only works with pixels, which I find... unhelpful. To be honest, I am not happy with this solution, but hey, it works.
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="10dp"
android:drawable="#drawable/image_placeholder"
android:top="10dp" />
</layer-list>

How to create ripple effect in simple layout

How can I have a ripple effect in a simple linear/relative layout when touching the layout?
I've tried setting the background of a layout to something like:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight" >
<item android:drawable="#android:color/white"/>
</ripple>
However I'm only seeing a plain white background and no ripple effect when touching the layout. What am I doing wrong?
Edit:
For reference, here is my layout xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="250dp"
android:layout_height="250dp"
android:background="#drawable/test"
android:clickable="true">
</RelativeLayout>
Set these properties on your layout (if your layout has the default white/light background):
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
You don't need a custom drawable in this case.
However, if your layout has a black/dark background, you'd have to create your own ripple drawable like this one:
<?xml version="1.0" encoding="utf-8"?>
<!-- An white rectangle ripple. -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#android:color/white">
<item
android:id="#android:id/mask"
android:gravity="center">
<shape android:shape="rectangle">
<solid android:color="#android:color/white"/>
</shape>
</item>
</ripple>
And then set this ripple drawable as your android:background property.
You can see many examples of these types of ripples in AOSP: in here
I'm adding this in addition to Igor Ganapolsky's answer in case anyone wants to have a layout with different color and also have a ripple effect. You simply create a ripple effect in drawables like this:
ripple.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="#color/rippleColor"
tools:targetApi="lollipop"> <!-- ripple effect color -->
<item android:id="#android:id/background">
<shape android:shape="rectangle">
<solid android:color="#color/backgroundColor" /> <!-- background color -->
</shape>
</item>
</ripple>
then give it as your layout's background or any button as Igor Ganapolsky mentioned in his answer.
android:clickable="true"
android:background="#drawable/ripple"
You have to alter following code snippet in any widget(TextView/Button) and you can implement Ripple Effect:
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
And you are good to go.
It turns out this is working as intended. The standard Material theme colorControlHighlight value is #40ffffff. So on a white background, this will not show up. Changing the highlight color to something else works, and/or changing the background color of the object.
Thanks all (especially Alanv for pointing me in the right direction).
This is an example for clicking on a sample layout with ripple effect :
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
Set android:clickable="true" on your layout.
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="#cfd8dc"
tools:targetApi="lollipop">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#d1c4e9" />
</shape>
</item>
</ripple>
Use this ripple.xml in Drawable folder, then assign it as View's
android:background="#drawable/ripple"
android:clickable="true"
Simply add default ripple effect with android:background="?selectableItemBackground"
Like:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="?selectableItemBackground"
android:clickable="true"
>
...
</LinearLayout>
Put this into your layout:
android:clickable="true"
android:background="?attr/selectableItemBackground"
Note: There is a bug in API documentation. It will work only on API >= 23
For all API levels use this Solution
I tries all those answers and nothing worked to me, so, I solved creating the following style:
<style name="Button.Borderless" parent="Base.Widget.AppCompat.Button.Borderless">
<item name="android:minHeight">0dp</item>
<item name="android:minWidth">0dp</item>
<item name="android:layout_marginLeft">-6dp</item>
<item name="android:layout_marginRight">-6dp</item>
<item name="android:paddingTop">0dp</item>
<item name="android:paddingBottom">0dp</item>
<item name="android:paddingLeft">6dp</item>
<item name="android:paddingRight">6dp</item>
</style>
And then, I applied to my linear layout:
<LinearLayout
android:id="#+id/ll_my_ripple"
style="#style/Button.Borderless">
</LinearLayout>
To make a circlar effect use the below code:
android:clickable="true"
android:background="?attr/selectableItemBackgroundBorderless"

Creating an Activity with the same background than ICS settings / Preferences

I am working on an app for ICS and I would like my Activity to have the same background than the settings, with the cool gradient.
I tried Theme.DeviceDefault and some other, but I cannot get it.
Is that possible or should I forget?
It is relatively simple to create this app background directly yourself.
drawable/app_background_ics.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="270"
android:startColor="#color/ics_background_start"
android:endColor="#color/ics_background_end"
android:type="linear" />
</shape>
values/colors.xml
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<color name="ics_background_start">#ff020202</color>
<color name="ics_background_end">#ff272D33</color>
</resources>
Then add the app_background_ics drawable as a background to your main view (in this example ListView).
Do not forget a transparent android:cacheColorHint in order to avoid a black background when scrolling in the ListView
<ListView android:id="#+id/video_list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:dividerHeight="2dip"
android:background="#drawable/app_background_ics"
android:cacheColorHint="#00000000"/>
Did you try Theme.Holo.Dark?
I needed 2 things:
<uses-sdk android:targetSdkVersion="11"/>
<application
android:hardwareAccelerated="true"
(...)/>
Works fine now..

Categories

Resources