MOCK UP
Requirement
I want to put custom button with selector.
Mock up is given above.
If anyone knows solution then share it.
Thank you.
basically you will need to create some new XML files and apply them to your Button element. As i can see from the mockup you will need a stroke and the background color with some shading effect applied, you can research more into the shading thing but the background color and the stroke is pretty straight forward.
Here is an example, done_rounded_btn.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:state_enabled="true"
android:drawable="#drawable/zzzzzzzzz_btn_orange" />
<item
android:state_focused="true"
android:state_enabled="true"
android:drawable="#drawable/zzzzzzzzz_btn_orange" />
<item
android:state_focused="false"
android:state_enabled="false"
android:drawable="#drawable/zzzzzzzzz_btn_inactiv" />
<item android:drawable="#drawable/zzzzzzzzz_btn_black"/>
</selector>
for the selection part and then you create the custom drawables corresponding to the mockup.
An example, zzzzzzzzzz_btn_orange:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid
android:color="#color/done_color">
</solid>
<corners
android:bottomLeftRadius="3dp"
android:bottomRightRadius="3dp"
android:topLeftRadius="3dp"
android:topRightRadius="3dp" />
</shape>
And then add it to your button as background, main.xml:
<Button
android:id="#+id/registers_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:background="#drawable/done_rounded_btn"
android:text="#string/done_txt"
android:textColor="#color/white"
android:textSize="15sp" />
Hope this helps!
You can use this instead of standard Button and set selector as background in xml:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
/**
* Custom Shape Button which ignores touches on transparent background.
*/
public class ButtonWithUntouchableTransparentBg extends Button {
public ButtonWithUntouchableTransparentBg(Context context) {
this(context, null);
}
public ButtonWithUntouchableTransparentBg(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ButtonWithUntouchableTransparentBg(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setDrawingCacheEnabled(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
// ignores touches on transparent background
if (isPixelTransparent(x, y))
return true;
else
return super.onTouchEvent(event);
}
/**
* #return true if pixel from (x,y) is transparent
*/
private boolean isPixelTransparent(int x, int y) {
Bitmap bmp = Bitmap.createBitmap(getDrawingCache());
int color = Color.TRANSPARENT;
try {
color = bmp.getPixel(x, y);
} catch (IllegalArgumentException e) {
// x or y exceed the bitmap's bounds.
// Reverts the View's internal state from a previously set "pressed" state.
setPressed(false);
}
// Ignores touches on transparent background.
if (color == Color.TRANSPARENT)
return true;
else
return false;
}
}
You can also create a shape that is using a selector inside. If your shape is just changing its color in different states, this is a lot cleaner.
color/color_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/blue_dark" android:state_pressed="true" />
<item android:color="#color/blue_light" />
</selector>
drawable/shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/color_selector" />
<corners android:bottomLeftRadius="6dip" android:bottomRightRadius="6dp" />
<padding android:bottom="0dip" android:left="0dip" android:right="0dip" android:top="0dip" />
</shape>
Button with rounded corners with two states (enabled/disabled):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="#color/white" />
<stroke android:width="1dp" android:color="#color/orange" />
</shape>
</item>
<item android:state_enabled="false">
<shape android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="#color/grey_card_background" />
<stroke android:width="1dp" android:color="#color/grey" />
</shape>
</item>
</selector>
inside your item put the shape in the selector XML
EX FROM MY CODE :
<!-- if pressed -->
<item android:state_pressed="true"><shape android:padding="10dp" android:shape="rectangle">
<solid android:color="#color/blue" />
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape></item>
<!-- if not pressed -->
<item><shape android:padding="10dp" android:shape="rectangle">
<solid android:color="#color/Purbble" />
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape></item>
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 have developed an rss application. I want the ListView which contains the titles and images to have the images with rounded corners. I have taken a sample code online, but the problem is that the images are still rectangular. The weird part is that I have a sliding menu, when toggled it pushes the rss ListView away, while it's being pushed the images have round corners! when they stop their pushing animation the become rectangular again. It's a pretty weird problem for me so any help?
Rounded Image class:
public class RoundedImageView extends ImageView
{
private float radius = 20.0f;
public RoundedImageView(Context context)
{
super(context);
}
public RoundedImageView(Context context,AttributeSet attrs)
{
super(context,attrs);
}
public RoundedImageView(Context context,AttributeSet attrs,int defStyle)
{
super(context,attrs,defStyle);
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas)
{
Path clipPath = new Path();
RectF rect = new RectF(0,0,getWidth(), getHeight());
clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
}
Try this way: create rounded_corner.xml file into drawable\rounded_corner.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#101010" />
<stroke
android:width="1dp"
android:color="#808080" />
<corners android:radius="15dp" />
And set as Background to your ImageView like
android:background="#drawable\rounded_corner"
And also set your RSS image to ImageView as a Src or a Bitmap like:
imageview.setBitmap(yourrssimage);
use rounded corner image or create xml and set as background image on imageview.
Create one XML like below in your drawable folder.
button_back.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="false"
android:drawable="#color/grey">
<shape>
<solid
android:color="#ef4444" />
<stroke
android:width="1dp"
android:color="#992f2f" />
<corners
android:radius="16dp" />
</shape>
</item>
and then apply to your button like this.
<Button
android:text="#string/press_me"
android:layout_margin="12dp"
android:layout_width="fill_parent"
android:layout_height="30dp"
android:background="#drawable/button_back"
/>
Create a stroke and list it as your imageview background
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#android:color/transparent"/>
<stroke android:width="5dip" android:color="#android:color/transparent" />
<corners android:radius="5dip"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>
And in your imageview xml
android:background="#drawable/your_stroke_xml"
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);
}
}
MOCK UP
Requirement
I want to put custom button with selector.
Mock up is given above.
If anyone knows solution then share it.
Thank you.
basically you will need to create some new XML files and apply them to your Button element. As i can see from the mockup you will need a stroke and the background color with some shading effect applied, you can research more into the shading thing but the background color and the stroke is pretty straight forward.
Here is an example, done_rounded_btn.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:state_enabled="true"
android:drawable="#drawable/zzzzzzzzz_btn_orange" />
<item
android:state_focused="true"
android:state_enabled="true"
android:drawable="#drawable/zzzzzzzzz_btn_orange" />
<item
android:state_focused="false"
android:state_enabled="false"
android:drawable="#drawable/zzzzzzzzz_btn_inactiv" />
<item android:drawable="#drawable/zzzzzzzzz_btn_black"/>
</selector>
for the selection part and then you create the custom drawables corresponding to the mockup.
An example, zzzzzzzzzz_btn_orange:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid
android:color="#color/done_color">
</solid>
<corners
android:bottomLeftRadius="3dp"
android:bottomRightRadius="3dp"
android:topLeftRadius="3dp"
android:topRightRadius="3dp" />
</shape>
And then add it to your button as background, main.xml:
<Button
android:id="#+id/registers_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:background="#drawable/done_rounded_btn"
android:text="#string/done_txt"
android:textColor="#color/white"
android:textSize="15sp" />
Hope this helps!
You can use this instead of standard Button and set selector as background in xml:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
/**
* Custom Shape Button which ignores touches on transparent background.
*/
public class ButtonWithUntouchableTransparentBg extends Button {
public ButtonWithUntouchableTransparentBg(Context context) {
this(context, null);
}
public ButtonWithUntouchableTransparentBg(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ButtonWithUntouchableTransparentBg(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setDrawingCacheEnabled(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
// ignores touches on transparent background
if (isPixelTransparent(x, y))
return true;
else
return super.onTouchEvent(event);
}
/**
* #return true if pixel from (x,y) is transparent
*/
private boolean isPixelTransparent(int x, int y) {
Bitmap bmp = Bitmap.createBitmap(getDrawingCache());
int color = Color.TRANSPARENT;
try {
color = bmp.getPixel(x, y);
} catch (IllegalArgumentException e) {
// x or y exceed the bitmap's bounds.
// Reverts the View's internal state from a previously set "pressed" state.
setPressed(false);
}
// Ignores touches on transparent background.
if (color == Color.TRANSPARENT)
return true;
else
return false;
}
}
You can also create a shape that is using a selector inside. If your shape is just changing its color in different states, this is a lot cleaner.
color/color_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/blue_dark" android:state_pressed="true" />
<item android:color="#color/blue_light" />
</selector>
drawable/shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/color_selector" />
<corners android:bottomLeftRadius="6dip" android:bottomRightRadius="6dp" />
<padding android:bottom="0dip" android:left="0dip" android:right="0dip" android:top="0dip" />
</shape>
Button with rounded corners with two states (enabled/disabled):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="#color/white" />
<stroke android:width="1dp" android:color="#color/orange" />
</shape>
</item>
<item android:state_enabled="false">
<shape android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="#color/grey_card_background" />
<stroke android:width="1dp" android:color="#color/grey" />
</shape>
</item>
</selector>
inside your item put the shape in the selector XML
EX FROM MY CODE :
<!-- if pressed -->
<item android:state_pressed="true"><shape android:padding="10dp" android:shape="rectangle">
<solid android:color="#color/blue" />
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape></item>
<!-- if not pressed -->
<item><shape android:padding="10dp" android:shape="rectangle">
<solid android:color="#color/Purbble" />
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape></item>
I have a custom ImageButton class mimicing the ToggleButton's checked state based on this tutorial How to add a custom button state .
Everything works fine, when I have a state list drawable as the android:src attribute, but the custom state doesn't work with the ImageButton's android:background attribute.
Here is my code:
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Checkable;
import android.widget.ImageButton;
public class CheckableImageButton extends ImageButton implements Checkable {
private static final int[] STATE_CHECKED = {R.attr.state_checked};
private boolean mChecked = false;
public CheckableImageButton(Context context) {
super(context);
}
public CheckableImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if(mChecked){
mergeDrawableStates(drawableState, STATE_CHECKED);
}
return drawableState;
}
#Override
public boolean isChecked() {
return mChecked;
}
#Override
public void setChecked(boolean checked) {
mChecked = checked;
refreshDrawableState();
}
#Override
public void toggle() {
setChecked(!mChecked);
}
}
And the relevant snippet from the layout XML:
<com.my.package.view.CheckableImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#drawable/header_button_bg"
android:padding="5dp"
android:src="#drawable/menu_button"
tools:ignore="ContentDescription" />
And the state list drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/my.package" >
<item android:state_pressed="true">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#ff000000" />
<gradient android:angle="-90" android:endColor="#d2914e" android:startColor="#906434" />
<corners android:radius="5dp" />
</shape>
</item>
<item app:state_checked="true">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#ff000000" />
<gradient android:angle="-90" android:endColor="#d2914e" android:startColor="#906434" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#ff000000" />
<gradient android:angle="-90" android:endColor="#4f5b6c" android:startColor="#345b75" />
<corners android:radius="5dp" />
</shape>
</item>
</selector>
Another wonderful trait of eclipse probably..
When I tried to revert my code to the last working version by hand (the state list drawable in the android:src tag), it produced the same error. I reverted from the SVN repo, it worked. Then I made the exact same changes as before, character by character, no difference, and voilá, it works now!
So that's it, the code in the question is fully functional.