Spinner inner padding is larger on Android 6.0.1 - android

Intro:
With the new release of Android 6.0.1, seems like Android made some changes on the Spinner component because by default, the inner padding around the down carrot is a bit bigger.
I noticed this on an app where I haven't modified anything in the code, but simply updated the OS on the device and yet the spinners have different sizes.
Situation:
I have 2 spinners one next to the other in a RelativeLayout(mind the rest of the components, I added everything so you can see this part of the layout - removed the totally unnecessary properties or view ids)
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/container_for_buttons_on_the_right"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true">
<!-- Buttons here-->
</LinearLayout>
<android.support.v7.widget.AppCompatSpinner
android:id="#+id/spinner_1"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<ViewSwitcher
android:id="#+id/spinner_switch"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_toEndOf="#id/spinner_1"
android:layout_toLeftOf="#id/container_for_buttons_on_the_right"
android:layout_toRightOf="#id/spinner_1"
android:layout_toStartOf="#id/container_for_buttons_on_the_right"
android:inAnimation="#anim/fade_in"
android:outAnimation="#anim/fade_out">
<android.support.v7.widget.AppCompatSpinner
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- ImageView properties are incomplete but I need it there.-->
</ViewSwitcher>
</RelativeLayout>
The layout used by the Spinner adapter for the getView() method is this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:ellipsize="end"
android:gravity="center_vertical"
android:singleLine="true"
tools:text="Test" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0"
android:gravity="center"
android:paddingLeft="4dp"
android:singleLine="true"
android:textColor="#color/text_primary"
android:textSize="#dimen/text_size_body"
tools:ignore="RtlHardcoded,RtlSymmetry"
tools:text="7%" />
</LinearLayout>
Exemplified:
The screenshot is combined of 2 separate screenshots taken:
The one on the top is taken on a Nexus 5 device running on Android 6.0
The one below is also taken on a Nexus 5 device BUT running on Android 6.0.1
EDIT 1
Using AppCompatSpinner from the support library does not change the behaviour. Support library version used is 23.1.1

With minimal effort I was able to fix this by building a custom background for the spinner.
Using AppCompatSpinner I had to create 2 xmls for the background, let's call this spinner_background.xml:
1. First one goes to the drawable folder and looks like this, spinner_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:opacity="transparent">
<item
android:width="24dp"
android:height="24dp"
android:drawable="#drawable/selector_background_borderless"
android:gravity="end|center_vertical" />
<item android:drawable="#drawable/bg_spinner_anchor" />
</layer-list>
Where selector_background_borderless is a plain selector like(I added the minimal items you need, you could explore it's ripple alternative for v21+. In fact I would recommend you to do so):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#19000000" android:state_pressed="true" />
<item android:drawable="#android:color/transparent" />
</selector>
And bg_spinner_anchor is a 9patch PNG for the caret. I used these assets: bg_spinner_anchor
2. The second one goes to the drawable-v23 folder to properly support ripple and looks like this, spinner_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingEnd="16dp"
android:paddingLeft="0dp"
android:paddingMode="stack"
android:paddingRight="0dp"
android:paddingStart="0dp">
<item
android:width="24dp"
android:height="24dp"
android:drawable="#drawable/selector_background_borderless"
android:gravity="end|center_vertical" />
<item
android:width="24dp"
android:height="24dp"
android:drawable="#drawable/ic_spinner_caret"
android:gravity="end|center_vertical" />
</layer-list>
Where ic_spinner_caret is a vector used from the Android source code looking like this. You should add also add this to your drawable-v23 folder:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:pathData="M7,10l5,5,5-5z"
android:fillColor="#524e4a"/>
</vector>
Credits go to alanv from the Android UI toolkit for Guidance!

I had the same issue and my plan was to rollback the 6.0.1 update for v23 only.
Make sure your Spinner has a style attached to it. For example style named as Widget.Spinner in example below:
<Spinner
android:id="#+id/spinner_1"
style="#style/Widget.Spinner"
android:layout_width="64dp"
android:layout_height="64dp"/>
Create (if already does not exist) styles.xml under values-v23 directory (for changes will be applied to API v23 only). For example, see Widget.Spinner style definition example below:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Widget.Spinner" parent="Widget.AppCompat.Spinner">
<item name="android:background">#drawable/spinner_background_material</item>
</style>
</resources>
The style's parent is Widget.AppCompat.Spinner and it redefines it's android:background with the one we will be rolling back from 6.0.1 source.
Note, that if you're targeting other versions too, you will need to add a default styles.xml under values directory with entry
<style name="Widget.Spinner" parent="Widget.AppCompat.Spinner"/>
for it is easier to define another generic style rather than different layout xml files and your project should have a generic styles.xml under values directory anyway, right? :)
Bring in spinner_background_material.xml from https://android.googlesource.com/platform/frameworks/base.git/+/android-6.0.1_r3/core/res/res/drawable/. Save it under drawable-v23 for again, we will just make sure we're changing API v23 only.
File's default content is:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack"
android:paddingStart="0dp"
android:paddingEnd="48dp"
android:paddingLeft="0dp"
android:paddingRight="0dp">
<item
android:gravity="end|fill_vertical"
android:width="48dp"
android:drawable="#drawable/control_background_40dp_material" />
<item
android:drawable="#drawable/ic_spinner_caret"
android:gravity="end|center_vertical"
android:width="24dp"
android:height="24dp"
android:end="12dp" />
</layer-list>
Now, this is the file you might want to tweak. I made changes to this file for tweaking the caret position:
a) set layer-list's android:paddingEnd equal to 0dp
b) halved first item's android:width to 24dp
c) removed the second item's android:end attribute
The changes made background thinner, by stripping it's sides but the approach retained the ripple effects. Feel free to play around with your own custom values, if needed.
Changes above will not compile as more files are needed to be brought in for they will be reffered by the files above.
Download into drawable-v23 (see link above):
a) control_background_40dp_material.xml
b) ic_spinner_caret.xml
Download into color-v23:
a) control_highlight_material.xml from https://android.googlesource.com/platform/frameworks/base.git/+/android-6.0.1_r3/core/res/res/color/ (this file can probably reside under drawable-v23 too, but lets follow the pattern of original source locations for now). Note, that file's #dimen/highlight_alpha_material_colored is picked up from appcompat-v7, if you use one :) If not, you can reffer it's value from it:
<item format="float" name="highlight_alpha_material_colored" type="dimen">0.26</item>
The solution is not the best as you need to bring over files you don't originally own. Also, you might want to monitor the possible updates to v23 for any future changes. But at least the changes are contained to v23 only.

Related

best way to manage filters with a custom style

I work on an Android app and I need to implement filters based on the app design guidelines.
There are 2 kinds of filters:
with an icon
without an icon
The filter can be selected/unselected (or checked/unchecked)
Each case can be visible here:
There filters will be displayed through a GridView by 3 columns on several lines.
I would like to know which native control is more appropriate to achieve this?
I've tried to use Chip, which has a checked parameter, but it seems not possible to change the chipIcon position.
I've also tried tried the Button, which allows to change the icon position with app:iconGravity, but there is no checked parameter.
I've also seen ToggleButtons but it requires to use MaterialButtonToggleGroup, whereas I need to display each filter trough the GridView.
So do I need to create a custom control to achieve this?
You can use a ToggleButton with a top drawable as follows:
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_selector"
android:checked="false"
android:drawableTop="#drawable/car"
android:drawablePadding="8dp"
android:drawableTint="#drawable/icon_text_colors"
android:padding="8dp"
android:textColor="#drawable/icon_text_colors"
android:textOff="Car wash"
android:textOn="Car wash"
android:textSize="14sp" />
where background_selector.xml is
<selector>
<item android:drawable="#android:color/darker_gray" android:state_checked="true"/>
<item android:drawable="#android:color/holo_blue_light" />
</selector>
and icon_text_colors.xml looks like this:
<selector>
<item android:color="#android:color/white" android:state_checked="true"/>
<item android:color="#android:color/black" android:state_checked="false"/>
</selector>
The unchecked state looks like this:
while the checked state looks like this:
For the button without the icon, you simply would not specify a drawable for the top.
These are not the colors you want, but this is the idea.
I've finally achieved this with a MaterialButton and the android:checkable property:
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.button.MaterialButton
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/CheackableCell"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:icon="#drawable/ic_carwash"
app:iconGravity="textTop"
app:iconPadding="12dp"
tools:text="Car Wash"
android:textAlignment="gravity"
android:gravity="top|center"
android:paddingBottom="4dp"
android:checkable="true"/>
It's very close to solution given by Cheticamp.

Button is not filling parent container height [duplicate]

Currently, I have the following bottom log in button.
When button is not being pressed
When button is being pressed
The XML looks like this
<LinearLayout
android:background="?attr/welcomeBottomNavBarBackground"
android:orientation="horizontal"
android:id="#+id/sign_in_bottom_nav_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
style="?android:attr/buttonBarButtonStyle"
android:id="#+id/sign_in_button"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="1.0"
android:layout_height="48dp"
android:gravity="center"
android:layout_gravity="center"
android:enabled="true"
android:textAllCaps="true"
android:text="#string/log_in" />
</LinearLayout>
I would like to remove the padding (Or should I call it margin? Please refer to my bottom most p/s section) around button when it is being pressed.
I look at How to remove padding around buttons in Android?
I had tried
<Button
...
...
android:minHeight="0dp"
android:minWidth="0dp" />
It doesn't work and has no effect.
I further try
<Button
...
...
android:background="#null"
android:minHeight="0dp"
android:minWidth="0dp" />
No more padding when pressed. However, the material designed pressed visual effect will gone too.
May I know what is the best way to remove button padding during pressed, yet retain the material designed pressed visual effect?
P/S
I don't really know whether I should call it padding or margin. What I wish to achieve is that, when we press on the bottom region, press visual effect change should be covered entire 100% bottom bar region (#+id/sign_in_bottom_nav_bar), instead of current 95% bottom bar region.
A standard button is not supposed to be used at full width which is why you experience this.
Background
If you have a look at the Material Design - Button Style you will see that a button has a 48dp height click area, but will be displayed as 36dp of height for...some reason.
This is the background outline you see, which will not cover the whole area of the button itself.
It has rounded corners and some padding and is supposed to be clickable by itself, wrap its content, and not span the whole width at the bottom of your screen.
Solution
As mentioned above, what you want is a different background. Not a standard button, but a background for a selectable item with this nice ripple effect.
For this use case there is the ?selectableItemBackground theme attribute which you can use for your backgrounds (especially in lists).
It will add a platform standard ripple (or some color state list on < 21) and will use your current theme colors.
For your usecase you might just use the following:
<Button
android:id="#+id/sign_in_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Login"
android:background="?attr/selectableItemBackground" />
<!-- /\ that's all -->
There is also no need to add layout weights if your view is the only one and spans the whole screen
If you have some different idea on what your background should look like you have to create a custom drawable yourself, and manage color and state there.
As simple, use the inset property like:
android:insetTop="0dp"
android:insetBottom="0dp"
android:insetRight="0dp"
android:insetLeft="0dp"
In styles.xml
<style name="MyButtonStyle" parent="Base.Widget.AppCompat.Button">
<item name="android:background">#drawable/selector</item>
<item name="android:textColor">#android:color/black</item>
</style>
In values/drawable:
my_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2dp" />
<!-- specify your desired color here -->
<solid android:color="#9e9b99" />
</shape>
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:drawable="#drawable/my_drawable"/>
<item android:state_pressed="true" android:drawable="#drawable/my_drawable"/>
<item android:drawable="#android:color/transparent"/>
</selector>
In values/drawable-v21:
my_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
android:tint="?attr/colorButtonNormal"
xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2dp" />
<solid android:color="#android:color/white" />
</shape>
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:id="#android:id/mask"
android:drawable="#drawable/my_drawable" />
</ripple>
In layout:
<Button
android:id="#+id/button"
style="#style/MyButtonStyle"
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="Test"/>
Result on API 19:
Result on API 21:
Source code
I think the best solution to solve that is create your own Ripple Effect. The padding when you press the button is respecting the default Ripple Effect of the component.
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:drawable="?attr/colorPrimary"/>
</ripple>
Or you can try change the style of your button to style="?android:textAppearanceSmall"
Remember: This effect is only shown on Android Lollipop (API 21) or higher.
I have been through what you are going through. Long story short, you just cannot do it cleanly with a <Button> tag alone, while ensuring backwards compatibility.
The simplest and the most widely practiced method is to use a <RelativeLayout> underlay, around a <Button>.
Button Code:
<RelativeLayout
android:id="#+id/myButtonUnderlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:visibility="visible">
<Button
android:id="#+id/myButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:text="I am as cute as a Button"/>
</RelativeLayout>
Wherever you need to use a button, you use this complete code.
Here is the breakdown:
OnClick events will be hooked to myButton.
Control dimensions of your button, by changing attributes of myButtonUnderlay.
In myButton, android:background="?attr/selectableItemBackgroundBorderless". This will make it a transparent button with just the text, and backwards compatible ripples.
In myButtonUnderlay, you will do all the other background applications, like setting the color of the button, margins, paddings, borders, gradients, and shadows etc.
If manipulation of the button's visibility (programmatic or not) is wish, you do it on myButtonUnderlay.
Note: To ensure backwards compatibility, make sure that you use
android:background="?attr/selectableItemBackgroundBorderless", and NOT
android:background="?android:attr/selectableItemBackgroundBorderless"
As #David Medenjak answer you can read the Google Material design Button-style to its developer site. Use button style as #David Medenjak explained in his answer. You can also do by the following way also
It is not a padding or margin but it is actually background effect of button.
If you want to remove that then you can do as following.
Option 1:
Step 1: Put the below code in styles.xml
<style name="myColoredButton">
<item name="android:textColor">#FF3E96</item>
<item name="android:padding">0dp</item>
<item name="android:minWidth">88dp</item>
<item name="android:minHeight">36dp</item>
<item name="android:elevation">1dp</item>
<item name="android:translationZ">1dp</item>
<item name="android:background">#FF0000</item>
</style>
Step 2:Create a new XML file under drawables folder and add the following code: I named my XML file as button_prime.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/colorPrimary">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="1dp" />
<solid android:color="#8B8386" />
</shape>
</item>
</ripple>
Step 3: Use the style and drawable in your Button as follows.
<Button
style="#style/myColoredButton"
android:layout_width="250dp"
android:layout_height="50dp"
android:text="Cancel"
android:gravity="center"
android:background="#drawable/button_prime"
android:colorButtonNormal="#3578A9" />
Option 2:
With the Support Library v7, all the styles are actually already defined and ready to use, for the standard buttons, all of these styles are available.So you can set your button style like this
<Button
style="#style/Widget.AppCompat.Button.Borderless"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="BUTTON"
android:gravity="center"
android:minHeight="0dp"
android:minWidth="0dp"
android:background="#color/colorAccent"/>
For more detail of Button style please check this answer
I think you will check this answer also. I hope you will get your solution.
The padding and margin may be a result of the original resources used in the button.
So you could try to change the resources used, using a selector:
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/btn_action_hover" />
<item android:state_selected="true" android:drawable="#drawable/btn_action_hover" />
<item android:state_focused="true" android:drawable="#drawable/btn_action_hover" />
<item android:drawable="#drawable/btn_action_normal" />
</selector>
That would change the default images/shapes for your buttons, so you could try using drawables and set every item to a drawable. The drawable being either a bitmap, or a .xml file(style file) defining the look of the button in its current state. I assume there still are some native styles included even though you have set the button-style yourself. This may be because you aren't using a custom theme. So the issue may also be solved by defing
theme="#style/myNewTheme"
where myNewTheme is your theme, and it should have any parents(parent="" should not be defined).
Take any given theme(designed by Google/Android, for an instance Theme.AppCompat.[name]), it does also come with a buttonStyle. This is a part of Theme.Holo.Light:
<!-- Button styles -->
<item name="buttonStyle">#style/Widget.Holo.Light.Button</item>
<item name="buttonStyleSmall">#style/Widget.Holo.Light.Button.Small</item>
<item name="buttonStyleInset">#style/Widget.Holo.Light.Button.Inset</item>
<item name="buttonStyleToggle">#style/Widget.Holo.Light.Button.Toggle</item>
<item name="switchStyle">#style/Widget.Holo.Light.CompoundButton.Switch</item>
<item name="mediaRouteButtonStyle">#style/Widget.Holo.Light.MediaRouteButton</item>
<item name="selectableItemBackground">#drawable/item_background_holo_light</item>
<item name="selectableItemBackgroundBorderless">?attr/selectableItemBackground</item>
<item name="borderlessButtonStyle">#style/Widget.Holo.Light.Button.Borderless</item>
<item name="homeAsUpIndicator">#drawable/ic_ab_back_holo_light</item>
As you see, this theme defines how your buttons will look/work in basic features. You can override parts of it, but you haven't overridden the important parts(being buttonStyle and similar). So if you create a new theme yourself and style it to your liking and set the theme(using theme="themename") and that theme does not inherit any theme, you should be able to style your buttons to your liking without having to worry about the default styles in the theme
Basically:
calling padding/margin="0dp" will not help. The default drawable defined by the theme has this in the button drawable, meaning you cannot change it. So you have to either change the button style, or change the theme completely. Make sure that theme does not have any parents, because many themes define the button style. You do not want the button style defined by the theme.
The best solution these days is just to use MaterialButton in place of Button.
Note: MaterialButton is visually different from Button and AppCompatButton. One of the main differences is that AppCompatButton has a 4dp inset on the left and right sides, whereas MaterialButton does not. To add an inset to match AppCompatButton, set android:insetLeft and android:insetRight on the button to 4dp, or change the spacing on the button’s parent layout.
When replacing buttons in your app with MaterialButton, you should inspect these changes for sizing and spacing differences.
Source: https://material.io/develop/android/components/material-button/
I'd suggest you taking a look at this just in case before all.
Then, if not working i'd suggest you to create your own style (like azizbekian suggest)using android xml drawables, and drawable states to differentiate pressed/notpressed.
I think using your own style may be the best answer as it will further give you more control on how your app is displaying, but using android default themes and styles also allows the user to have custom styles which is a good idea. However, you cannot test every custom style so you cannot check that your app will display correctly on ALL custom styles, and therefore may encounter problems with some.
Set the Button background as android:background="?selectableItemBackground"
<LinearLayout
android:background="?attr/welcomeBottomNavBarBackground"
android:orientation="horizontal"
android:id="#+id/sign_in_bottom_nav_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
style="?android:attr/buttonBarButtonStyle"
android:background="?selectableItemBackground"
android:id="#+id/sign_in_button"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="1.0"
android:layout_height="48dp"
android:gravity="center"
android:layout_gravity="center"
android:enabled="true"
android:textAllCaps="true"
android:text="#string/log_in" />
</LinearLayout>
After trying lots of solution, Finally I came to a conclusion that with tag alone we can't achieve this. to remove this unwanted space around button my solution is as below:
<RelativeLayout
android:id="#+id/myButtonUnderlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:visibility="visible">
<Button
android:id="#+id/save_button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="-5dp"
android:layout_marginBottom="-5dp"
android:layout_above="#+id/content_scrollview"
android:layout_gravity="bottom"
android:background="#drawable/ripple_theme"
android:enabled="true"
android:text="SetUp Store"
android:textColor="#fff"
android:textSize="18sp"
android:visibility="gone"
tools:visibility="visible"
style="#style/MediumFontTextView" />
</RelativeLayout>
1.add a drawable resource file named maybe button_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#ff0000"/>
<stroke android:width="5dp" android:color="#00ff00"/>
</shape>
</item>
<item>
<shape>
<solid android:color="#00ff00"/>
</shape>
</item>
</selector>
2.Use the button_background.xml as the button background, done!
github
blog
I don't really know whether I should call it padding or margin.
The button is enacting surface elevation for providing visual feedback in response to touch. It is one of two feedbacks used for surface reaction; the first one being the ripple effect. For example, a raised button has resting state elevation of 2dp and pressed state elevation of 8dp (See raised button under Shadows). The button meets the finger as it touches the surface.
May I know what is the best way to remove button padding during pressed, yet retain the material designed pressed visual effect?
Having answered the first part, I do not believe you are having all of the material design if you wish to remove the surface elevation effect.
Anyways, here is how to remove surface elevation visual feedback:
Add animator file button_raise.xml to animator directory under res directory having the following code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="true"
android:state_pressed="true">
<objectAnimator
android:duration="#android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueTo="0dp"
android:valueType="floatType" />
</item>
</selector>
Refer newly created animator in the button using stateListAnimator property:
<Button
...
android:stateListAnimator="#animator/button_raise"
... />
Hope this helps.

How to change background color of popup-keyboard for android soft keyboard?

It took me a long time to figure out how to get rid of the ugly black default and color my custom keyboard.
I worked from this very helpful answer and I can now color my keyboard nicely:
How to change background color of key for android soft keyboard?
Just the popup-keyboards are still in the default colors.
I found another helpful answer, which took me almost to a solution. But the answer is focusing on the creation and preview of the popups:
Creating a SoftKeyboard with Multiple/Alternate characters per key
#Graeme has mentioned
If you want to change the layout/style of the popup (which defaults to #android:layout/ keyboard_popup_keyboard.xml) you can specify a android:popupLayout attribute which points to a layout file
So I have made my own version of keyboard_popup_keyboard.xml and put it next to my main layout file input.xml into /res/layout and made a reference to it, like in the example given.
<org.gasana.android.aniikeyboard.LatinKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/keyboard"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:keyBackground="#drawable/samplekeybackground"
android:keyTextColor="#000000"
android:popupLayout="#layout/popup"
/>
Sadly there was no example for the popupLayout file. So I copied the original file all the way up from
C:\Users\martin\AppData\Local\Android\sdk\platforms\android-28\data\res\layout\keyboard_popup_keyboard.xml
and tried to tweak it as popup.xml to use the same background as my main keyboard:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/samplekeybackground"
>
<android.inputmethodservice.KeyboardView
android:id="#android:id/keyboardView"
android:background="#drawable/samplekeybackground"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:popupLayout="#layout/popup"
android:keyTextSize="22sp"
tools:ignore="ResourceCycle" />
<ImageButton android:id="#android:id/closeButton"
android:background="#drawable/samplekeybackground"
android:src="#drawable/btn_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="8dp"
android:clickable="true"
/>
My keyboard still builds and creates a working APK. Just the color of the popups is still the ugly default.
Context: I am a linguist, not a developper. I made this custom keyboard for a minority language with a special alphabet and tone-markers and have it free on the Play Store. It works. But people are hesitating, because of the aweful color-design. As soon as I get the popups colored, I will publish a fresh version. Thank you.
Since no answer was coming here for two months, I took time for more poking and guessing. Now I got lucky today and want to be nice to the next linguist, who also needs a custom keyboard and needs to work from examples:
mykeyboard.java is pointing to the layout file for the main keyboard so (third line "input"). I just give a three line quote:
#Override public View onCreateInputView() {
mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
R.layout.input, null);
So inside my \res\layout\input.xml I added the reference to my popup-layout:
<org.my.project.here.LatinKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/keyboard"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:keyBackground="#drawable/samplekeybackground"
android:keyTextColor="#000000"
android:popupLayout="#layout/popup" <!-- here it is -->
/>
And my \res\layout\popup.xml looks like this; I believe I copied it from the provided sample project. Today I just changed the two marked lines for light blue background colour and for black text colour and that finally did the trick. Seems I had looped references earlier but no error messages, just the ugly black default layout.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/samplekeybackground">
<android.inputmethodservice.KeyboardView
android:id="#android:id/keyboardView"
android:background="#color/colorPrimary"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:keyTextSize="22sp"
android:keyBackground="#drawable/samplekeybackground" <!-- here it is -->
android:keyTextColor="#000000" <!-- and here -->
tools:ignore="ResourceCycle"/>
<ImageButton android:id="#android:id/closeButton"
android:background="#android:color/transparent"
android:src="#drawable/btn_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="8dp"
android:clickable="true"/>
The mentioned samplekeybackground.xml is just a very simple definition, pointing to two actual xml-colour-defintions:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Non focused states -->
<item
android:state_focused="false"
android:state_selected="false"
android:state_pressed="false"
android:drawable="#drawable/normal" />
<!-- Pressed state -->
<item
android:state_pressed="true"
android:drawable="#drawable/pressed" /></selector>
And just to be complete, because I appreciate stuff I can just copy and play with for testing, here is the normal.xml; the pressed.xml is the same, just a darker blue:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="1dp" android:color="#A1B7F7" />
<solid android:color="#C7D4FA"/>
</shape>
All this is from guessing and building many versions until I got lucky. Can probably not answer any follow-up questions, but it does work:

How to convert layout to drawable for use in splash screen

Background information
When a user enters my Android application. They are first taken to LoginActivity. LoginActivity takes some time to load as it is also responsible for performing background sqlite migrations as well as other housekeeping tasks (this takes 500-1000ms).
Unfortunately, the user sees a blank screen during this entire time. As setContentView has not executed yet.
I am trying to remediate this problem by following the guides
https://android.jlelse.eu/launch-screen-in-android-the-right-way-aca7e8c31f52
https://www.bignerdranch.com/blog/splash-screens-the-right-way/
They tell me I need to create a background_splash.xml in drawables and point to it using a custom style with <item name="android:windowBackground">#drawable/background_splash</item>
Unfortunately I noticed that I am not able to control padding margin width height, gravity of my logo in drawables.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#color/gray"/>
<!-- cant control android:margin=... (my min API is 21) -->
<!-- cant control android:width=... (my min API is 21) -->
<!-- cant control android:height=... (my min API is 21) -->
<item>
<bitmap
android:gravity="center"
android:src="#mipmap/ic_launcher"/>
</item>
</layer-list>
My problem
How to properly achieve same behavior (or at least similar) as my current activity_login.xml file and convert that into a drawable?
My code
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/material_red_500">
<!--***********************************************************
* Layout section: The login logo
************************************************************-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<android.support.v7.widget.AppCompatImageView
android:layout_centerInParent="true"
android:src="#drawable/image_symbol_lock"
android:scaleType="fitCenter"
android:layout_width="150dp"
android:layout_height="150dp"/>
</RelativeLayout>
<!--***********************************************************
* Layout section: The login button (facebook)
************************************************************-->
<android.support.v7.widget.AppCompatTextView
android:id="#+id/button_facebook"
android:paddingTop="28dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingBottom="28dp"
android:background="#color/material_blue_500"
android:text="LOG IN"
android:textSize="32sp"
android:textColor="#color/white"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v7.widget.LinearLayoutCompat>
You can create a layout_splash with your own design and in the Splash style only set a background color. So first you will see the background color and not the blank and next see the layout. You could do this with the login activity.

Adding Ripple Effect to RecyclerView item

I am trying to add Ripple Effect to RecyclerView's item. I had a look online, but could not find what I need. I assume it has to be a custom effect. I have tried android:background attribute to the RecyclerView itself and set it to "?android:selectableItemBackground" but it did not work.:
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:clickable="true"
android:background="?android:selectableItemBackground"
android:id="#+id/recyclerView"
android:layout_below="#+id/tool_bar"/>
This is the RecyclerView that I am trying to add the effect to:
I figured out. The only thing that I had to do is to add this attribute:
android:background="?android:attr/selectableItemBackground"
to the root element of the layout that my RecyclerView adapter inflates like that:
<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="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:background="?android:attr/selectableItemBackground"
tools:background="#drawable/bg_gradient">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="17sp"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
android:id="#+id/shoppingListItem"
android:hint="#string/enter_item_hint"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/shopping_list_item_checkbox_label"
android:id="#+id/shoppingListCheckBox"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:checked="false"/>
</RelativeLayout>
Result:
If you are still not able to see ripple effect, add these lines also to the root element of the layout.
android:clickable="true"
android:focusable="true"
As already answered, the simplest solution is to just add one of the following as your RecyclerView row's background:
android:background="?android:attr/selectableItemBackground"
android:background="?attr/selectableItemBackground"
However if you are experiencing problems with this method or if you want finer control over the colors, then you can do the following.
Custom Ripple Effect
This answer is starting with this simple Android RecyclerView example. It will look like the following image.
Add selector for pre API 21 devices
Before API 21 (Android 5.0 Lollipop), clicking a RecyclerView item just changed its background color (no ripple effect). That is what we are going to do, too. If you still have users with those devices, they are used to that behavior, so we aren't going to worry about them too much. (Of course, if you really want the ripple effect for them, too, you could use a custom library.)
Right click your res/drawable folder and choose New > Drawable resource file. Call it custom_ripple. Click OK and paste in the following code.
custom_ripple.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#color/colorAccent" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#android:color/transparent" />
</shape>
</item>
</selector>
I used colorAccent as the highlight color for the pressed state because it was already available, but you can define whatever color you want.
Add Ripple Effect for API 21+ devices
Right click your res/drawable folder and choose New > Drawable resource file. Call it custom_ripple again. Don't click OK, yet this time, though. From the Available qualifiers list choose Version, then click the >> button and write 21 for the Platform API level. Now click OK and paste in the following code.
v21/custom_ripple.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/colorAccent">
<item
android:id="#android:id/mask"
android:drawable="#android:color/white" />
</ripple>
Again, I used colorAccent for the ripple color because it was available, but you can use whatever color you want. The mask confines the ripple effect to just the row layout. The mask color apparently doesn't matter so I just used an opaque white.
Set as the background
In your RecyclerView item's root layout, set the background to the custom ripple that we created.
android:background="#drawable/custom_ripple"
In the example project that we started with, it looks like this:
<?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="wrap_content"
android:orientation="horizontal"
android:background="#drawable/custom_ripple"
android:padding="10dp">
<TextView
android:id="#+id/tvAnimalName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"/>
</LinearLayout>
Finished
That's it. You should be able to run your project now. Thanks to this answer and this YouTube video for help.
I think there is one small detail that is missed.
If you still do not get the ripple effect after adding android:background="?android:attr/selectableItemBackground" try adding these following lines in the root of the layout.
android:clickable="true"
android:focusable="true"
These will make sure that the view is clickable and will enable the ripple effect with the background attribute mentioned above
add this lines in your adapter xml root view
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
A simple and custom approach is to set a view theme as outlined here.
some_view.xml
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:focusable="true"
android:src="#drawable/up_arrow"
android:theme="#style/SomeButtonTheme"/>
some_style.xml
<style name="SomeButtonTheme" >
<item name="colorControlHighlight">#color/someColor</item>
</style>
Other custom implementations may be found here.
Using a Button Style
This has worked for me countlessly.
Add the Borderless Button Style to the root element of your layout.
There's no need for focusable or clickable attributes, the default styling encapsulates all that for you.
<androidx.constraintlayout.widget.ConstraintLayout
style="#android:style/Widget.Material.Button.Borderless"
android:layout_width="match_parent"
android:layout_height="wrap_content">

Categories

Resources