How to draw segment of circle at the bottom of view [android]? - android

My activity should look like this:
I'm not sure what's the best way to show the segment of the circle between top and bottom views.
I'd like to avoid saving the segment as image.
Is there a way to show it using drawable xml (I've tried to achieve this using oval, but I don't know how to make is so "flat")?
Maybe drawing on canvas?

I think option 3 is the best, you can control exactly what you're drawing but you don't loose OOP karma points
OPTION 1
You can create a custom View for your top View and implement the drawing yourself like this, I'm subclassing RelativeLayout here but you can subclass whatever View you want
public class CurveBgRelativeLayout extends RelativeLayout {
public CurveBgRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
private Path path;
private Paint paint;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(0xffff0000);
path = new Path();
float horizontalOffset = w * .8f;
float top = -h * .8f;
float bottom = h;
RectF ovalRect = new RectF(-horizontalOffset, top, w + horizontalOffset, bottom);
path.lineTo(ovalRect.left, top);
path.arcTo(ovalRect, 0, 180, false);
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
}
#Override
protected void onDraw(Canvas canvas) {
if (path != null)
canvas.drawPath(path, paint);
super.onDraw(canvas);
}
}
and then in your xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.CurveBgRelativeLayout
android:layout_width="match_parent"
android:background="#ffffffff"
android:layout_height="0dp"
android:layout_weight="1"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ffff0000"
/>
</LinearLayout>
OPTION 2
You can create an xml drawable as a background for your top View, the only problem here is that the horizontal stretch of the circle is given with a size in dp, so it's not relative to the View's size
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:height="40dp"
android:gravity="bottom">
<shape android:shape="rectangle">
<solid android:color="#ffff0000" />
</shape>
</item>
<item
android:width="500dp"
android:height="60dp"
android:gravity="bottom|center_horizontal"
android:top="-40dp">
<shape android:shape="oval">
<solid android:color="#ffffffff" />
</shape>
</item>
<item
android:height="30dp"
android:bottom="30dp"
android:gravity="bottom">
<shape android:shape="rectangle">
<solid android:color="#ffffffff" />
</shape>
</item>
</layer-list>
OPTION 3
public class CurveBottomDrawable extends Drawable {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Path path = new Path();
public CurveBottomDrawable(int color) {
paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
}
#Override
public void draw(#NonNull Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
paint.setColor(0xffff0000);
path.reset();
Rect bounds = getBounds();
float horizontalOffset = bounds.width() * .8f;
float top = -bounds.height() * .8f;
float bottom = bounds.height();
RectF ovalRect = new RectF(-horizontalOffset, top, bounds.width() + horizontalOffset, bottom);
path.lineTo(ovalRect.left, top);
path.arcTo(ovalRect, 0, 180, false);
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
canvas.drawPath(path, paint);
}
#Override
public void setAlpha(#IntRange(from = 0, to = 255) int alpha) {
paint.setAlpha(alpha);
}
#Override
public void setColorFilter(#Nullable ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
}
and then set it programmatically
myView.setBackground(new CurveBottomDrawable(0xffff0000));

Related

Bitmap with rounded convers

I want to make Bitmap rounded, but in result bitmap I have only left-top , and left-bottom corners become rounded. How to make all corners rounded?
#Override
public Bitmap transform(Bitmap source) {
Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int cornerSizePx = 28;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, source.getWidth(), source.getHeight());
final RectF rectF = new RectF(rect);
// prepare canvas for transfer
paint.setAntiAlias(true);
paint.setColor(0xFFFFFFFF);
paint.setStyle(Paint.Style.FILL);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawRoundRect(rectF, cornerSizePx, cornerSizePx, paint);
// draw source
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, rect, rect, paint);
return output;
}
Here is my source bitmap:
Here is result Bitmap
But I expected this:
Make Custom ImageView
Create Java class name CutomImageView.
Paste Following Code into that class.
public class CustomImageView extends ImageView {
public static float radius = 25.0f;
public CustomImageView(Context context) {
super(context);
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
//float radius = 36.0f;
Path clipPath = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}}
In layout use this
<your package name.CustomImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/thumbimg"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:visibility="gone"
/>
<?xml version="1.0" encoding="utf-8"?>
<item android:state_pressed="true">
<shape >
<solid android:color="#color/colorPrimaryDark"/>
<corners
android:radius="30dp"/>
</shape>
</item>
<item android:state_focused="true" >
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/colorPrimaryDark"/>
<corners
android:radius="30dp"/>
</shape>
</item>
<item android:state_focused="false" >
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/colorPrimary"/>
<corners
android:radius="30dp"/>
</shape>
</item>
<item android:state_pressed="false" >
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/colorPrimary"/>
<corners
android:radius="30dp"
/>
</shape>
</item>
put this code inside a new drawable file then use this new drawable file as a background of your image

Children of ListView doesn't respect parents border radius [duplicate]

I am trying to make a view in android with rounded edges. The solution I found so far is to define a shape with rounded corners and use it as the background of that view.
Here is what I did, define a drawable as given below:
<padding
android:top="2dp"
android:bottom="2dp"/>
<corners android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
Now I used this as the background for my layout as below:
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:clipChildren="true"
android:background="#drawable/rounded_corner">
This works perfectly fine, I can see that the view has rounded edges.
But my layout has got many other child views in it, say an ImageView or a MapView. When I place an ImageView inside the above layout, the corners of image are not clipped/cropped, instead it appears full.
I have seen other workarounds to make it work like the one explained here.
But is there a method to set rounded corners for a view and all its
child views are contained within that main view that has rounded
corners?
Another approach is to make a custom layout class like the one below. This layout first draws its contents to an offscreen bitmap, masks the offscreen bitmap with a rounded rect and then draws the offscreen bitmap on the actual canvas.
I tried it and it seems to work (at least for my simple testcase). It will of course affect performance compared to a regular layout.
package com.example;
import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.FrameLayout;
public class RoundedCornerLayout extends FrameLayout {
private final static float CORNER_RADIUS = 40.0f;
private Bitmap maskBitmap;
private Paint paint, maskPaint;
private float cornerRadius;
public RoundedCornerLayout(Context context) {
super(context);
init(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
setWillNotDraw(false);
}
#Override
public void draw(Canvas canvas) {
Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas offscreenCanvas = new Canvas(offscreenBitmap);
super.draw(offscreenCanvas);
if (maskBitmap == null) {
maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
}
offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
}
private Bitmap createMask(int width, int height) {
Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(mask);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, width, height, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);
return mask;
}
}
Use this like a normal layout:
<com.example.RoundedCornerLayout
android:layout_width="200dp"
android:layout_height="200dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/test"/>
<View
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#ff0000"
/>
</com.example.RoundedCornerLayout>
Or you can use a android.support.v7.widget.CardView like so:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#color/white"
card_view:cardCornerRadius="4dp">
<!--YOUR CONTENT-->
</android.support.v7.widget.CardView>
shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#f6eef1" />
<stroke
android:width="2dp"
android:color="#000000" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners android:radius="5dp" />
</shape>
and inside you layout
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:clipChildren="true"
android:background="#drawable/shape">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/your image"
android:background="#drawable/shape">
</LinearLayout>
Jaap van Hengstum's answer works great however I think it is expensive and if we apply this method on a Button for example, the touch effect is lost since the view is rendered as a bitmap.
For me the best method and the simplest one consists in applying a mask on the view, like that:
#Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight);
float cornerRadius = <whatever_you_want>;
this.path = new Path();
this.path.addRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, Path.Direction.CW);
}
#Override
protected void dispatchDraw(Canvas canvas) {
if (this.path != null) {
canvas.clipPath(this.path);
}
super.dispatchDraw(canvas);
}
Create a xml file called round.xml in the drawable folder and paste this content:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#FFFFFF" />
<stroke android:width=".05dp" android:color="#d2d2d2" />
<corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomRightRadius="5dp" android:bottomLeftRadius="5dp"/>
</shape>
then use the round.xml as background to any item. Then it will give you rounded corners.
If you are having problem while adding touch listeners to the layout. Use this layout as parent layout.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.widget.FrameLayout;
public class RoundedCornerLayout extends FrameLayout {
private final static float CORNER_RADIUS = 6.0f;
private float cornerRadius;
public RoundedCornerLayout(Context context) {
super(context);
init(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
#Override
protected void dispatchDraw(Canvas canvas) {
int count = canvas.save();
final Path path = new Path();
path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), cornerRadius, cornerRadius, Path.Direction.CW);
canvas.clipPath(path, Region.Op.REPLACE);
canvas.clipPath(path);
super.dispatchDraw(canvas);
canvas.restoreToCount(count);
}
}
as
<?xml version="1.0" encoding="utf-8"?>
<com.example.view.RoundedCornerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/patentItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingRight="20dp">
... your child goes here
</RelativeLayout>
</com.example.view.RoundedCornerLayout>
In case you want to round some specific corner.
fun setCorners() {
val mOutlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
val left = 0
val top = 0;
val right = view.width
val bottom = view.height
val cornerRadiusDP = 16f
val cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, cornerRadiusDP, resources.displayMetrics).toInt()
// all corners
outline.setRoundRect(left, top, right, bottom, cornerRadius.toFloat())
/* top corners
outline.setRoundRect(left, top, right, bottom+cornerRadius, cornerRadius.toFloat())*/
/* bottom corners
outline.setRoundRect(left, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/
/* left corners
outline.setRoundRect(left, top, right + cornerRadius, bottom, cornerRadius.toFloat())*/
/* right corners
outline.setRoundRect(left - cornerRadius, top, right, bottom, cornerRadius.toFloat())*/
/* top left corner
outline.setRoundRect(left , top, right+ cornerRadius, bottom + cornerRadius, cornerRadius.toFloat())*/
/* top right corner
outline.setRoundRect(left - cornerRadius , top, right, bottom + cornerRadius, cornerRadius.toFloat())*/
/* bottom left corner
outline.setRoundRect(left, top - cornerRadius, right + cornerRadius, bottom, cornerRadius.toFloat())*/
/* bottom right corner
outline.setRoundRect(left - cornerRadius, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/
}
}
myView.apply {
outlineProvider = mOutlineProvider
clipToOutline = true
}
}
Can be used on a LinearLayout with children that looks like this:
to this:
With the Material Components Library the best way to make a View with rounded corners is to use the MaterialShapeDrawable.
Create a ShapeAppearanceModel with custom rounded corners:
ShapeAppearanceModel shapeAppearanceModelLL1 = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius16)
.build();
Create a MaterialShapeDrawable:
MaterialShapeDrawable shapeDrawableLL1 = new MaterialShapeDrawable(shapeAppearanceModeLL1);
If you want to apply also an elevationOverlay for the dark theme use this:
MaterialShapeDrawable shapeDrawableLL1 = MaterialShapeDrawable.createWithElevationOverlay(this, 4.0f);
shapeDrawableLL1.setShapeAppearanceModel(shapeAppearanceModelLL1);
Optional: apply to the shapeDrawable a background color and a stroke
shapeDrawableLL1.setFillColor(
ContextCompat.getColorStateList(this,R.color...));
shapeDrawableLL1.setStrokeWidth(2.0f);
shapeDrawableLL1.setStrokeColor(
ContextCompat.getColorStateList(this,R.color...));
Finally apply the shapeDrawable as background in your LinearLayout (or other view):
LinearLayout linearLayout1= findViewById(R.id.ll_1);
ViewCompat.setBackground(linearLayout1,shapeDrawableLL1);
In Android L you will be able to just use View.setClipToOutline to get that effect. In previous versions there is no way to just clip the contents of a random ViewGroup in a certain shape.
You will have to think of something that would give you a similar effect:
If you only need rounded corners in the ImageView, you can use a shader to 'paint' the image over the shape you are using as background. Take a look at this library for an example.
If you really need every children to be clipped, maybe you can another view over your layout? One with a background of whatever color you are using, and a round 'hole' in the middle? You could actually create a custom ViewGroup that draws that shape over every children overriding the onDraw method.
Create a xml file under your drawable folder with following code. (The name of the file I created is rounded_corner.xml)
rounded_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="#a9c5ac" >
</solid>
<!-- view border color and width -->
<stroke
android:width="3dp"
android:color="#1c1b20" >
</stroke>
<!-- If you want to add some padding -->
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" >
</padding>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
And keep this drawable as background for the view to which you want to keep rounded corner border. Let’s keep it for a LinearLayout
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/rounded_corner"
android:layout_centerInParent="true">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hi, This layout has rounded corner borders ..."
android:gravity="center"
android:padding="5dp"/>
</LinearLayout>
The CardView worked for me in API 27 in Android Studio 3.0.1. The colorPrimary was referenced in the res/values/colors.xml file and is just an example. For the layout_width of 0dp it will stretch to the width of the parent. You'll have to configure the constraints and width/height to your needs.
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
app:cardBackgroundColor="#color/colorPrimary">
<!-- put your content here -->
</android.support.v7.widget.CardView>
You can use an androidx.cardview.widget.CardView like so:
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="#dimen/dimen_4"
app:cardElevation="#dimen/dimen_4"
app:contentPadding="#dimen/dimen_10">
...
</androidx.cardview.widget.CardView>
OR
shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#f6eef1" />
<stroke
android:width="2dp"
android:color="#000000" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners android:radius="5dp" />
</shape>
and inside you layout
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/shape">
...
</LinearLayout>
To create round corner image using com.google.android.material:material:1.2.0-beta01
float radius = context.getResources().getDimension(R.dimen.border_radius_hug);
shapeAppearanceModel = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius)
.build();
imageView.setShapeAppearanceModel(shapeAppearanceModel)
or if you want to use it in xml file:
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/thumb"
android:layout_width="80dp"
android:layout_height="60dp"
app:shapeAppearanceOverlay="#style/circleImageView"
/>
in style.xml add this:
<style name="circleImageView" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">10%</item>
</style>
follow this tutorial and all the discussion beneath it -
http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
according to this post written by Guy Romain, one of the leading developers of the entire Android UI toolkit, it is possible to make a container (and all his child views) with rounded corners, but he explained that it too expensive (from performances of rendering issues).
I'll recommend you to go according to his post, and if you want rounded corners, then implement rounded corners ImageView according to this post. then, you could place it inside a container with any background, and you'll get the affect you wish.
that's what I did also also eventually.
public class RoundedCornerLayout extends FrameLayout {
private double mCornerRadius;
public RoundedCornerLayout(Context context) {
this(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public double getCornerRadius() {
return mCornerRadius;
}
public void setCornerRadius(double cornerRadius) {
mCornerRadius = cornerRadius;
}
#Override
public void draw(Canvas canvas) {
int count = canvas.save();
final Path path = new Path();
path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), (float) mCornerRadius, (float) mCornerRadius, Path.Direction.CW);
canvas.clipPath(path, Region.Op.REPLACE);
canvas.clipPath(path);
super.draw(canvas);
canvas.restoreToCount(count);
}
}
Difference from Jaap van Hengstum's answer:
Use BitmapShader instead of mask bitmap.
Create bitmap only once.
public class RoundedFrameLayout extends FrameLayout {
private Bitmap mOffscreenBitmap;
private Canvas mOffscreenCanvas;
private BitmapShader mBitmapShader;
private Paint mPaint;
private RectF mRectF;
public RoundedFrameLayout(Context context) {
super(context);
init();
}
public RoundedFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setWillNotDraw(false);
}
#Override
public void draw(Canvas canvas) {
if (mOffscreenBitmap == null) {
mOffscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
mOffscreenCanvas = new Canvas(mOffscreenBitmap);
mBitmapShader = new BitmapShader(mOffscreenBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setShader(mBitmapShader);
mRectF = new RectF(0f, 0f, canvas.getWidth(), canvas.getHeight());
}
super.draw(mOffscreenCanvas);
canvas.drawRoundRect(mRectF, 8, 8, mPaint);
}
}
The tutorial link you provided seems to suggest that you need to set the layout_width and layout_height properties, of your child elements to match_parent.
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent">
try this property with your linear layout it will help
tools:context=".youractivity"
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
Bitmap roundedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(roundedBitmap);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return roundedBitmap;
}
I have seen many solutions, but most of them are useless with Image
View unless you change Image View to other design components, and I do
not recommend them because they may not be compatible with some
**
solution using:
**
Width and color of stroke in drawable
And Margin for the picture
versions. Here is the quick solution.
The first step:
<RelativeLayout
android:layout_width="90dp"
android:layout_height="90dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:scaleType="centerCrop"
android:src="#drawable/a" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/card_helh" />
</RelativeLayout>
design shape
The second step:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="#dimen/_10dp"/>
<stroke android:color="#color/white" android:width="5dp"/>
</shape>
**
A note
** about setting the night mode, set the color stroke color to the color of the container's night so that it appears more homogeneous This
solution works 100%
This solution is mine and I am currently using it
Use shape in xml with rectangle.set the property of bottom or upper radius as want.then apply that xml as background to ur view....or...use gradients to do it from code.

Change color of shape in xml drawable file through layout

So I created this drawable xml file called rounded_rect. I initially set its color to red. However I want to be able to change this color in my layout file.
rounded_rect.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">
<solid android:color="#ffff1900"/>
<corners
android:bottomRightRadius="15dp"
android:bottomLeftRadius="15dp"
android:topLeftRadius="15dp"
android:topRightRadius="15dp"/>
<stroke android:width="4dp"
android:color="#000000"/>
</shape>
My layout file contains a custom View called ItemView. One of my custom attributes is background color.
<custonview.android.example.com.customview.ItemView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:imagePath="#drawable/yes"
custom:text="Yes"
custom:backgroundColor="#000000"
android:layout_row="0"
android:layout_column="0"
android:background="#drawable/rounded_rect_green"
android:layout_margin="30dp" />
The goal is to be able to change the color in my drawable file to the color I assigned in my layout file. Here is my ItemView.java file
public class ItemView extends View {
//attributes of item view
private Drawable drawable;
private String text;
private int backgroundColor;
private int width, height;
private Paint paint;
public ItemView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.ItemView, 0, 0);
try {
text = a.getString(R.styleable.ItemView_text);
backgroundColor = a.getInteger(R.styleable.ItemView_backgroundColor, 0);
drawable = a.getDrawable(R.styleable.ItemView_imagePath);
} finally {
}
paint = new Paint();
width = drawable.getMinimumWidth() / 2;
height = drawable.getMinimumHeight() / 2;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
//positions the image in the middle horizontally and a little above the text below
drawable.setBounds(width / 4, height / 4 - 50, width - (width / 4),
height - (height / 4) - 50);
drawable.draw(canvas);
paint.setTextSize(100);
paint.setColor(Color.BLACK);
canvas.drawText(text, width / 2 -
paint.measureText(text, 0, text.length()) / 2, height - 50, paint);
}
}
Maybe I am over contemplating it. Free free to be creative in your answers. Thank you in advance
Try the below code-
GradientDrawable bgShape = (GradientDrawable)yourview.getBackground();
bgShape.setColor(Color.MAGENTA);
You'll have to create separate drawables for each colour, as there is no way to set those attributes in runtime - because the application would have to compile them.

How to make a view with rounded corners?

I am trying to make a view in android with rounded edges. The solution I found so far is to define a shape with rounded corners and use it as the background of that view.
Here is what I did, define a drawable as given below:
<padding
android:top="2dp"
android:bottom="2dp"/>
<corners android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
Now I used this as the background for my layout as below:
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:clipChildren="true"
android:background="#drawable/rounded_corner">
This works perfectly fine, I can see that the view has rounded edges.
But my layout has got many other child views in it, say an ImageView or a MapView. When I place an ImageView inside the above layout, the corners of image are not clipped/cropped, instead it appears full.
I have seen other workarounds to make it work like the one explained here.
But is there a method to set rounded corners for a view and all its
child views are contained within that main view that has rounded
corners?
Another approach is to make a custom layout class like the one below. This layout first draws its contents to an offscreen bitmap, masks the offscreen bitmap with a rounded rect and then draws the offscreen bitmap on the actual canvas.
I tried it and it seems to work (at least for my simple testcase). It will of course affect performance compared to a regular layout.
package com.example;
import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.FrameLayout;
public class RoundedCornerLayout extends FrameLayout {
private final static float CORNER_RADIUS = 40.0f;
private Bitmap maskBitmap;
private Paint paint, maskPaint;
private float cornerRadius;
public RoundedCornerLayout(Context context) {
super(context);
init(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
setWillNotDraw(false);
}
#Override
public void draw(Canvas canvas) {
Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas offscreenCanvas = new Canvas(offscreenBitmap);
super.draw(offscreenCanvas);
if (maskBitmap == null) {
maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
}
offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
}
private Bitmap createMask(int width, int height) {
Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(mask);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, width, height, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);
return mask;
}
}
Use this like a normal layout:
<com.example.RoundedCornerLayout
android:layout_width="200dp"
android:layout_height="200dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/test"/>
<View
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#ff0000"
/>
</com.example.RoundedCornerLayout>
Or you can use a android.support.v7.widget.CardView like so:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#color/white"
card_view:cardCornerRadius="4dp">
<!--YOUR CONTENT-->
</android.support.v7.widget.CardView>
shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#f6eef1" />
<stroke
android:width="2dp"
android:color="#000000" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners android:radius="5dp" />
</shape>
and inside you layout
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:clipChildren="true"
android:background="#drawable/shape">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/your image"
android:background="#drawable/shape">
</LinearLayout>
Jaap van Hengstum's answer works great however I think it is expensive and if we apply this method on a Button for example, the touch effect is lost since the view is rendered as a bitmap.
For me the best method and the simplest one consists in applying a mask on the view, like that:
#Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight);
float cornerRadius = <whatever_you_want>;
this.path = new Path();
this.path.addRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, Path.Direction.CW);
}
#Override
protected void dispatchDraw(Canvas canvas) {
if (this.path != null) {
canvas.clipPath(this.path);
}
super.dispatchDraw(canvas);
}
Create a xml file called round.xml in the drawable folder and paste this content:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#FFFFFF" />
<stroke android:width=".05dp" android:color="#d2d2d2" />
<corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomRightRadius="5dp" android:bottomLeftRadius="5dp"/>
</shape>
then use the round.xml as background to any item. Then it will give you rounded corners.
If you are having problem while adding touch listeners to the layout. Use this layout as parent layout.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.widget.FrameLayout;
public class RoundedCornerLayout extends FrameLayout {
private final static float CORNER_RADIUS = 6.0f;
private float cornerRadius;
public RoundedCornerLayout(Context context) {
super(context);
init(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
#Override
protected void dispatchDraw(Canvas canvas) {
int count = canvas.save();
final Path path = new Path();
path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), cornerRadius, cornerRadius, Path.Direction.CW);
canvas.clipPath(path, Region.Op.REPLACE);
canvas.clipPath(path);
super.dispatchDraw(canvas);
canvas.restoreToCount(count);
}
}
as
<?xml version="1.0" encoding="utf-8"?>
<com.example.view.RoundedCornerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/patentItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingRight="20dp">
... your child goes here
</RelativeLayout>
</com.example.view.RoundedCornerLayout>
In case you want to round some specific corner.
fun setCorners() {
val mOutlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
val left = 0
val top = 0;
val right = view.width
val bottom = view.height
val cornerRadiusDP = 16f
val cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, cornerRadiusDP, resources.displayMetrics).toInt()
// all corners
outline.setRoundRect(left, top, right, bottom, cornerRadius.toFloat())
/* top corners
outline.setRoundRect(left, top, right, bottom+cornerRadius, cornerRadius.toFloat())*/
/* bottom corners
outline.setRoundRect(left, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/
/* left corners
outline.setRoundRect(left, top, right + cornerRadius, bottom, cornerRadius.toFloat())*/
/* right corners
outline.setRoundRect(left - cornerRadius, top, right, bottom, cornerRadius.toFloat())*/
/* top left corner
outline.setRoundRect(left , top, right+ cornerRadius, bottom + cornerRadius, cornerRadius.toFloat())*/
/* top right corner
outline.setRoundRect(left - cornerRadius , top, right, bottom + cornerRadius, cornerRadius.toFloat())*/
/* bottom left corner
outline.setRoundRect(left, top - cornerRadius, right + cornerRadius, bottom, cornerRadius.toFloat())*/
/* bottom right corner
outline.setRoundRect(left - cornerRadius, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/
}
}
myView.apply {
outlineProvider = mOutlineProvider
clipToOutline = true
}
}
Can be used on a LinearLayout with children that looks like this:
to this:
With the Material Components Library the best way to make a View with rounded corners is to use the MaterialShapeDrawable.
Create a ShapeAppearanceModel with custom rounded corners:
ShapeAppearanceModel shapeAppearanceModelLL1 = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius16)
.build();
Create a MaterialShapeDrawable:
MaterialShapeDrawable shapeDrawableLL1 = new MaterialShapeDrawable(shapeAppearanceModeLL1);
If you want to apply also an elevationOverlay for the dark theme use this:
MaterialShapeDrawable shapeDrawableLL1 = MaterialShapeDrawable.createWithElevationOverlay(this, 4.0f);
shapeDrawableLL1.setShapeAppearanceModel(shapeAppearanceModelLL1);
Optional: apply to the shapeDrawable a background color and a stroke
shapeDrawableLL1.setFillColor(
ContextCompat.getColorStateList(this,R.color...));
shapeDrawableLL1.setStrokeWidth(2.0f);
shapeDrawableLL1.setStrokeColor(
ContextCompat.getColorStateList(this,R.color...));
Finally apply the shapeDrawable as background in your LinearLayout (or other view):
LinearLayout linearLayout1= findViewById(R.id.ll_1);
ViewCompat.setBackground(linearLayout1,shapeDrawableLL1);
In Android L you will be able to just use View.setClipToOutline to get that effect. In previous versions there is no way to just clip the contents of a random ViewGroup in a certain shape.
You will have to think of something that would give you a similar effect:
If you only need rounded corners in the ImageView, you can use a shader to 'paint' the image over the shape you are using as background. Take a look at this library for an example.
If you really need every children to be clipped, maybe you can another view over your layout? One with a background of whatever color you are using, and a round 'hole' in the middle? You could actually create a custom ViewGroup that draws that shape over every children overriding the onDraw method.
Create a xml file under your drawable folder with following code. (The name of the file I created is rounded_corner.xml)
rounded_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="#a9c5ac" >
</solid>
<!-- view border color and width -->
<stroke
android:width="3dp"
android:color="#1c1b20" >
</stroke>
<!-- If you want to add some padding -->
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" >
</padding>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
And keep this drawable as background for the view to which you want to keep rounded corner border. Let’s keep it for a LinearLayout
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/rounded_corner"
android:layout_centerInParent="true">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hi, This layout has rounded corner borders ..."
android:gravity="center"
android:padding="5dp"/>
</LinearLayout>
The CardView worked for me in API 27 in Android Studio 3.0.1. The colorPrimary was referenced in the res/values/colors.xml file and is just an example. For the layout_width of 0dp it will stretch to the width of the parent. You'll have to configure the constraints and width/height to your needs.
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
app:cardBackgroundColor="#color/colorPrimary">
<!-- put your content here -->
</android.support.v7.widget.CardView>
You can use an androidx.cardview.widget.CardView like so:
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="#dimen/dimen_4"
app:cardElevation="#dimen/dimen_4"
app:contentPadding="#dimen/dimen_10">
...
</androidx.cardview.widget.CardView>
OR
shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#f6eef1" />
<stroke
android:width="2dp"
android:color="#000000" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners android:radius="5dp" />
</shape>
and inside you layout
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/shape">
...
</LinearLayout>
To create round corner image using com.google.android.material:material:1.2.0-beta01
float radius = context.getResources().getDimension(R.dimen.border_radius_hug);
shapeAppearanceModel = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius)
.build();
imageView.setShapeAppearanceModel(shapeAppearanceModel)
or if you want to use it in xml file:
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/thumb"
android:layout_width="80dp"
android:layout_height="60dp"
app:shapeAppearanceOverlay="#style/circleImageView"
/>
in style.xml add this:
<style name="circleImageView" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">10%</item>
</style>
follow this tutorial and all the discussion beneath it -
http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
according to this post written by Guy Romain, one of the leading developers of the entire Android UI toolkit, it is possible to make a container (and all his child views) with rounded corners, but he explained that it too expensive (from performances of rendering issues).
I'll recommend you to go according to his post, and if you want rounded corners, then implement rounded corners ImageView according to this post. then, you could place it inside a container with any background, and you'll get the affect you wish.
that's what I did also also eventually.
public class RoundedCornerLayout extends FrameLayout {
private double mCornerRadius;
public RoundedCornerLayout(Context context) {
this(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public double getCornerRadius() {
return mCornerRadius;
}
public void setCornerRadius(double cornerRadius) {
mCornerRadius = cornerRadius;
}
#Override
public void draw(Canvas canvas) {
int count = canvas.save();
final Path path = new Path();
path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), (float) mCornerRadius, (float) mCornerRadius, Path.Direction.CW);
canvas.clipPath(path, Region.Op.REPLACE);
canvas.clipPath(path);
super.draw(canvas);
canvas.restoreToCount(count);
}
}
Difference from Jaap van Hengstum's answer:
Use BitmapShader instead of mask bitmap.
Create bitmap only once.
public class RoundedFrameLayout extends FrameLayout {
private Bitmap mOffscreenBitmap;
private Canvas mOffscreenCanvas;
private BitmapShader mBitmapShader;
private Paint mPaint;
private RectF mRectF;
public RoundedFrameLayout(Context context) {
super(context);
init();
}
public RoundedFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setWillNotDraw(false);
}
#Override
public void draw(Canvas canvas) {
if (mOffscreenBitmap == null) {
mOffscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
mOffscreenCanvas = new Canvas(mOffscreenBitmap);
mBitmapShader = new BitmapShader(mOffscreenBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setShader(mBitmapShader);
mRectF = new RectF(0f, 0f, canvas.getWidth(), canvas.getHeight());
}
super.draw(mOffscreenCanvas);
canvas.drawRoundRect(mRectF, 8, 8, mPaint);
}
}
The tutorial link you provided seems to suggest that you need to set the layout_width and layout_height properties, of your child elements to match_parent.
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent">
try this property with your linear layout it will help
tools:context=".youractivity"
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
Bitmap roundedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(roundedBitmap);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return roundedBitmap;
}
I have seen many solutions, but most of them are useless with Image
View unless you change Image View to other design components, and I do
not recommend them because they may not be compatible with some
**
solution using:
**
Width and color of stroke in drawable
And Margin for the picture
versions. Here is the quick solution.
The first step:
<RelativeLayout
android:layout_width="90dp"
android:layout_height="90dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:scaleType="centerCrop"
android:src="#drawable/a" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/card_helh" />
</RelativeLayout>
design shape
The second step:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="#dimen/_10dp"/>
<stroke android:color="#color/white" android:width="5dp"/>
</shape>
**
A note
** about setting the night mode, set the color stroke color to the color of the container's night so that it appears more homogeneous This
solution works 100%
This solution is mine and I am currently using it
Use shape in xml with rectangle.set the property of bottom or upper radius as want.then apply that xml as background to ur view....or...use gradients to do it from code.

Create an Incomplete Button Stroke

Aim: Stroke only the top and bottom.
What I've tried:
Below is a copy of my XML.
I've tried following the solution in This Stack Overflow Answer.
But my problem is that the doesn't let me choose the options of cutting off the left and right by 1dp as per the solution.
Any ideas?
Code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape >
<gradient
android:startColor="#color/secondaryButtonStartColorSelected"
android:endColor="#color/secondaryButtonEndColorSelected"
android:angle="270" />
<stroke
android:width="#dimen/secondary_button_border_size"
android:color="#color/secondaryButtonBorderColorSelected" />
</shape>
</item>
<item android:state_focused="true" >
<shape>
<gradient
android:startColor="#color/secondaryButtonStartColorSelected"
android:endColor="#color/secondaryButtonEndColorSelected"
android:angle="270" />
<stroke
android:width="#dimen/secondary_button_border_size"
android:color="#color/secondaryButtonBorderColorSelected"/>
</shape>
</item>
</selector>
You could create a custom Drawable to handle this for you, but you'd have to set it in code vs XML. Here's a quick and dirty version:
public class HorizontalStrokeDrawable extends Drawable {
private Paint mPaint = new Paint();
private int mStrokeWidth;
public HorizontalStrokeDrawable (int strokeColor, int strokeWidth) {
mPaint.setColor(strokeColor);
mStrokeWidth = strokeWidth;
}
#Override
public void draw (Canvas canvas) {
Rect bounds = getBounds();
canvas.drawRect(0, 0, bounds.right, mStrokeWidth, mPaint);
canvas.drawRect(0, bounds.bottom - mStrokeWidth, bounds.right, bounds.bottom, mPaint);
}
#Override
public void setAlpha (int alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
#Override
public void setColorFilter (ColorFilter cf) {
mPaint.setColorFilter(cf);
invalidateSelf();
}
#Override
public int getOpacity () {
return PixelFormat.TRANSLUCENT;
}
}
Now you can just set it wherever you need it:
view.setBackgroundDrawable(new HorizontalStrokeDrawable(myColor, myStrokeWidth));

Categories

Resources