I'm currently implementing an app which has a RecyclerView in which there are several custom views. From each one of these views the user can open a context menu (which requires a long click) but it's quite hard to figure out as generally, they will just perform a simple click and then think there is nothing more to it. But if I manage to give some UI feedback it could be much clearer. The idea is a simple ripple animation that highlights the background an which wouldn't complete from a simple click but which would go all the way for a long click action.
As I have been stuck on this for two days I have done my research and actually found some SO questions asking the same thing, for example this one from Cheok Yan Cheng is very well written and he even posted a video showing the desired effect (my question is pretty much the exact same) but there are no good answers as the first one says that we should use ?attr/selectableItemBackground but the given effect is different from the one I'm aiming for and I tried the second one, it doesn't do anything for a simple click as you start the animation in onLongClick.
EDIT :
Note that the expected behavior cannot be achieved from
?attr/selectableItemBackground nor by creating a ripple xml file and then set it as the background as these will give a normal onClick animation and a different longClick animation from the desired one again, look at this video to see what the desired effect is.
Try to follow these steps, it might help:
Step1:
Create ripple.xml in drawable: (This is for Android >= v21)
<?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">
<color android:color="#android:color/transparent" />
</item>
</ripple>
In this line <color android:color="#android:color/transparent" /> will make your button transparent.
Step2:
in your item.xml where I used ConstraintLayout:
<Button
android:id="#+id/btnItemClickOnRecyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerInParent="true"
android:layout_marginTop="16dp"
android:background="#drawable/ripple"
android:paddingBottom="4dp"
android:text="#string/view_details"
android:textColor="#color/White"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
And That's it.
Since your button will be fully covering your Item and it will hover on top of other view, it will act like an item.
To implement longClick listener on the button, make sure you register it in holder and then holder.button.setOnLongClick......
Try it, If any doubts please comment.
Make a xml file named ripple.xml then set the ripple.xml as the foreground of your view. It will work like a charm!!!
<?xml version="1.0" encoding="utf-8"?>
<!-- An white rectangle ripple. -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="#3fce29"
tools:targetApi="lollipop">
<item
android:id="#android:id/mask"
android:gravity="center">
<shape android:shape="rectangle">
<solid android:color="#3fce29"/>
</shape>
</item>
</ripple>
Try this first make ripple effect xml
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/light_gray"
tools:targetApi="lollipop">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#color/light_gray"/>
</shape>
</item>
</ripple>
than your adapter decalr xml parent layout like LinearLayout or if use RelativLayout set background as below
<?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="wrap_content"
android:background="#drawable/ripple"
>......
Related
I have been experimenting with button attributes and what I can do with buttons in general. I wanted to modify the way a button looks when clicked.
I created three drawable resource files, two for each button states(pressed or default) and one for state list to pass to the button in the main activity xml.
However this does not work as the button stays the same when I click it.
custom_button_pressed.xml file code
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#color/button_color_pressed"/>
<corners android:radius="30dp"/>
</shape>
custom_button.xml file (default state file) code:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="30dp"/>
<solid android:color="#color/button_color"/>
</shape>
custom_button_full.xml file code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#drawable/custom_button_pressed"
android:state_pressed="true" />
<item android:drawable="#drawable/custom_button"/>
</selector>
code fragment for the button in the main xml file:
<Button
android:id="#+id/buttonAboutApp"
android:layout_width="160dp"
android:layout_height="105dp"
android:layout_marginEnd="6dp"
android:layout_marginRight="6dp"
android:layout_marginBottom="44dp"
android:background="#drawable/custom_button_full"
android:drawableLeft="#mipmap/about_app_icon"
android:text="#string/About_app"
android:textAllCaps="false"
android:textColor="#color/app_background"
app:backgroundTint="#color/button_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
what am I doing wrong ? Thank you in advance
If you are using a version of the Material Components library less than 1.2.0, the android:background attribute is not supported by MaterialButton. If your app/activity uses a MaterialComponents theme, any <Button> tag will be automatically inflated as a MaterialButton instance, so your custom background won't work.
Since you're trying to override the button's appearance anyway, you probably want just a basic android.widget.Button instead of a MaterialButton. You can achieve this by specifying the fully-qualified name in the view tag of your layout file:
<android.widget.Button
android:background="#drawable/custom_button_full"
.../>
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>
I am using android:background="?attr/selectableItemBackground" on a LinearLayout (which acts as a button) to get the ripple effect. When this button is clicked, the current activity slides left during a transition. The problem is that the ripple effect takes some time to be triggered and at the time it becomes visibile, the activity transition has already started, which makes the use of the touch feedback completely useless. I don't want to add a delay to the activity transition, that would be stupid IMO.
XML file looks like this:
<android.support.v7.widget.CardView>
<LinearLayout
android:clickable="true"
android:background="?attr/selectableItemBackground"/>
</android.support.v7.widget.CardView>
How can I make the ripple effect useful and visible ?
Try to use own drawable for background:
<android.support.v7.widget.CardView>
<LinearLayout
android:clickable="true"
android:background="#drawable/ripple"/>
</android.support.v7.widget.CardView>
And ripple.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#80585554">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#your color"/>
</shape>
</item>
</ripple>
On CardView you can apply
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:foreground="?attr/selectableItemBackground"
android:clickable="true">
<!--linearlayout etc...-->
</android.support.v7.widget.CardView>
The pressed state is delayed if one of the view's parents returns true in the shouldDelayChildPressedState method. Typically, subclasses of the ViewGroup that do not scroll should override this method and return false.
I am looking for a way to style my button like an example from an older question (How to create standard Borderless buttons (like in the design guidline mentioned)?) but some things were left out from the answer.
How can I add more than one value to an XML element, particularly android:background ="";?
I figured out how to make my buttons borderless, but I want them to have a really thin border, and a different background color. I have seen lots of tips online, but I can't find a way to put all my items together properly in code. Below is a copy pasted image with the top part representing the layout I want to achieve with the button name and a thumbnail image on the right hand side on the button with the button being a different color then the background of the app, and below that is a copy pasted image of the border style I'm trying to achieve, thin, touching borders between buttons. I have looked everywhere and tried many ideas but none seem to work properly, or some require me to have
android:background="?android:attr/selectableItemBackground"
but this interacts with
android:background="#22272D"
I need to keep the text in the button because my app is going to translate the buttons text to the language of the users phone, so I can't make the whole button just an image. Below is my XML and the output, any recommendations to how I should change it would be of massive help!
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="6"
tools:context="com.aid.travelers.myapplication.Transportation">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/transportation_page"
android:textSize="40sp"
android:textColor="#000000"/>
<Button
android:layout_width="match_parent"
android:text="#string/airport"
android:id="#+id/AirportButton"
android:layout_height="60dp"
android:layout_weight="1"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:background="?android:attr/selectableItemBackground"/>
<Button
android:layout_width="match_parent"
android:text="#string/bicycle"
android:id="#+id/BicycleButton"
android:layout_height="60dp"
android:layout_weight="1"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:background="?android:attr/selectableItemBackground"/>
I'm not sure that I get your question, but I guess you want to custom the background of your button, and have a touch effect when you press it.
Have a look at this answer :
https://stackoverflow.com/a/7176006/5446285
You should create your own resource file background.xml (for example) that you create in your drawable folder.
The code should be like :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/background_selected"/> <!-- pressed -->
<item android:drawable="#drawable/background_unselected" /> <!-- default -->
</selector>
You should now create 2 other files in your drawable folder : background_selected.xml, and background_unselected.xml.
To do so, I advise you something like this if you want a thin border :
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#7c7c7c" />
</shape>
</item>
<item android:bottom="2dp" android:top="2dp" android:right="2dp" android:left="2dp">
<shape android:shape="rectangle" >
<solid android:color="#a0a0a0" />
</shape>
</item>
Then you set the background of your button in your xml :
android:background="#drawable/background"
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>