How to show shadow around the linearlayout in Android? - android

How can I show shadow for my linear layout. I want white colored rounded background with shadow around the linearlayout. I have done this so far.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#xml/rounded_rect_shape"
android:orientation="vertical"
android:padding="10dp">
<-- My buttons, textviews, Imageviews go here -->
</LinearLayout>
And rounded_rect_shape.xml under xml directory
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#ffffff" />
<corners
android:bottomLeftRadius="3dp"
android:bottomRightRadius="3dp"
android:topLeftRadius="3dp"
android:topRightRadius="3dp" />
</shape>

There is also another solution to the problem by implementing a layer-list that will act as the background for the LinearLayoout.
Add background_with_shadow.xml file to res/drawable. Containing:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item >
<shape
android:shape="rectangle">
<solid android:color="#android:color/darker_gray" />
<corners android:radius="5dp"/>
</shape>
</item>
<item android:right="1dp" android:left="1dp" android:bottom="2dp">
<shape
android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>
Then add the the layer-list as background in your LinearLayout.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_with_shadow"/>

Well, this is easy to achieve .
Just build a GradientDrawable that comes from black and goes to a transparent color, than use parent relationship to place your shape close to the View that you want to have a shadow, then you just have to give any values to height or width .
Here is an example, this file have to be created inside res/drawable , I name it as shadow.xml :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#9444"
android:endColor="#0000"
android:type="linear"
android:angle="90"> <!-- Change this value to have the correct shadow angle, must be multiple from 45 -->
</gradient>
</shape>
Place the following code above from a LinearLayout , for example, set the android:layout_width and android:layout_height to fill_parent and 2.3dp, you'll have a nice shadow effect on your LinearLayout .
<View
android:id="#+id/shadow"
android:layout_width="fill_parent"
android:layout_height="2.3dp"
android:layout_above="#+id/id_from_your_LinearLayout"
android:background="#drawable/shadow">
</View>
Note 1: If you increase android:layout_height more shadow will be shown .
Note 2: Use android:layout_above="#+id/id_from_your_LinearLayout" attribute if you are placing this code inside a RelativeLayout, otherwise ignore it.
Hope it help someone.

There is no such attribute in Android, to show a shadow. But possible ways to do it are:
Add a plain LinearLayout with grey color, over which add your actual layout, with margin at bottom and right equal to 1 or 2 dp
Have a 9-patch image with a shadow and set it as the background to your Linear layout

For lollipop and above you can use elevation.
For older versions:
Here is a lazy hack from:
http://odedhb.blogspot.com/2013/05/android-layout-shadow-without-9-patch.html
(toast_frame does not work on KitKat, shadow was removed from toasts)
just use:
android:background="#android:drawable/toast_frame"
or:
android:background="#android:drawable/dialog_frame"
as a background
examples:
<TextView
android:layout_width="fill_parent"
android:text="I am a simple textview with a shadow"
android:layout_height="wrap_content"
android:textSize="18sp"
android:padding="16dp"
android:textColor="#fff"
android:background="#android:drawable/toast_frame"
/>
and with different bg color:
<LinearLayout
android:layout_height="64dp"
android:layout_width="fill_parent"
android:gravity="center"
android:background="#android:drawable/toast_frame"
android:padding="4dp"
>
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Button shadow"
android:background="#33b5e5"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="#fff"
android:layout_gravity="center|bottom"
/>
</LinearLayout>

Try this.. layout_shadow.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#CABBBBBB"/>
<corners android:radius="2dp" />
</shape>
</item>
<item
android:left="0dp"
android:right="0dp"
android:top="0dp"
android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:radius="2dp" />
</shape>
</item>
</layer-list>
Apply to your layout like this
android:background="#drawable/layout_shadow"

I know this is old, but most of these answers require a ton of extra code.
If you have a light colored background, you can simply use this:
android:elevation="25dp"

Actually I agree with #odedbreiner but I put the dialog_frame inside the first layer and hide the black background under the white layer.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#android:drawable/dialog_frame"
android:right="2dp" android:left="2dp" android:bottom="2dp" android:top="5dp" >
<shape android:shape="rectangle">
<corners android:radius="5dp"/>
</shape>
</item>
<item>
<shape
android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>

save this 9.png. (change name it to 9.png)
2.save it in your drawable.
3.set it to your layout.
4.set padding.
For example :
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/shadow"
android:paddingBottom="6dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="6dp"
>
.
.
.
</LinearLayout>

Create a new XML by example named "shadow.xml" at DRAWABLE with the following code (you can modify it or find another better):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/middle_grey"/>
</shape>
</item>
<item android:left="2dp"
android:right="2dp"
android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#color/white"/>
</shape>
</item>
</layer-list>
After creating the XML in the LinearLayout or another Widget you want to create shade, you use the BACKGROUND property to see the efect. It would be something like :
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingRight="#dimen/margin_med"
android:background="#drawable/shadow"
android:minHeight="?attr/actionBarSize"
android:gravity="center_vertical">

You can use following class for xml tag:
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.FloatRange;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import com.webappmate.weeassure.R;
/**
* Created by GIGAMOLE on 13.04.2016.
*/
public class ShadowLayout extends FrameLayout {
// Default shadow values
private final static float DEFAULT_SHADOW_RADIUS = 30.0F;
private final static float DEFAULT_SHADOW_DISTANCE = 15.0F;
private final static float DEFAULT_SHADOW_ANGLE = 45.0F;
private final static int DEFAULT_SHADOW_COLOR = Color.DKGRAY;
// Shadow bounds values
private final static int MAX_ALPHA = 255;
private final static float MAX_ANGLE = 360.0F;
private final static float MIN_RADIUS = 0.1F;
private final static float MIN_ANGLE = 0.0F;
// Shadow paint
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setFilterBitmap(true);
}
};
// Shadow bitmap and canvas
private Bitmap mBitmap;
private final Canvas mCanvas = new Canvas();
// View bounds
private final Rect mBounds = new Rect();
// Check whether need to redraw shadow
private boolean mInvalidateShadow = true;
// Detect if shadow is visible
private boolean mIsShadowed;
// Shadow variables
private int mShadowColor;
private int mShadowAlpha;
private float mShadowRadius;
private float mShadowDistance;
private float mShadowAngle;
private float mShadowDx;
private float mShadowDy;
public ShadowLayout(final Context context) {
this(context, null);
}
public ShadowLayout(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public ShadowLayout(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
setLayerType(LAYER_TYPE_HARDWARE, mPaint);
// Retrieve attributes from xml
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShadowLayout);
try {
setIsShadowed(typedArray.getBoolean(R.styleable.ShadowLayout_sl_shadowed, true));
setShadowRadius(
typedArray.getDimension(
R.styleable.ShadowLayout_sl_shadow_radius, DEFAULT_SHADOW_RADIUS
)
);
setShadowDistance(
typedArray.getDimension(
R.styleable.ShadowLayout_sl_shadow_distance, DEFAULT_SHADOW_DISTANCE
)
);
setShadowAngle(
typedArray.getInteger(
R.styleable.ShadowLayout_sl_shadow_angle, (int) DEFAULT_SHADOW_ANGLE
)
);
setShadowColor(
typedArray.getColor(
R.styleable.ShadowLayout_sl_shadow_color, DEFAULT_SHADOW_COLOR
)
);
} finally {
typedArray.recycle();
}
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// Clear shadow bitmap
if (mBitmap != null) {
mBitmap.recycle();
mBitmap = null;
}
}
public boolean isShadowed() {
return mIsShadowed;
}
public void setIsShadowed(final boolean isShadowed) {
mIsShadowed = isShadowed;
postInvalidate();
}
public float getShadowDistance() {
return mShadowDistance;
}
public void setShadowDistance(final float shadowDistance) {
mShadowDistance = shadowDistance;
resetShadow();
}
public float getShadowAngle() {
return mShadowAngle;
}
#SuppressLint("SupportAnnotationUsage")
#FloatRange
public void setShadowAngle(#FloatRange(from = MIN_ANGLE, to = MAX_ANGLE) final float shadowAngle) {
mShadowAngle = Math.max(MIN_ANGLE, Math.min(shadowAngle, MAX_ANGLE));
resetShadow();
}
public float getShadowRadius() {
return mShadowRadius;
}
public void setShadowRadius(final float shadowRadius) {
mShadowRadius = Math.max(MIN_RADIUS, shadowRadius);
if (isInEditMode()) return;
// Set blur filter to paint
mPaint.setMaskFilter(new BlurMaskFilter(mShadowRadius, BlurMaskFilter.Blur.NORMAL));
resetShadow();
}
public int getShadowColor() {
return mShadowColor;
}
public void setShadowColor(final int shadowColor) {
mShadowColor = shadowColor;
mShadowAlpha = Color.alpha(shadowColor);
resetShadow();
}
public float getShadowDx() {
return mShadowDx;
}
public float getShadowDy() {
return mShadowDy;
}
// Reset shadow layer
private void resetShadow() {
// Detect shadow axis offset
mShadowDx = (float) ((mShadowDistance) * Math.cos(mShadowAngle / 180.0F * Math.PI));
mShadowDy = (float) ((mShadowDistance) * Math.sin(mShadowAngle / 180.0F * Math.PI));
// Set padding for shadow bitmap
final int padding = (int) (mShadowDistance + mShadowRadius);
setPadding(padding, padding, padding, padding);
requestLayout();
}
private int adjustShadowAlpha(final boolean adjust) {
return Color.argb(
adjust ? MAX_ALPHA : mShadowAlpha,
Color.red(mShadowColor),
Color.green(mShadowColor),
Color.blue(mShadowColor)
);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Set ShadowLayout bounds
mBounds.set(
0, 0, MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)
);
}
#Override
public void requestLayout() {
// Redraw shadow
mInvalidateShadow = true;
super.requestLayout();
}
#Override
protected void dispatchDraw(final Canvas canvas) {
// If is not shadowed, skip
if (mIsShadowed) {
// If need to redraw shadow
if (mInvalidateShadow) {
// If bounds is zero
if (mBounds.width() != 0 && mBounds.height() != 0) {
// Reset bitmap to bounds
mBitmap = Bitmap.createBitmap(
mBounds.width(), mBounds.height(), Bitmap.Config.ARGB_8888
);
// Canvas reset
mCanvas.setBitmap(mBitmap);
// We just redraw
mInvalidateShadow = false;
// Main feature of this lib. We create the local copy of all content, so now
// we can draw bitmap as a bottom layer of natural canvas.
// We draw shadow like blur effect on bitmap, cause of setShadowLayer() method of
// paint does`t draw shadow, it draw another copy of bitmap
super.dispatchDraw(mCanvas);
// Get the alpha bounds of bitmap
final Bitmap extractedAlpha = mBitmap.extractAlpha();
// Clear past content content to draw shadow
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
// Draw extracted alpha bounds of our local canvas
mPaint.setColor(adjustShadowAlpha(false));
mCanvas.drawBitmap(extractedAlpha, mShadowDx, mShadowDy, mPaint);
// Recycle and clear extracted alpha
extractedAlpha.recycle();
} else {
// Create placeholder bitmap when size is zero and wait until new size coming up
mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
}
}
// Reset alpha to draw child with full alpha
mPaint.setColor(adjustShadowAlpha(true));
// Draw shadow bitmap
if (mCanvas != null && mBitmap != null && !mBitmap.isRecycled())
canvas.drawBitmap(mBitmap, 0.0F, 0.0F, mPaint);
}
// Draw child`s
super.dispatchDraw(canvas);
}
}
use Tag in xml like this:
<yourpackagename.ShadowLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
app:sl_shadow_color="#9e000000"
app:sl_shadow_radius="4dp">
<child views>
</yourpackagename.ShadowLayout>
UPDATE
put the below code in attrs.xml in resource>>values
<declare-styleable name="ShadowLayout">
<attr name="sl_shadowed" format="boolean"/>
<attr name="sl_shadow_distance" format="dimension"/>
<attr name="sl_shadow_angle" format="integer"/>
<attr name="sl_shadow_radius" format="dimension"/>
<attr name="sl_shadow_color" format="color"/>
</declare-styleable>

One possible solution is using nine patch image like this http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
OR
I have done this in the following way. This is my main layout in which round_corner.xml and drop_shadow.xml used as background resource. round_corner_two is same like round_corner.xml only the color attribute is different. copy the round_corner.xml,drop_shadow.xml and round_conere_two.xml into drawable folder.
<RelativeLayout
android:id="#+id/facebook_id"
android:layout_width="250dp"
android:layout_height="52dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="28dp"
android:background="#drawable/round_corner" >
<LinearLayout
android:id="#+id/shadow_id"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="1dp"
android:background="#drawable/drop_shadow" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginBottom="2dp"
android:background="#drawable/round_corner_two"
android:gravity="center"
android:text="#string/fb_butn_text"
android:textColor="#color/white" >
</TextView>
</LinearLayout>
</RelativeLayout>
round_corner.xml:
<?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="#ffffff" >
</solid>
<!-- view border color and width -->
<stroke
android:width="0dp"
android:color="#3b5998" >
</stroke>
<!-- If you want to add some padding -->
<padding
android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp" >
</padding>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
drop_shadow.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item >
<shape
android:shape="rectangle">
<solid android:color="#android:color/darker_gray" />
<corners android:radius="12dp"/>
</shape>
</item>
<item android:right="1dp" android:left="1dp" android:bottom="5dp">
<shape
android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>

i know this is way too late. but i had the same requirement. i solved like this
<android.support.v7.widget.CardView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardUseCompatPadding="true"
app:cardElevation="4dp"
app:cardCornerRadius="3dp" >
<!-- put whatever you want -->
</android.support.v7.widget.CardView>
you need to add dependency:
compile 'com.android.support:cardview-v7:25.0.1'

set this xml drwable as your background;---
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Bottom 2dp Shadow -->
<item>
<shape android:shape="rectangle" >
<solid android:color="#d8d8d8" />-->Your shadow color<--
<corners android:radius="15dp" />
</shape>
</item>
<!-- White Top color -->
<item android:bottom="3px" android:left="3px" android:right="3px" android:top="3px">-->here you can customize the shadow size<---
<shape android:shape="rectangle" >
<solid android:color="#FFFFFF" />
<corners android:radius="15dp" />
</shape>
</item>
</layer-list>

Related

Android Layout transparent layout background with underline

I am trying to have a layout background drawable, which will be only gradient underline with 1-2 dp height and rest is transparent, so the upper part will have the parent's background.
Here is what I have.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android>
<!-- underline color -->
<item>
<shape>
<gradient
android:startColor="#color/colorPrimaryDark"
android:endColor="#FFFFFFFF"
android:centerY="0.5"
android:angle="0"/>
</shape>
</item>
<!-- main color -->
<item android:bottom="2.5dp">
<shape android:shape="rectangle">
<solid android:color="#color/white" />
<padding
android:top="4dp"
android:bottom="4dp" />
</shape>
</item>
If I change the solid color in "main color" to transparent, whole background will be using "underline color" settings.
The technique you use to create a line on the bottom of the view works if the color of the layer overlaying the gradient layer is opaque. What you are trying to do is to apply a transparent layer that replaces (erases) the underlying gradient. That is not how it works: A transparent overlay leaves the underlying color, here a gradient, untouched.
Here is an alternate layer-list drawable that you can use for API 23+:
underline_drawable.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:gravity="bottom">
<shape>
<size android:height="2dp" />
<gradient
android:angle="0"
android:centerY="0.5"
android:endColor="#FFFFFFFF"
android:startColor="#color/colorPrimaryDark" />
</shape>
</item>
</layer-list>
Here is what it looks like:
Prior to API 23, you can use the following custom drawable, but it must be set in code.
GradientUnderline.java
public class GradientUnderline extends Drawable {
private Shader mShader;
private final Paint mPaint;
private int mHeight = -1;
private int mStartColor = Color.BLACK;
private int mEndColor = Color.WHITE;
private int mLastWidth;
public GradientUnderline() {
mPaint = new Paint();
}
public GradientUnderline(int lineHeight, int startColor, int endColor) {
mPaint = new Paint();
mHeight = lineHeight;
mStartColor = startColor;
mEndColor = endColor;
}
#Override
public void draw(#NonNull Canvas canvas) {
if (mShader == null || getBounds().width() != mLastWidth) {
mLastWidth = getBounds().width();
mShader = new LinearGradient(0, 0, getBounds().width(), mHeight, mStartColor,
mEndColor, Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
}
canvas.drawRect(0, getBounds().height() - mHeight, getBounds().width(),
getBounds().height(), mPaint);
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(#Nullable ColorFilter colorFilter) {
}
#Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
}
I missed the availability of android:gravity initially because it is not mentioned on the "Drawable Resources" page. It is mentioned, however, in the LayerDrawable documentation.
Why problem occurs: Shape at first item will draw the gradient in entire region. After setting colour to second item will hide the top item region except ay 2.5dp at bottom. So whenever you set transparent colour to second item it automatically show the top level item that is gradient region..
Here i suggest the way to use but you can set to fixed height in view.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="47dp">
<shape>
<gradient
android:startColor="#color/colorPrimaryDark"
android:endColor="#FFFFFFFF"
android:centerY="0.5"
android:angle="0"/>
</shape>
</item>
</layer-list>
View.xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#drawable/bottom_line">
</RelativeLayout>
Change size according to your needs..!
OUTPUT

How to add shadow around circular imageview

I want to add shadow around circular imageView.
Here is my code.
I want to make like this image
This is my .xml file
check this image.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="#+id/layoutTop"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#355482" >
</RelativeLayout>
<RelativeLayout
android:id="#+id/layoutBottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_below="#+id/layoutTop"
android:background="#drawable/loading" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="113dp"
android:text="Profile"
android:textColor="#355482"
android:textSize="20dp"
android:textStyle="bold" />
</RelativeLayout>
<ImageView
android:id="#+id/overlapImage"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="132dp"
android:adjustViewBounds="true"
android:background="#drawable/round_image"
android:src="#drawable/ic_launcher" />
this is round_image.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#ffffff" />
<corners android:radius="2dp"/>
<size
android:height="80dp"
android:width="80dp" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
</shape>
I try some code for shadow effect but it's not working.
Hope this will help you:)
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#color/gray"/>
<!--shadow Color-->
</shape>
</item>
<item
android:left="0dp"
android:right="0dp"
android:top="0dp"
android:bottom="3dp">
<shape android:shape="oval">
<solid android:color="#color/lightgrey"/>//Background Color
</shape>
</item>
</layer-list>
Change the background Color and Shadow color as you want..
It is way simpler than you think. Your ImageView needs to appear rounded based on an oval background, as it is squared by default. Then you need to include elevation, and it will show as you expected. You cannot set the oval background transparent as it won't allow for
shadow elevation.
this is drawable/white_oval.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#android:color/white"/>
</shape>
</item>
</layer-list>
Now in your imageview, I am skipping here how you include your image
<ImageView
android:id="#+id/alert_icon"
android:layout_width="#dimen/alert_icon"
android:layout_height="#dimen/alert_icon"
android:contentDescription="#string/your_shadow_rulez"
android:background="#drawable/white_oval"
android:elevation="#dimen/elevation_fab" />
of course make sure your image view both width and height match. The bigger the elevation the larger the shadow
see how simple and nice this looks
Create a circle_shadow.xml file and use this code it work good for me. Make changes the radius according to your requirement.
circle_shadow.xml
<!-- Drop Shadow -->
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#00CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#10CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#20CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#30CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#50CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<!-- Background Color (white) -->
<item>
<shape android:shape="oval">
<solid android:color="#android:color/white" />
<corners android:radius="3dp" />
</shape>
</item>
Before answering I want to give some advice. You just have to put title of your question in Google. I tried to search like circular imageview with shadow android:
Without use of Library:
Change android:color="#BDBDBD" in shape tag.
Your round_image.xml will be like:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#BDBDBD" />
<corners android:radius="2dp"/>
<size
android:height="80dp"
android:width="80dp" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
</shape>
Using Library:
Have you tried this CircularImageView
You can use this library or if you don't want to use then get some code from this library inner res folder.
Thank you.
Here, I share my best practice to show a shadow effect to a circular image/resource with some details.
The above example image's icon is 56dp x 56dp and is cropped with a zoomed view so it may not look attractive but the results will show good on an actual device under the naked eye.
The above example is delivered by using:
Some amount of elevation, to let shadow.
Provide margin to the view almost double of elevation to fit the shadow.
Ensure the parent view provides the space almost double of elevation to fit the shadow.
Create and use an OutlineProvider to create the shadow.
Now here we begin with the code.
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="#dimen/margin_14dp"> // Point no. 3
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/img"
android:layout_width="#dimen/margin_56dp"
android:layout_height="#dimen/margin_56dp"
android:layout_margin="#dimen/margin_14dp" // Point no. 2
android:elevation="#dimen/margin_8dp" // Point no. 1
android:src="#drawable/ic_bell" />
</FrameLayout>
Let's proceed to point no. 4, here is the OutlineProvider class for a Circular Outline.
import android.graphics.Outline;
import android.view.View;
import android.view.ViewOutlineProvider;
public class CircularOutlineProvider extends ViewOutlineProvider {
#Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), (view.getWidth() / 2F));
}
}
We left to use the OutlineProvider in our Java/Kotlin class to do the magic at runtime.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
findViewById(R.id.img).setOutlineProvider(new CircularOutlineProvider());
End of Magic Session!
For more experience and enhance details, please read the official article.
Add this xml code in your drawable layout and add it in your background:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item>
<shape android:shape="oval">
<gradient
android:startColor="#FF000000"
android:endColor="#00000000"
android:gradientRadius="31dp"
android:type="radial"
/>
</shape>
</item>
<item android:top="4dp" android:left="4dp" android:right="4dp" android:bottom="4dp">
<shape android:shape="oval">
<size android:width="55dp"
android:height="55dp"/>
<solid android:color="#android:color/white" />
</shape>
</item>
</layer-list>
</item>
</selector>
This Class is Custom Circular Imageview with shadow, Stroke,saturation and using this Custom Circular ImageView you can make your image in Circular Shape with Radius. Guys for Circular Shadow ImageView No need Github this class is enough. Adding CircularImageView to your root layout dynamically.
*Adding Circular ImageView to your layout dynamically*
RelativeLayout rootLayout= (RelativeLayout) findViewById(R.id.rootLayout);
rootLayout.addView(new CircularImageView(this,200,200,imageBitmap));
public CircularImageView(Context context, int width, int height, Bitmap bitmap) {
super(context);
this.context = context;
this.width = width;
this.height = height;
------> here "bitmap" is the square shape(width* width) scaled bitmap ..
this.bitmap = bitmap;
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
paint3=new Paint();
paint3.setStyle(Paint.Style.STROKE);
paint3.setColor(Color.WHITE);
paint3.setAntiAlias(true);
paintBorder = new Paint();
imagePaint= new Paint();
paintBorder.setColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
this.bitmap2 = Bitmap.createScaledBitmap(bitmap, (bitmap.getWidth() - 40), (bitmap.getHeight() - 40), true);
imagePaint.setAntiAlias(true);
invalidate();
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Shader b;
if (bitmap3 != null)
b = new BitmapShader(bitmap3, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
else
b = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
imagePaint.setShader(b);
canvas.drawBitmap(maskedBitmap(), 20, 20, null);
}
private Bitmap maskedBitmap()
{
Bitmap l1 = Bitmap.createBitmap(width,width, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(l1);
paintBorder.setShadowLayer(radius, x, y, Color.parseColor("#454645"));
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
final RectF rect = new RectF();
rect.set(20, 20, bitmap2.getWidth(), bitmap2.getHeight());
canvas.drawRoundRect(rect, corner_radius, corner_radius, paintBorder);
canvas.drawRoundRect(rect, corner_radius, corner_radius, imagePaint);
if (strokeWidth!=0.0f)
{
paint3.setStrokeWidth(strokeWidth);
canvas.drawRoundRect(rect, corner_radius, corner_radius, paint3);
}
paint.setXfermode(null);
return l1;
}
------> use seekbar here, here you have to pass "0 -- 250" here corner radius will change ..
public void setCornerRadius(int corner_radius)
{
this.corner_radius = corner_radius;
invalidate();
}
-------->use seekbar here, here you have to pass "0 -- 10.0f" here shadow radius will change
public void setShadow(float radius)
{
this.radius = radius;
invalidate();
}
----> use seekbar here, here you have to pass "0 -- 10.0f" here stroke size will change
public void setStroke(float stroke)
{
this.strokeWidth = stroke;
invalidate();
}
private Bitmap updateSat(Bitmap src, float settingSat)
{
int w = src.getWidth();
int h = src.getHeight();
Bitmap bitmapResult =
Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(settingSat);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, paint);
return bitmapResult;
}
--------> use seekbar here, here you have to pass "0 -- 2.0f" here saturation will change
public void setSaturation(float sat)
{
System.out.println("qqqqqqqqqq "+sat);
bitmap3=updateSat(bitmap2, sat);
invalidate();
}
}
--------> Seekbar to change radius
radius_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
text_radius.setText(""+progress);
circularImageView.setCornerRadius(progress);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change shadow
shadow_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
float f= 4+progress/10.0f;
text_shadow.setText(""+progress);
circularImageView.setShadow(f);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change saturation
saturation_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
int progressSat = saturation_seekbar.getProgress();
float sat = (float) ((progressSat*4 / 100.0f)-1.0f);
circularImageView.setSaturation(sat);
text_saturation.setText(""+progressSat);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change stroke
stroke_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
if (progress==0)
{
float f=(progress*10.0f/100.0f);
circularImageView.setStroke(f);
}
else
{
float f=(progress*10.0f/100.0f);
circularImageView.setStroke(f);
}
text_stroke.setText(""+progress);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
//radius seekbar in xml file
<SeekBar
android:layout_width="match_parent"
android:layout_gravity="center"
android:progress="50"
android:max="250"
android:id="#+id/radius_seekbar"
android:layout_height="wrap_content" />
//saturation seekbar in xml file
<SeekBar
android:layout_width="match_parent"
android:layout_gravity="center"
android:progress="50"
android:max="100"
android:id="#+id/saturation_seekbar"
android:layout_height="wrap_content" />
//shadow seekbar in xml file
<SeekBar
android:layout_width="match_parent"
android:layout_gravity="center"
android:progress="0"
android:max="100"
android:id="#+id/shadow_seekbar"
android:layout_height="wrap_content" />
//stroke seekbar in xml file
<SeekBar
android:layout_width="match_parent"
android:layout_gravity="center"
android:progress="0"
android:max="100"
android:id="#+id/stroke _seekbar"
android:layout_height="wrap_content" />

Android how to create triangle and rectangle shape programmatically?

How can we create ballon drawable shape as below. where we can change the color of it dynamically.
Here it is XML for triangle and rectangle. save it inside drawable folder.
triangle.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item >
<rotate
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="-40%"
android:pivotY="87%" >
<shape
android:shape="rectangle" >
<stroke android:color="#android:color/transparent" android:width="10dp"/>
<solid
android:color="#000000" />
</shape>
</rotate>
</item>
</layer-list>
rectangle.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<solid android:color="#B2E3FA" />
</shape>
</item>
</layer-list>
and layout for shape you require.
<RelativeLayout
android:id="#+id/rlv1"
android:layout_width="150dp"
android:layout_height="50dp"
android:background="#drawable/rectangle" />
<RelativeLayout
android:id="#+id/rlv2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_below="#+id/rlv1"
android:background="#drawable/triangle"
android:rotation="180" />
set margin according you required.
Source
If you want a border for your layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linear_root"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="#+id/text_message"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:background="#drawable/bg_rectangle"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:padding="8dp"
android:text="Abc"
/>
<ImageView
android:id="#+id/image_arrow"
android:layout_marginTop="-1.5dp"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="center_horizontal"
android:background="#drawable/icon_arrow_down"
/>
</LinearLayout>
bg_rectangle
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#eaeaea" />
<stroke
android:width="1dp"
android:color="#f00" />
<corners android:radius="8dp" />
</shape>
icon_arrow_down, or you can create triangle by vector like here
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="45"
android:pivotX="135%"
android:pivotY="15%"
android:toDegrees="45"
>
<shape android:shape="rectangle">
<solid android:color="#eaeaea"/>
<stroke
android:width="1dp"
android:color="#f00" />
</shape>
</rotate>
</item>
</layer-list>
The clean and right way to do this whilst keeping it dynamic is to extend the View class.
Then in the onDraw you would do something like this:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBackground(canvas);
}
private void drawBackground(Canvas canvas) {
int width = (int) mWidth;
int height = (int) mHeight;
Point a = new Point(0, 0);
Point b = new Point(width, 0);
Point c = new Point(width, height - mPointHeight);//mPointedHeight is the length of the triangle... in this case we have it dynamic and can be changed.
Point d = new Point((width/2)+(mPointedHeight/2), height - mPointHeight);
Point e = new Point((width/2), height);// this is the sharp point of the triangle
Point f = new Point((width/2)-(mPointedHeight/2), height - mPointHeight);
Point g = new Point(0, height - mPointHeight);
Path path = new Path();
path.moveTo(a.x, a.y);
path.lineTo(b.x, b.y);
path.lineTo(c.x, c.y);
path.lineTo(d.x, d.y);
path.lineTo(e.x, e.y);
path.lineTo(f.x, f.y);
path.lineTo(g.x, g.y);
canvas.drawPath(path, mPointedBackgroundPaint);// mPointedBackgroundPaint is whatever color you want as the fill.
}
There you go, no unnecessary layering or code that isn't dynamic or clean. You could also add the text in the box too.
Use a triangle image and a rectangular image and mathematically align them in the above mentioned format. Use color filtering to dynamically change its color.
You can even draw them on a custom view, using vector graphics, using custom colors, and that would be another way of solving this problem.
Create custom view and draw traingle with canvas
package com.example.dickbutt;
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.view.View;
public class TriangleShapeView extends View {
public int colorCode = Color.MAGENTA;
public int getColorCode() {
return colorCode;
}
public void setColorCode(int colorCode) {
this.colorCode = colorCode;
}
public TriangleShapeView(Context context) {
super(context);
}
public TriangleShapeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public TriangleShapeView(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int w = getWidth() / 2;
int h = getHeight() / 2;
Path path = new Path();
path.moveTo(0, 0);
path.lineTo(w, 2 * h);
path.lineTo(2 * w, 0);
path.lineTo(0, 0);
path.close();
Paint p = new Paint();
p.setColor(colorCode);
p.setAntiAlias(true);
canvas.drawPath(path, p);
}
}
Result
Usage
<TextView
android:id="#+id/progress_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#android:color/holo_purple"
android:gravity="center_horizontal"
android:text="200,0000000"
android:textColor="#fff" />
<com.example.dickbutt.TriangleShapeView
android:id="#+id/textView1"
android:layout_width="10dp"
android:layout_height="20dp"
android:layout_below="#+id/progress_value"
android:layout_centerHorizontal="true"
android:background="#drawable/rectangle"
android:gravity="center_horizontal"
android:textSize="10sp" />
Advantages
Change shape according to width and height of view .
Highly customization possible.
Look cleaner
Use Canvas in onDraw method inside custom View class.
Other way is to use Path class.
First you can create one xml inside drawable folder
That xml will be responsible for the border color of rectangle shape
You can create such border shape with below code
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#B2E3FA" />
</shape>
</item>
<item android:left="5dp" android:bottom="5dp" android:top="5dp" >
<shape android:shape="rectangle">
<solid android:color="#D8D8D8" />
</shape>
</item>
</layer-list>
well this will create a required border to rectangle shape, you need to assign background of that rectangle shape with this drawable like this
android:background="#drawable/bg"
where bg is xml file name which has been saved on drawable folder
After that you need to put that triangle exactly below to rectangle object.
I hope you understood my logic

How to programmatically create or alter a drawable made of lines of different colors

I have to draw a 3dp line to represent a level completion in a quizz game.
This line must be of 2 colors. For example, if user has completed 40% of the level, the line will be red for the first 40% of the line, the other 60% being grey.
I have managed to do that with a drawable :
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="line" >
<size android:height="3dp" android:width="40dp"/>
<stroke
android:width="1dp"
android:color="#FFFC10" />
</shape>
</item>
<item android:left="40dp">
<shape android:shape="line" >
<size android:height="3dp" android:width="60dp" />
<stroke
android:width="1dp"
android:color="#DDDDDD" />
</shape>
</item>
</layer-list>
And then I display it with an ImageView :
<ImageView
android:id="#+id/row_completion_bar"
android:src="#drawable/completion_bar"
android:layout_width="100dp"
android:layout_height="3dp" />
... but now, I must of course be able to change this 40%/60% ration depending of the actuel user completion.
First question: what is the best most efficient way to do it ? Change the drawable at runtime ? or create a new drawable at runtime in Java ?
Second question: how to do it ? I tried both ways (recreate this drawable in java code / alter the xml drawable at runtime) and didn't succeeded :-(
Any help will be greatly appreciated.
so this is a custom Drawable you can use:
class LineDrawable extends Drawable {
private Paint mPaint;
public LineDrawable() {
mPaint = new Paint();
mPaint.setStrokeWidth(3);
}
#Override
public void draw(Canvas canvas) {
int lvl = getLevel();
Rect b = getBounds();
float x = b.width() * lvl / 10000.0f;
float y = (b.height() - mPaint.getStrokeWidth()) / 2;
mPaint.setColor(0xffff0000);
canvas.drawLine(0, y, x, y, mPaint);
mPaint.setColor(0xff00ff00);
canvas.drawLine(x, y, b.width(), y, mPaint);
}
#Override
protected boolean onLevelChange(int level) {
invalidateSelf();
return true;
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter cf) {
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
and the test code:
View v = new View(this);
final LineDrawable d = new LineDrawable();
d.setLevel(4000);
v.setBackgroundDrawable(d);
setContentView(v);
OnTouchListener l = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int lvl = (int) (10000 * event.getX() / v.getWidth());
d.setLevel(lvl);
return true;
}
};
v.setOnTouchListener(l);
How about using a progress bar? The style of the done and to-do markers can be set either programatically or via xml files.
Your code will also be more readable/maintainable because you'll be using the right widget for the job. Your layout will contain:
<ProgressBar
android:id="#+id/progressBar"
android:layout_height="3dip"
android:layout_width="match_parent"
android:progressDrawable="#drawable/progress_bar" />
You can update the bar from your code using e.g.:
ProgressBar bar = (ProgressBar)findViewById(R.id.progressBar);
bar.setProgress(40);
This example overrides the style of the bar (as directed by the progressDrawable attribute), using a res/drawable/progress_bar.xml file - contents below. This one has extra niceness like gradient shading and rounded corners; adjust as you see fit:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:angle="270"
android:centerColor="#ff5a5d5a"
android:centerY="0.5"
android:endColor="#ff747674"
android:startColor="#ff9d9e9d" />
</shape>
</item>
<item android:id="#android:id/progress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:angle="0"
android:endColor="#ff009900"
android:startColor="#ff000099" />
</shape>
</clip>
</item>
</layer-list>
Credit to http://www.tiemenschut.com/how-to-customize-android-progress-bars/, which gives much more detail on how to customise progress bars.
I found a way to do this. Don't know if it's the most efficient way, but here it is:
I used a RelativeLayout to superpose ImageViews with background color.
in layout.xml:
<RelativeLayout style="#style/CompletionBar">
<ImageView
android:id="#+id/row_completion_bar_0"
style="#style/CompletionBar0" />
<ImageView
android:id="#+id/row_completion_bar_1"
style="#style/CompletionBar1" />
</RelativeLayout>
in styles.xml:
<!-- Completion Bar (Relative Layout) -->
<style name="CompletionBar">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
<!-- Completion Bar 0 (ImageView) -->
<style name="CompletionBar0">
<item name="android:layout_width">100dp</item>
<item name="android:layout_height">2dp</item>
<item name="android:background">#CCCCCC</item>
</style>
<!-- Completion Bar 1 (ImageView) -->
<style name="CompletionBar1">
<item name="android:layout_width">40dp</item>
<item name="android:layout_height">2dp</item>
<item name="android:background">#555555</item>
</style>
in java file:
ImageView cb1 = (ImageView)row.findViewById(R.id.row_completion_bar_1);
cb1.getLayoutParams().width = 40; /* Value in pixels, must convert to dp */
This snippet will work for all api
Use this:
Drawable drawable = editText.getBackground();
drawable.setColorFilter(editTextColor, PorterDuff.Mode.SRC_ATOP);
if(Build.VERSION.SDK_INT > 16) {
editText.setBackground(drawable);
}else{
editText.setBackgroundDrawable(drawable);
}

How to make layout with rounded corners..?

How can I make a layout with rounded corners? I want to apply rounded corners to my LinearLayout.
1: Define layout_bg.xml in drawables:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="3dp" android:color="#B1BCBE" />
<corners android:radius="10dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
2: Add layout_bg.xml as background to your layout
android:background="#drawable/layout_bg"
For API 21+, Use Clip Views
Rounded outline clipping was added to the View class in API 21. See this training doc or this reference for more info.
This in-built feature makes rounded corners very easy to implement. It works on any view or layout and supports proper clipping.
Here's What To Do:
Create a rounded shape drawable and set it as your view's background:
android:background="#drawable/round_outline"
Clip to outline in code: setClipToOutline(true)
The documentation used to say that you can set android:clipToOutline="true" the XML, but this bug is now finally resolved and the documentation now correctly states that you can only do this in code.
What It Looks Like:
Special Note About ImageViews
setClipToOutline() only works when the View's background is set to a shape drawable. If this background shape exists, View treats the background's outline as the borders for clipping and shadowing purposes.
This means that if you want to round the corners on an ImageView with setClipToOutline(), your image must come from android:src instead of android:background (since background is used for the rounded shape). If you MUST use background to set your image instead of src, you can use this nested views workaround:
Create an outer layout with its background set to your shape drawable
Wrap that layout around your ImageView (with no padding)
The ImageView (including anything else in the layout) will now be clipped to the outer layout's rounded shape.
Here's a copy of a XML file to create a drawable with a white background, black border and rounded corners:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffffff"/>
<stroke android:width="3dp"
android:color="#ff000000"
/>
<padding android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
/>
<corners android:bottomRightRadius="7dp" android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp" android:topRightRadius="7dp"/>
</shape>
save it as a xml file in the drawable directory,
Use it like you would use any drawable background(icon or resource file) using its resource name (R.drawable.your_xml_name)
Use CardView in android v7 support library.
Though it's a bit heavy, it solves all problem, and easy enough.
Not like the set drawable background method, it could clip subviews successfully.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#android:color/transparent"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="0dp"
card_view:contentPadding="0dp">
<YOUR_LINEARLAYOUT_HERE>
</android.support.v7.widget.CardView>
I have done this way:
Check Screenshot:
Create drawable file named with custom_rectangle.xml in drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#android:color/white" />
<corners android:radius="10dip" />
<stroke
android:width="1dp"
android:color="#android:color/white" />
</shape>
Now apply Rectangle background on View:
mView.setBackground(R.drawlable.custom_rectangle);
Done
I think a better way to do it is to merge 2 things:
make a bitmap of the layout, as shown here.
make a rounded drawable from the bitmap, as shown here
set the drawable on an imageView.
This will handle cases that other solutions have failed to solve, such as having content that has corners.
I think it's also a bit more GPU-friendly, as it shows a single layer instead of 2 .
The only better way is to make a totally customized view, but that's a lot of code and might take a lot of time. I think that what I suggested here is the best of both worlds.
Here's a snippet of how it can be done:
RoundedCornersDrawable.java
/**
* shows a bitmap as if it had rounded corners. based on :
* http://rahulswackyworld.blogspot.co.il/2013/04/android-drawables-with-rounded_7.html
* easy alternative from support library: RoundedBitmapDrawableFactory.create( ...) ;
*/
public class RoundedCornersDrawable extends BitmapDrawable {
private final BitmapShader bitmapShader;
private final Paint p;
private final RectF rect;
private final float borderRadius;
public RoundedCornersDrawable(final Resources resources, final Bitmap bitmap, final float borderRadius) {
super(resources, bitmap);
bitmapShader = new BitmapShader(getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
final Bitmap b = getBitmap();
p = getPaint();
p.setAntiAlias(true);
p.setShader(bitmapShader);
final int w = b.getWidth(), h = b.getHeight();
rect = new RectF(0, 0, w, h);
this.borderRadius = borderRadius < 0 ? 0.15f * Math.min(w, h) : borderRadius;
}
#Override
public void draw(final Canvas canvas) {
canvas.drawRoundRect(rect, borderRadius, borderRadius, p);
}
}
CustomView.java
public class CustomView extends ImageView {
private View mMainContainer;
private boolean mIsDirty=false;
// TODO for each change of views/content, set mIsDirty to true and call invalidate
#Override
protected void onDraw(final Canvas canvas) {
if (mIsDirty) {
mIsDirty = false;
drawContent();
return;
}
super.onDraw(canvas);
}
/**
* draws the view's content to a bitmap. code based on :
* http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/
*/
public static Bitmap drawToBitmap(final View viewToDrawFrom, final int width, final int height) {
// Create a new bitmap and a new canvas using that bitmap
final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bmp);
viewToDrawFrom.setDrawingCacheEnabled(true);
// Supply measurements
viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
// Apply the measures so the layout would resize before drawing.
viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight());
// and now the bmp object will actually contain the requested layout
canvas.drawBitmap(viewToDrawFrom.getDrawingCache(), 0, 0, new Paint());
return bmp;
}
private void drawContent() {
if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0)
return;
final Bitmap bitmap = drawToBitmap(mMainContainer, getMeasuredWidth(), getMeasuredHeight());
final RoundedCornersDrawable drawable = new RoundedCornersDrawable(getResources(), bitmap, 15);
setImageDrawable(drawable);
}
}
EDIT: found a nice alternative, based on "RoundKornersLayouts" library. Have a class that will be used for all of the layout classes you wish to extend, to be rounded:
//based on https://github.com/JcMinarro/RoundKornerLayouts
class CanvasRounder(cornerRadius: Float, cornerStrokeColor: Int = 0, cornerStrokeWidth: Float = 0F) {
private val path = android.graphics.Path()
private lateinit var rectF: RectF
private var strokePaint: Paint?
var cornerRadius: Float = cornerRadius
set(value) {
field = value
resetPath()
}
init {
if (cornerStrokeWidth <= 0)
strokePaint = null
else {
strokePaint = Paint()
strokePaint!!.style = Paint.Style.STROKE
strokePaint!!.isAntiAlias = true
strokePaint!!.color = cornerStrokeColor
strokePaint!!.strokeWidth = cornerStrokeWidth
}
}
fun round(canvas: Canvas, drawFunction: (Canvas) -> Unit) {
val save = canvas.save()
canvas.clipPath(path)
drawFunction(canvas)
if (strokePaint != null)
canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, strokePaint)
canvas.restoreToCount(save)
}
fun updateSize(currentWidth: Int, currentHeight: Int) {
rectF = android.graphics.RectF(0f, 0f, currentWidth.toFloat(), currentHeight.toFloat())
resetPath()
}
private fun resetPath() {
path.reset()
path.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW)
path.close()
}
}
Then, in each of your customized layout classes, add code similar to this one:
class RoundedConstraintLayout : ConstraintLayout {
private lateinit var canvasRounder: CanvasRounder
constructor(context: Context) : super(context) {
init(context, null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context, attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
init(context, attrs, defStyle)
}
private fun init(context: Context, attrs: AttributeSet?, defStyle: Int) {
val array = context.obtainStyledAttributes(attrs, R.styleable.RoundedCornersView, 0, 0)
val cornerRadius = array.getDimension(R.styleable.RoundedCornersView_corner_radius, 0f)
val cornerStrokeColor = array.getColor(R.styleable.RoundedCornersView_corner_stroke_color, 0)
val cornerStrokeWidth = array.getDimension(R.styleable.RoundedCornersView_corner_stroke_width, 0f)
array.recycle()
canvasRounder = CanvasRounder(cornerRadius,cornerStrokeColor,cornerStrokeWidth)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
setLayerType(FrameLayout.LAYER_TYPE_SOFTWARE, null)
}
}
override fun onSizeChanged(currentWidth: Int, currentHeight: Int, oldWidth: Int, oldheight: Int) {
super.onSizeChanged(currentWidth, currentHeight, oldWidth, oldheight)
canvasRounder.updateSize(currentWidth, currentHeight)
}
override fun draw(canvas: Canvas) = canvasRounder.round(canvas) { super.draw(canvas) }
override fun dispatchDraw(canvas: Canvas) = canvasRounder.round(canvas) { super.dispatchDraw(canvas) }
}
If you wish to support attributes, use this as written on the library:
<resources>
<declare-styleable name="RoundedCornersView">
<attr name="corner_radius" format="dimension"/>
<attr name="corner_stroke_width" format="dimension"/>
<attr name="corner_stroke_color" format="color"/>
</declare-styleable>
</resources>
Another alternative, which might be easier for most uses: use MaterialCardView . It allows customizing the rounded corners, stroke color and width, and elevation.
Example:
<FrameLayout
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" android:layout_width="match_parent"
android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"
tools:context=".MainActivity">
<com.google.android.material.card.MaterialCardView
android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center"
app:cardCornerRadius="8dp" app:cardElevation="8dp" app:strokeColor="#f00" app:strokeWidth="2dp">
<ImageView
android:layout_width="match_parent" android:layout_height="match_parent" android:background="#0f0"/>
</com.google.android.material.card.MaterialCardView>
</FrameLayout>
And the result:
Do note that there is a slight artifacts issue at the edges of the stroke (leaves some pixels of the content there), if you use it. You can notice it if you zoom in. I've reported about this issue here.
EDIT: seems to be fixed, but not on the IDE. Reported here.
Step 1: Define bg_layout.xml in drawables folder, and put the below code in it.
Step 2: Add that bg_layout.xml as background to your layout, Done.
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#EEEEEE"/> <!--your desired colour for solid-->
<stroke
android:width="3dp"
android:color="#EEEEEE" /> <!--your desired colour for border-->
<corners
android:radius="50dp"/> <!--shape rounded value-->
</shape>
If you would like to make your layout rounded, it is best to use the CardView, it provided many features to make the design beautiful.
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".3"
android:text="#string/quote_code"
android:textColor="#color/white"
android:textSize="#dimen/text_head_size" />
</LinearLayout>
</android.support.v7.widget.CardView>
With this card_view:cardCornerRadius="5dp", you can change the radius.
Try this...
1.create drawable xml(custom_layout.xml):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#FFFFFF" />
<stroke
android:width="2dp"
android:color="#FF785C" />
<corners android:radius="10dp" />
</shape>
2.add your view background
android:background="#drawable/custom_layout"
With the Material Components Library you can use the MaterialShapeDrawable to draw custom shapes.
Just put the LinearLayout in your xml layout:
<LinearLayout
android:id="#+id/linear_rounded"
android:layout_width="match_parent"
android:layout_height="wrap_content"
..>
<!-- content ..... -->
</LinearLayout>
Then in your code you can apply a ShapeAppearanceModel. Something like:
float radius = getResources().getDimension(R.dimen.default_corner_radius);
LinearLayout linearLayout= findViewById(R.id.linear_rounded);
ShapeAppearanceModel shapeAppearanceModel = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius)
.build();
MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable(shapeAppearanceModel);
//Fill the LinearLayout with your color
shapeDrawable.setFillColor(ContextCompat.getColorStateList(this,R.color.secondaryLightColor));
ViewCompat.setBackground(linearLayout,shapeDrawable);
Note:: it requires the version 1.1.0 of the material components library.
The best and simplest method would be to make use of card_background drawable in your layout. This also follows Google's material design guidelines. Just include this in you LinearLayout:
android:background="#drawable/card_background"
Add this to your drawable directory and name it card_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#BDBDBD"/>
<corners android:radius="5dp"/>
</shape>
</item>
<item
android:left="0dp"
android:right="0dp"
android:top="0dp"
android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#ffffff"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>
Function for set corner radius programmatically
static void setCornerRadius(GradientDrawable drawable, float topLeft,
float topRight, float bottomRight, float bottomLeft) {
drawable.setCornerRadii(new float[] { topLeft, topLeft, topRight, topRight,
bottomRight, bottomRight, bottomLeft, bottomLeft });
}
static void setCornerRadius(GradientDrawable drawable, float radius) {
drawable.setCornerRadius(radius);
}
Using
GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setColor(Color.GREEN);
setCornerRadius(gradientDrawable, 20f);
//or setCornerRadius(gradientDrawable, 20f, 40f, 60f, 80f);
view.setBackground(gradientDrawable);
Use CardView to get rounded edges for any layouts.
Use card_view:cardCornerRadius="5dp" for cardview to get rounded layout edges.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="15dp"
android:weightSum="1">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".3"
android:text="#string/quote_code"
android:textColor="#color/white"
android:textSize="#dimen/text_head_size" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:text="#string/quote_details"
android:textColor="#color/white"
android:textSize="#dimen/text_head_size" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
A better way to do it would be:
background_activity.xml
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:gravity="fill">
<color android:color="#color/black"/>
</item>
<item>
<shape android:gravity="fill">
<solid android:color="#color/white"/>
<corners android:radius="10dip"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>
</item>
</layer-list>
This will work below API 21 also, and give you something like this:
If you are willing to make a little more effort more better control, then use android.support.v7.widget.CardView with its cardCornerRadius attribute (and set elevation attribute to 0dp to get rid of any accompanying drop shadow with the cardView). Also, this will work from API level as low as 15.
Create your xml in drawable, layout_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/your_colour" />
<stroke
android:width="2dp"
android:color="#color/your_colour" />
<corners android:radius="10dp" />
</shape>
<--width, color, radius should be as per your requirement-->
and then, add this in your layout.xml
android:background="#drawable/layout_background"
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="3dip" android:color="#B1BCBE" />
<corners android:radius="10dip"/>
<padding android:left="3dip" android:top="3dip" android:right="3dip" android:bottom="3dip" />
</shape>
#David, just put padding same value as stroke, so border can be visible, regardeless image size
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:padding="#dimen/_10sdp"
android:shape="rectangle">
<solid android:color="#color/header" />
<corners
android:bottomLeftRadius="#dimen/_5sdp"
android:bottomRightRadius="#dimen/_5sdp"
android:topLeftRadius="#dimen/_5sdp"
android:topRightRadius="#dimen/_5sdp" />
I've taken #gauravsapiens answer with my comments inside to give you a reasonable apprehension of what the parameters will effect.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Background color -->
<solid android:color="#color/white" />
<!-- Stroke around the background, width and color -->
<stroke android:width="4dp" android:color="#color/drop_shadow"/>
<!-- The corners of the shape -->
<corners android:radius="4dp"/>
<!-- Padding for the background, e.g the Text inside a TextView will be
located differently -->
<padding android:left="10dp" android:right="10dp"
android:bottom="10dp" android:top="10dp" />
</shape>
If you're just looking to create a shape that rounds the corners, removing the padding and the stroke will do. If you remove the solid as well you will, in effect, have created rounded corners on a transparent background.
For the sake of being lazy I have created a shape underneath, which is just a solid white background with rounded corners - enjoy! :)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Background color -->
<solid android:color="#color/white" />
<!-- The corners of the shape -->
<corners android:radius="4dp"/>
</shape>
I'm a bit late to the party, but this is still a problem. So I wrote a set of OutlineProviders and BindingAdapters for data binding that enables you to clip corners from xml.
NOTE: Clipping with outline does not support corners to be different sizes!
I wrote a detailed response with code on this stackoverflow post
What you will get with code + binding adapter:
<androidx.constraintlayout.widget.ConstraintLayout
clipRadius="#{#dimen/some_radius}"
clipBottomLeft="#{#dimen/some_radius}"
clipBottomRight="#{#dimen/some_radius}"
clipTopLeft="#{#dimen/some_radius}"
clipTopRight="#{#dimen/some_radius}"
clipCircle="#{#bool/clip}"
This enables you to clip the view to a circle, round all corners, round corners in one direction (left, top, right, bottom) or single corners.
If what you want is just a simple rounded rectangle, cut the long story short.
float r=8;
ShapeDrawable shape =
new ShapeDrawable (new RoundRectShape(new float[] { r, r, r, r, r, r, r, r },null,null));
shape.getPaint().setColor(Color.RED);
view.setBackground(shape);
The first two floats are for the top-left corner (remaining pairs correspond clockwise).
for more details read this answer
You can do it with a custom view, like this RoundAppBar and RoundBottomAppBar.
Here a path is used to clipPath the canvas.

Categories

Resources