I make a circle button with states and I want to add shadow to the button like the default buttons how I can do this? Here is my code:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="#color/yellow_pressed" />
<stroke android:width="1dp" android:color="#fff" />
</shape>
</item>
<item android:state_focused="true">
<shape android:shape="oval">
<solid android:color="#color/yellow_pressed" />
<stroke android:width="1dp" android:color="#fff" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="#color/yellow_default" />
<stroke android:width="1dp" android:color="#fff" />
</shape>
</item>
</selector>
Starting from Lollipop, you can use:
public static void setOvalElevationToView(final View view) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP)
view.setOutlineProvider(new ViewOutlineProvider() {
#TargetApi(VERSION_CODES.LOLLIPOP)
#Override
public void getOutline(View view, Outline outline) {
final int size = view.getWidth();
outline.setOval(0, 0, size, size);
}
});
}
You might also need to disable clipping on the parent of the view, so that the shadows won't be clipped
Related
I want to create a rectangle shape in XML like this:
Characteristics:
crystal-clear
shadow bottom
2 color areas
My solution is to have two shape overlap and rotate the angle for one, but it didn't work.
Does anyone have an idea how to solve this? Thank you!
create a custom ImageButton:
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.widget.ImageButton;
import androidx.annotation.Nullable;
#SuppressLint("AppCompatCustomView")
public class CustomRectangleView extends ImageButton {
private Paint drawPaint;
private Paint drawPaint1;
public CustomRectangleView(Context context) {
super(context);
setUpDraw();
}
public CustomRectangleView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
setUpDraw();
}
private void setUpDraw() {
drawPaint = new Paint();
setUpNewPaintObject(drawPaint, getResources().getColor(R.color.blue_light), 5);
drawPaint1 = new Paint();
setUpNewPaintObject(drawPaint1, Color.LTGRAY, 8);
}
private void setUpNewPaintObject(Paint paintObject, int color, int stroke) {
paintObject.setColor(color);
paintObject.setAntiAlias(true);
paintObject.setStrokeWidth(stroke);
paintObject.setStyle(Paint.Style.FILL_AND_STROKE);
paintObject.setStrokeJoin(Paint.Join.ROUND);
paintObject.setStrokeCap(Paint.Cap.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float RADIUS = 200;
#SuppressLint("DrawAllocation")
Path path = new Path();
path.moveTo(0, 0); // used for first point
path.lineTo(585, 0);
path.lineTo(0, 60);
#SuppressLint("DrawAllocation")
Path path1 = new Path();
path1.moveTo(15, 0); // used for first point
path1.lineTo(585, 0);
path1.moveTo(15, 150); // used for first point
path1.lineTo(585, 150);
canvas.drawPath(path, drawPaint);
canvas.drawPath(path1, drawPaint1);
}
}
and add this custom view to XML file:
<CustomRectangleView
android:layout_width="200dp"
android:layout_height="50dp"
android:src="#drawable/ic_add_black_24dp"
android:background="#6388C0">
</CustomRectangleView>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- "background shadow" -->
<item>
<shape android:shape="rectangle" >
<solid android:color="#000000" />
<corners android:radius="15dp" />
</shape>
</item>
<!-- background color -->
<item
android:bottom="3px"
android:left="3px"
android:right="3px"
android:top="3px">
<shape android:shape="rectangle" >
<solid android:color="#cc2b2b" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- over left shadow -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="180"
android:centerColor="#00FF0000"
android:centerX="0.9"
android:endColor="#99000000"
android:startColor="#00FF0000" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- over right shadow -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="360"
android:centerColor="#00FF0000"
android:centerX="0.9"
android:endColor="#99000000"
android:startColor="#00FF0000" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- over top shadow -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="-90"
android:centerColor="#00FF0000"
android:centerY="0.9"
android:endColor="#00FF0000"
android:startColor="#99000000"
android:type="linear" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- over bottom shadow -->
<item>
<shape android:shape="rectangle" >
<gradient
android:angle="90"
android:centerColor="#00FF0000"
android:centerY="0.9"
android:endColor="#00FF0000"
android:startColor="#99000000"
android:type="linear" />
<corners android:radius="8dp" />
</shape>
</item>
</layer-list>
I created a custom drawable for a button and found that if I share the drawable between an array of button, any button I press within the array of button will cause the last button in the array to be appear to be pressed as well. Here is the code...
//xml code for stage button
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/stage_button_selected"></item>
<item android:state_pressed="false"
android:drawable="#drawable/stage_button_deselected"></item>
</selector>
//xml code for stage_button_selected
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:left="5dp" android:right="5dp" android:top="5dp"
android:bottom="5dp">
<shape android:shape="oval" android:innerRadius="5dp">
<solid android:color="#android:color/holo_blue_light"></solid>
<stroke android:color="#android:color/holo_blue_dark"
android:width="2dp"></stroke>
<corners android:radius="5dp"></corners>
</shape>
</item>
</layer-list>
//xml code for stage_button_deselected
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:left="5dp" android:right="5dp" android:top="5dp"
android:bottom="5dp">
<shape android:shape="oval" android:innerRadius="5dp">
<solid android:color="#android:color/white"></solid>
<stroke android:color="#dddddd" android:width="2dp"></stroke>
<corners android:radius="5dp"></corners>
</shape>
</item>
</layer-list>`
//android code
Drawable drawable = resources.getDrawable(R.drawable.stage_button, null);
for(int ctr=0; ctr<btnStage.length; ctr++){
GridLayout.Spec specRow = GridLayout.spec(specStage[ctr][0], 1);
GridLayout.Spec specCol = GridLayout.spec(specStage[ctr][1], 1);
GridLayout.LayoutParams lp = new GridLayout.LayoutParams(specRow,
specCol);
btnStage[ctr] = new Button(MainActivity.this);
btnStage[ctr].setBackground(drawable);
btnStage[ctr].setText("Stage " + stageNo(ctr));
btnStage[ctr].setWidth(btnWidth);
btnStage[ctr].setHeight(btnHeight);
final String temp = stageNo(ctr);
btnStage[ctr].setOnClickListener(MainActivity.this);
ss_gridLayout.addView(btnStage[ctr], lp);
}
The solution to the problem is to create an array of drawable for use of the array of buttons, however it doesn't make sense that I cannot share the drawable between the array of buttons without it causing an unwanted effect...
I am not able to show the shadow of the indicator above the indicatior height within the tabs. i am using the karim library for material tabs,where i apply elevation but that does not help.How can i accheive shadow within the tab?
layout
<io.karim.MaterialTabs
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentBottom="true"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:background="#android:color/transparent"
android:textColor="#color/white"
app:mtIndicatorColor="#color/colorPrimaryRed"
app:mtIndicatorHeight="3dp"
app:mtPaddingMiddle="false"
app:mtSameWeightTabs="true"
app:mtTabPaddingLeftRight="10dp" />
test drawable
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item android:left="-11dp" android:right="-11dp" android:top="-11dp">
<shape>
<stroke android:width="10dp" android:color="#color/colorPrimaryRed" />
<gradient android:angle="90" android:endColor="#00fafafa" android:startColor="#88d66f67" android:type="linear" />
<corners android:radius="2dp" />
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
</shape>
</item>
</layer-list>
</item>
</selector>
java
class StarterMenuAdapter extends FragmentPagerAdapter {
public StarterMenuAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 1) {
LoginFragment loginFragment = new LoginFragment();
return loginFragment;
} else {
RegisterFragment registerFragment = new RegisterFragment();
return registerFragment;
}
}
#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length].toUpperCase();
}
#Override
public int getCount() {
return CONTENT.length;
}
}
want to achieve
what i got
how can shadow within the tab be achieved?
It is similar as you want,
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item android:left="-8dp" android:right="-8dp" android:top="-8dp">
<shape>
<stroke android:width="7dp" android:color="#color/red" />
<gradient android:angle="90" android:endColor="#00fafafa" android:startColor="#88d66f67" android:type="linear" />
<corners android:radius="2dp" />
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
</shape>
</item>
</layer-list>
</item>
</selector>
Output
In my app, I have the selector below.
Is possible to create a similar selector, by color instead of by image-drawable, but at runtime?
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_window_focused="false"
android:drawable="#drawable/ic_button_orange_normal" />
<item
android:state_pressed="true"
android:drawable="#drawable/ic_button_orange_pressed" />
<item
android:state_focused="true"
android:drawable="#drawable/ic_button_orange_focused" />
<item
android:drawable="#drawable/ic_button_orange_normal" />
</selector>
I have tried the function below to create the selector in runtime, but I need to create a round button, not square.
Is this possible?
private StateListDrawable makeSelector(int color)
{
StateListDrawable res = new StateListDrawable();
res.setExitFadeDuration(400);
res.setAlpha(45);
ShapeDrawable d = new ShapeDrawable();
res.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(ColorUtilities.decrease(color, 0x003030)));
res.addState(new int[] {}, new ColorDrawable(Color.TRANSPARENT));
return res;
}
Edit again... I have found the way to create round selectors...
private static ShapeDrawable getRoundShapeDrawable(int color)
{
ShapeDrawable shape_drawable = new ShapeDrawable(new OvalShape());
shape_drawable.getPaint().setColor(color);
return shape_drawable;
}
public static StateListDrawable getRoundShapeSelector(int normal_color, int pressed_color)
{
ShapeDrawable normal_shape_drawable = getRoundShapeDrawable(normal_color), pressed_shape_drawable = getRoundShapeDrawable(pressed_color);
StateListDrawable state_list_drawable = new StateListDrawable();
state_list_drawable.addState(new int[] { android.R.attr.state_pressed }, pressed_shape_drawable);
state_list_drawable.addState(new int[] { android.R.attr.state_focused }, pressed_shape_drawable);
state_list_drawable.addState(new int[] { }, normal_shape_drawable);
return state_list_drawable;
}
You can use "StateListDrawable"
StateListDrawable
and add state in it.
Let me know if you face problem in implementing this.
If you want to create a round button. Then you can use layer-list then add this drawable xml as a Layer.
Eg. How to create round button.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp">
<shape android:shape="rectangle" >
<corners android:radius="40dp" />
<solid android:color="#fff" />
</shape>
</item>
<item
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp">
<shape android:shape="rectangle" >
<corners android:radius="40dp" />
<solid android:color="#d3d3d3" />
</shape>
</item>
<item
android:bottom="1dp"
android:left="2dp"
android:right="1dp"
android:top="2dp">
<shape android:shape="rectangle" >
<corners android:radius="40dp" />
<solid android:color="#EBEBEB" />
</shape>
</item>
<item
android:id="#+id/wl_btn_bg_shape"
android:bottom="6dp"
android:left="6dp"
android:right="6dp"
android:top="6dp">
<shape android:shape="rectangle" >
<corners android:radius="40dp" />
<solid android:color="#00caa8" />
</shape>
</item>
</layer-list>
create and save about code in drawable as wl_btn_bg.xml
Now you need to add this xml as view background
LayerDrawable layers = (LayerDrawable) context.getResources().getDrawable(R.drawable.wl_btn_bg);
view.setBackground(layers);
and if you want to change the color of selector then you need to add following lines in layers
LayerDrawable layers = (LayerDrawable) context.getResources().getDrawable(R.drawable.wl_btn_bg);
GradientDrawable shape = (GradientDrawable) (layers.findDrawableByLayerId(R.id.wl_btn_bg_shape));
shape.setColor(Color.parseColor("#ff6655"));
Done....
How to change text position for different button states?
On image you can see how its look like now:
drawable
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true">
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="4dp">
<shape android:shape="rectangle">
<solid android:color="#DCDBDB" />
<corners android:radius="7dp" />
<stroke android:width="1dp" android:color="#B1B1B1"/>
</shape>
</item>
<item android:bottom="4.5dp" android:left="1.5dp" android:right="1.5dp" android:top="5.5dp">
<shape android:shape="rectangle" android:gravity="bottom">
<solid android:color="#F2F1F1" />
<corners android:radius="6dp" />
<stroke android:width="1dp" android:color="#FFFFFF"/>
</shape>
</item>
</layer-list>
</item>
<item>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#DCDBDB" />
<corners android:radius="7dp" />
<stroke android:width="1dp" android:color="#B1B1B1"/>
</shape>
</item>
<item android:bottom="8.5dp" android:left="1.5dp" android:right="1.5dp" android:top="1.5dp">
<shape android:shape="rectangle">
<solid android:color="#F2F1F1" />
<corners android:radius="6dp" />
<stroke android:width="1dp" android:color="#FFFFFF"/>
</shape>
</item>
</layer-list>
</item>
</selector>
Few days ago I asked similar question - Android 3D button src padding, but for text I cant use this trick :/ (or dont know how).
You will need to create a custom Button and override the methods for changing it's state in order to customize it's gravity based on the current state.
For example here is the code for a custom Button whose text will jump to the bottom when it is pressed:
public class VariableGravityButton extends Button {
public VariableGravityButton(Context context) {
super(context);
}
public VariableGravityButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VariableGravityButton(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void setPressed(boolean pressed) {
if (pressed != isPressed()) {
setGravity(pressed ? Gravity.CENTER_HORIZONTAL |
Gravity.BOTTOM : Gravity.CENTER);
}
super.setPressed(pressed);
}
}