Adding Ripple Effect to RecyclerView item - android

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">

Related

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.

Android app - basic icon button without text

How do I make a basic icon button without text or background? For example, just a simple vector image from #drawables that, when clicked, shows that circular response thing around it. I don't want the icon to have any background color to it. Just an icon that can be clicked, that's literally it.
I can only figure out how to do it by creating a menu and setting the icon as an item with app:showAsAction="always". It seems like there must be a better way to do this.
Edit: Here's an example of what I want to achieve. It's very basic. Just a clickable icon with responsive feedback when touched. https://material-ui.com/components/buttons/#icon-buttons
It's exactly the same as creating the following. I just thought there was likely an easier way to do this without having to create and load a menu just for one single icon:
<menu 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"
tools:context="com.mycompany.myapp.MainActivity">
<item
android:id="#+id/action_contacts"
android:icon="#drawable/ic_contacts_24"
android:title="#string/action_contacts"
app:iconTint="#android:color/white"
app:showAsAction="always" />
</menu>
First create a vector drawable and then add to the ImageView like
this:
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
app:srcCompat="#drawable/ic_delete" />
You can use a MaterialButton, ImageButton and even an ImageView for this. Here's an example of how you'd do it with an ImageView...
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:src="#drawable/your_icon" />
All you need to do is set the selectableItemBackground, this will use your theme's primary color (or maybe the secondary color, I can't remember).
Now if you want a different color for ripple effect, for example a grey ripple, then you can create the drawable yourself...
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#dddddd">
<item android:id="#android:id/mask">
<color android:color="#dddddd" />
</item>
</ripple>
and set the view background below..
android:background="?attr/selectableItemBackground"
it'll work with any view provided the view is clickable
Yes, you can use ImageView if you like, but if you want to generate the complete image (including frame/borders) yourself you don't have to go that far. You could practically use plain View (except that you'd have to supply android:layout_width/height explicitly). Just use Button and have the android:background specify a selector which will select between images.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/clear1" android:state_pressed="true"/>
<item android:drawable="#drawable/clear0"/>
</selector>

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:

Spinner inner padding is larger on Android 6.0.1

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.

White Space with CardView on pre-lollipop devices

I am attempting to add rounding and shadows to some views on an app and am utilizing the card view library to achieve that. It is looking good on lollipop devices but am running into compatibility issues with anything pre-lollipop.
I will preface this by saying that I have looked at the answers in the questions below have found that none of them are working for me.
Appcompat CardView and Picasso no rounded Corners
Cardview - white border around card
Unnecessary padding in CardView?
The most popular answer was to add the attribute 'cardPreventOverlap=false' but this removes the rounded corners. I have tried variations of this flag and 'cardUseCompatPadding="true"' but none of them seem to do the trick. Has anyone else run into the same problem?
My code:
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
card_view:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/selector"
android:gravity="center"
android:orientation="horizontal" >
<ImageView
android:layout_width="44dp"
android:layout_height="match_parent"
android:layout_marginRight="4dp"
android:background="#color/mid_yellow"
android:padding="0dp"
android:src="#drawable/ic_add_white_24dp" />
<TextView
style="#style/Text.Primary.White"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:text="Button" />
</LinearLayout>
This is how it currently looks on Android 5.0:
The exact same code on 4.4.2 displays as:
With 'cardPreventOverlap=false':
Update Unfortunately we were not able to solve the issue; given that the app only had small install base pre5.0 we decided it was not important. We ended up going with the third option 'cardPreventOverlap=false'.
Content clipping is not supported, because is quite expensive on older devices. If you wish, you can use Carbon. It has its own CardView implementation, which correctly clip content to rounded corners. Carbon also adds content clipping and elevation to all other layouts so for your purpose you can use a LinearLayout with rounded corners and shadow. See the image:
Instead of using card_view:cardCornerRadius you can set the background of the cardview with a drawable like:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<corners android:radius="4dip"/>
</shape>
You can also do this for each element in your cardview such that you have for each element the correct background color.
In that case you can specify only certain corners with:
<corners
android:topLeftRadius="4dp"
android:bottomLeftRadius="4dp"/>
For your + button for example.
Use this in combination with cardUseCompatPadding="true"

Categories

Resources