How to create button shadow in android material design style - android

New material design guidelines introduce elevated buttons which are dropping nice shadow. According to the preview SDK documentation there will be elevation attribute available in new SDK. However, is there any way to achieve similar effect now?

This worked for me.
Layout having button
<Button
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="#dimen/button_size"
android:layout_height="#dimen/button_size"
android:background="#drawable/circular_button_ripple_selector"
android:textAppearance="?android:textAppearanceLarge"
android:textColor="#color/button_text_selector"
android:stateListAnimator="#anim/button_elevation"/>
drawble/button_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="#drawable/button_selected"/>
<item android:state_pressed="true"
android:drawable="#drawable/button_pressed"/>
<item android:drawable="#drawable/button"/>
</selector>
anim/button_elevation.xml
<?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:valueFrom="2dip"
android:valueTo="4dip"
android:valueType="floatType" />
</item>
<item>
<objectAnimator
android:duration="#android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueFrom="4dip"
android:valueTo="2dip"
android:valueType="floatType" />
</item>
</selector>
If you have a button in rectangular shape then you are done here. But if you have circular or oval shaped button then it would be looking like,
To remove corners from circular or oval shaped button add this code to your .java file.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...........
int buttonSize = (int) getResources().getDimension(R.dimen.button_size);
Outline circularOutline = new Outline();
circularOutline.setOval(0, 0, buttonSize, buttonSize);
for (int i = 0; i < MAX_BUTTONS; i++) {
Button button = ......
.......
button.setOutline(circularOutline);
........
}
.....
}
Angular shape removed!! Now, it would look exactly like

You can use 9-patch images, with shadows. Put the image in drawable--xxhdpi and set it as background on the button or other element.
android:background="#drawable/shadow_bg"

Or you could use CardView as a Button and use its CardView as a Button and its setCardElevation method.
Combined with touch events and ValueAnimator, you could get nice animated shadow below the button.

Related

Android color selector with radio buttons

I would like to create a group of radio buttons to pick a color. Something like this:
How can I achieve something like this? I didn't find any color property on the original RadioButton. Do I have to create a custom control? If yes, can someone just hint me on the basic steps so I can try to some new research? I'm very new to Android, and trying to learn by doing...
You can surely try custom radio buttons or you could simply use or inflate views to achieve this kind of color picker.
with xml: you will need to create two drawable resource files in the drawable folder. First goes like this,
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#e91e63" />
<size
android:width="48dp"
android:height="48dp" />
This is applicable when you haven't received any click on the view (clickable). The second file applies when we detect a click.
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#e91e63" />
<size
android:width="53dp"
android:height="53dp" />
<stroke
android:width="5dp"
android:color="#d2d1d2" />
Now, in the activity one needs to set the background drawable to the view (be it image button or imageview). This goes like this (just an example):
public class MainActivity extends AppCompatActivity {
private ImageButton img;
private boolean isSelected = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageButton) findViewById(R.id.img);
img.setClickable(true);
img.setBackground(getDrawable(R.drawable.unselected_circle));
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
img.startAnimation(AnimationUtils.loadAnimation(getBaseContext(), android.R.anim.fade_in));
if (isSelected) {
isSelected = false;
img.setBackground(getDrawable(R.drawable.unselected_circle));
} else {
isSelected = true;
img.setBackground(getDrawable(R.drawable.selected_circle));
}
}
});
}
}
and the activity_main layout looks something like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/viewGroup"
tools:context="com.android.empty.MainActivity">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:layout_margin="20dp"
android:clickable="true"
android:id="#+id/img"/>
However, with this method one will end up creating multiple drawables for different colors. To avoid that, we can create the drawables programmatically, writing code once and using the same for different colors using setColor(int color) method:
public class MainActivity extends AppCompatActivity {
private ImageButton img;
private boolean isSelected = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final GradientDrawable unselected = new GradientDrawable();
unselected.setShape(GradientDrawable.OVAL);
unselected.setColor(Color.parseColor("#e91e63"));
unselected.setSize(144, 144);
final GradientDrawable selected = new GradientDrawable();
selected.setShape(GradientDrawable.OVAL);
selected.setColor(Color.parseColor("#E91E63"));
selected.setSize(159, 159);
selected.setStroke(15, Color.parseColor("#D2D1D2"));
img = (ImageButton) findViewById(R.id.img);
img.setBackground(unselected);
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
img.startAnimation(AnimationUtils.loadAnimation(getBaseContext(), android.R.anim.fade_in));
if (isSelected) {
isSelected = false;
img.setBackground(unselected);
} else {
isSelected = true;
img.setBackground(selected);
}
}
});
}
}
The result looks something like this
Note: This example tells only the way to achieve one selector like the one mentioned in the question. To create multiple selectors, one needs to inflate the view (Image Button) using LayoutInflater class.
I Was stuck in the same problem to use radio buttons but then I tried my own hand on and created [CustomRadioShapes]1 Lib.
Simple implementation.
implementation:
Download release aar file from CustomRadioAndShapes/library folder
In your Android Studio File-> New -> New Module -> Import .aar or .jar
Select aar file and SubProject Name as CustomRadioAndShapes. Done.
Replace Drawable in RadioButton
I found a way to use the native RadioButton. You have to create your own Drawable and Style and then you're good to go. It took me all afternoon to get it right, so dear poor soul reading this - I hope it helps.
Below is a list of all resources you would need to achieve the following:
Built on Android 13 (API level 33)
Tested to also work on Android 7.0 (API level 24)
drawable/colour_picker.xml
(start with the selector element if you don't care about the ripple effect when picking an option)
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#android:color/white" android:radius="50dp">
<item>
<selector>
<item android:drawable="#drawable/colour_picker_checked" android:state_checked="true" />
<item android:drawable="#drawable/colour_picker_unchecked" android:state_checked="false" />
</selector>
</item>
</ripple>
drawable/colour_picker_checked.xml
(make sure shapes only use tint instead of color here or they will later on be broken)
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval" android:tint="#FFFFFF">
<stroke android:width="5dp" />
<solid android:color="#android:color/transparent" />
<size android:width="50dp" android:height="50dp"/>
</shape>
</item>
<item android:top="10dp" android:bottom="10dp" android:left="10dp" android:right="10dp">
<shape android:shape="oval" android:tint="#FFFFFF">
<solid android:width="1dp" />
</shape>
</item>
</layer-list>
drawable/colour_picker_unchecked.xml
(size needs to match colour_picker_checked.xml exactly or selecting options causes layout shift)
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval" android:tint="#FFFFFF">
<solid android:color="#android:color/transparent" />
<size android:width="50dp" android:height="50dp"/>
</shape>
</item>
<item android:top="10dp" android:bottom="10dp" android:left="10dp" android:right="10dp">
<shape android:shape="oval" android:tint="#FFFFFF">
<solid android:width="1dp" />
</shape>
</item>
</layer-list>
values/styles.xml
(the settings will distribute and align the buttons horizontally)
<style name="colour_picker"
parent="Base.Widget.AppCompat.CompoundButton.RadioButton">
<item name="android:button">#drawable/colour_picker</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">0dp</item>
<item name="android:gravity">center</item>
<item name="android:layout_weight">1</item>
</style>
layout/colour_picker.xml
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical"
android:theme="#style/RippleStyle">
<RadioGroup
android:id="#+id/colour_choice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="10dp">
<RadioButton name="" style="#style/colour_picker" android:buttonTint="#FFFFFF"/>
<RadioButton style="#style/colour_picker" android:buttonTint="#FF00FF"/>
</RadioGroup>
</LinearLayout>
How to Use It
The only difficulty at this point is identifying which option was chosen. If your list of colours is fixed and you don't mind hardcoding, consider giving each RadioButton an android:id directly in the XML.
In my case, I chose to create the RadioButton objects programmatically, which lets me cross-reference the colour from a string-array resource.
String[] colourPalette = getResources().getStringArray(R.array.colour_options);
RadioGroup colourPicker = findViewById(R.id.YOUR_LAYOUT_WHERE_THIS_SHOULD_END_UP);
LayoutInflater inflater = LayoutInflater.from(this);
for (int i = 0; i < colourPalette.length; i++) {
RadioButton colourOption = (RadioButton) inflater.inflate(R.layout.colour_picker_item,null).getRootView();
colourOption.setId(i);
colourOption.setButtonTintList(ColorStateList.valueOf(Color.parseColor(colourPalette[i])));
colourPicker.addView(colourOption);
}
For this to work you need two additional resources:
layout/colour_picker_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RadioButton style="#style/colour_picker" />
values/colors.xml
<string-array name="colour_options">
<item name="#FFFF00">#FFFF00</item>
<item name="#FF0000">#FF0000</item>
</string-array>
And then in your code it's as easy as this:
colourPicker.setOnCheckedChangeListener((group, checkedId) -> {
RadioButton colourOption = colourPicker.findViewById(checkedId);
int colour = Color.parseColor(colourPalette[colourOption.getId()]);
// do whatever you need to do with your picked colour
});

android checkbox text disappears when custom background is set

I want to make a weekly calendar, where every day is a custom checkbox with objective to look like the image bellow:
(http://i.imgur.com/WjIKCd0.png)
When the user clicks on a day (Monday in this case), the "background" and "button" checkbox changes as well the text color...
I made the drawables and it seems to work fine... check bellow the code:
Checkbox layout:
<CheckBox
android:id="#+id/selectMonday"
android:layout_width="40dp"
android:layout_height="40dp"
android:button="#drawable/ic_none"
style="#style/CheckBoxBackgroundView"
android:onClick="selectDay"
android:text="#string/monday_letter"
android:gravity="center"
android:checked="true"/>
(the drawable "ic_none", is simple a 135x135 "transparent" image with nothing in it...)
Style (CheckBoxBackgroundView):
<style name="CheckBoxBackgroundView">
<item name="android:background">#drawable/background_day_week_picker_box_selector</item>
<item name="android:textColor">#color/text_color_day_week_picker_box_selector</item>
<item name="android:textSize">#dimen/text_spinner_text</item>
<item name="android:textStyle">bold</item>
</style>
Background Selector (background_day_week_picker_box_selector):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="#drawable/background_day_of_week_picker_unselected" />
<item android:state_checked="true"
android:drawable="#drawable/background_day_of_week_picker_selected" />
</selector>
Background selected (background_day_of_week_picker_selected):
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- view background color -->
<solid
android:color="#color/red_color" >
</solid>
<!-- view border color and width -->
<stroke
android:width="3dp"
android:color="#color/transparent">
</stroke>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
and finally the color selector (text_color_day_week_picker_box_selector):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:color="#color/red_color"></item>
<item android:state_checked="true"
android:color="#color/white"></item>
</selector>
I tried this in several devices... in some, it appears like it suppose to, in others the text disappears and it looks like this:
(http://i.imgur.com/Jy9FrPS.png)
probably is coincidence, but all the devices that worked are below 5 inches...
is there anything wrong with my code that I'm not seeing? anyone have any suggestions?
Thanks in advance
The problem is that the 135x135 button drawable is pushing the text out of the bounds of your CheckBox's width. Instead of using a drawable, you can just set android:button="#color/transparent".

Android L FAB Button shadow

In the Material Design guidelines Google presented a new style of button, the FAB Button. I found instructions how to make it but I have trouble adding the shadow. How can this be achieved?
Check out the "activity.java", there is probably the code you need.
I made the Fab - Button like this:
layout.xml
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="56dp"
android:layout_height="56dp"
android:text="+"
android:textSize="40sp"
android:background="#drawable/ripple"
android:id="#+id/fabbutton"
android:layout_margin="#dimen/activity_horizontal_margin"
android:elevation="3dp"
android:paddingBottom="16dp"
android:fontFamily="sans-serif-light"
android:layout_alignParentEnd="true"
android:layout_gravity="right|bottom" />
ripple.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple android:color="#ffb300" xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/fab"></item>
</ripple>
fab.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#color/accentColor" />
</shape>
Activity.java
import android.graphics.Outline;
...
Button fab = (Button) rootView.findViewById(R.id.fabbutton);
Outline mOutlineCircle;
int shapeSize = getResources().getDimensionPixelSize(R.dimen.shape_size);
mOutlineCircle = new Outline();
mOutlineCircle.setRoundRect(0, 0, shapeSize, shapeSize, shapeSize / 2);
fab.setOutline(mOutlineCircle);
fab.setClipToOutline(true);
This code will be shown as error in android studio v0.8.1, so as other android l components. It will be fixed in the next version.
Result:
You can use a Button:
<ImageButton
android:id="#+id/fab"
android:background="#drawable/ripple"
android:stateListAnimator="#anim/anim"
android:src="#drawable/ic_action_add"
android:elevation="4dp"
/>
where the ic_action_add is your icon.
drawable/ripple.xml is:
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
<item>
<shape android:shape="oval">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
anim/anim.xml is:
<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:valueFrom="#dimen/button_elevation"
android:valueTo="#dimen/button_press_elevation"
android:valueType="floatType" />
</item>
<item>
<objectAnimator
android:duration="#android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueFrom="#dimen/button_press_elevation"
android:valueTo="#dimen/button_elevation"
android:valueType="floatType" />
</item>
</selector>
Dimens.xml is
<resources>
<dimen name="fab_size">56dp</dimen>
<dimen name="button_elevation">2dp</dimen>
<dimen name="button_press_elevation">4dp</dimen>
</resources>
With the elevation attribute you should set the Outline via code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layoutfab);
//Outline
Button fab = (Button) findViewById(R.id.fab)
ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() {
#Override
public void getOutline(View view, Outline outline) {
// Or read size directly from the view's width/height
int size = getResources().getDimensionPixelSize(R.dimen.fab_size);
outline.setOval(0, 0, size, size);
}
};
fab.setOutlineProvider(viewOutlineProvider);
}
}
The problem with the circular shadow can be easily solved without any tricks with Outline: just add these properties to the button in the XML layout (in addition to the custom background):
android:elevation="5dp"
android:stateListAnimator="#null"
Although Android Studio may display it wrong in the layout preview, it works fine when launched on a device.

Pressed button background change in Android as in Xcode

I was wondering is there any way to make your customised ImageButton or a Button change background on click.
Now, I know that it can be done through XML doing something like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/login_selected" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="#drawable/login_mouse_over" /> <!-- focused -->
<item android:drawable="#drawable/login" /> <!-- default -->
</selector>
Or in code, doing something like this, onClick:
public void onClick(View v) {
if(v == ButtonName) {
ButtonName.setImageResource(R.drawable.ImageName);
}
}
BUT, If I want to do it this way, that means I have to use 2 different images for one button. One with the normal and one with the pressed state.
That can be problem if I have, lets say, 100 different buttons.
That's 200 images, just for buttons.
You can Imagine resources saving with the ability of just telling eclipse it's a button, and I want it to go a bit darker, when I press it.
So I am asking is there a way of doing it like in Xcode ?
Setting up a background or an image of a button and it shades a bit when pressed, not changing the background or anything, just shading it a bit,
Try this code
if the name of
is btn_back.png
make the following darawble xml file
btn_semi.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#50000011"
/>
<corners android:radius="10dip"/>
</shape>
btn_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" >
<layer-list>
<item android:drawable="#drawable/btn_back"></item>
<item android:drawable="#drawable/btn_semi"></item>
</layer-list>
</item>
<item android:drawable="#drawable/btn_back"></item>
</selector>
Create a button in layout
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/btn_background"
/>
You can try to use setAlpha but its only available in API 11 and above

How can i make an "Gmail" like header buttons? (Pic attached)

Does any one knows how can i skin an android button to look like this:
a busy cat http://www.11sheep.com/temp/picForSO.jpg
Thanks in advance,
Lior
The following layout files will product a button with 5px radius, of course u input your own color and change the solid color to gradient to match ur screenshots, then on the button change the text colour to white or something.. I dont have time for examples now.. good luck though.
and lastly you have to apply them as background to your button like this
<Button
android:id="#+id/btnLoveThisOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="Love me love u too!"
android:background="#drawable/button_background" <!-- Yes look at me -->
/>
button_background_normal.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/button_background_normal_color"/> <!-- Change this to your own colour -->
<corners android:radius="5px"/>
<stroke android:width="1dp" android:color="#20ffffff"/>
</shape>
button_background_pressed.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/button_background_pressed_color"/> <!-- Change this to your own colour -->
<corners android:radius="5px"/>
</shape>
button_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true"
android:state_pressed="false"
android:drawable="#drawable/button_background_normal" />
<item android:state_focused="true"
android:state_pressed="true"
android:drawable="#drawable/button_background_pressed" />
<item android:state_focused="false"
android:state_pressed="true"
android:drawable="#drawable/button_background_pressed" />
<item android:drawable="#drawable/button_background_normal" />
</selector>
I know two ways to make it:
a Button or TextView with an image having that engraving rectangle, for stretch, use 9.patch :)
a Button or TextView with transparent background and a selector drawing the shape border
However, I don't know exactly how they did as shown in your picture.

Categories

Resources