Android Xml Rounded Clipped Corners

Android XML rounded clipped corners

What your describing sounds like this:

<LinearLayout android:shape="rounded">
<LinearLayout android:background="@drawable/pedometer_stats_background">
</LinearLayout>
</LinearLayout>

And the inner layout is pushing outside the rounded corners because it isn't rounded. You'll have to round the corners of your bitmap. If you have a repeating bitmap you'll want to look at defining a nine-patch drawable. Round your corners then define the portion of the graphic that can expand.

http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape

It'd be nice if we could just add a bitmap to the shape drawable and have that be applied as a skin over whatever shape we're drawing. And, I bet if you know what your doing you could create a Shape subclass that draws a bitmap, but that's not included in Android out of the box unfortunately.

How to make layout with rounded corners..?

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"

Android: how to clip only top rounded corners

I've managed to get this working by creating a custom ViewOutlineProvider and using that instead of a background value

ViewOutlineProvider mViewOutlineProvider = new ViewOutlineProvider() {
@Override
public void getOutline(final View view, final Outline outline) {
float cornerRadiusDP = 16f;
float cornerRadius = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, cornerRadiusDP, getResources().getDisplayMetrics());
outline.setRoundRect(0, 0, view.getWidth(), (int)(view.getHeight() + cornerRadius), cornerRadius);
}
};
scrollView.setOutlineProvider(mViewOutlineProvider);
scrollView.setClipToOutline(true);

How to make a view with 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>

Use clipping to round corners of ViewGroup

Having defined this layout:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent">

<com.playground.RoundedRelativeLayout
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:background="@color/colorPrimary" />

</FrameLayout>

Where RoundedRelativeLayout has following implementation:



public class RoundedRelativeLayout extends RelativeLayout {

private RectF rectF;
private Path path = new Path();
private float cornerRadius = 15;

public RoundedRelativeLayout(Context context) {
super(context);
}

public RoundedRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}

public RoundedRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
rectF = new RectF(0, 0, w, h);
resetPath();
}

@Override
public void draw(Canvas canvas) {
int save = canvas.save();
canvas.clipPath(path);
super.draw(canvas);
canvas.restoreToCount(save);
}

@Override
protected void dispatchDraw(Canvas canvas) {
int save = canvas.save();
canvas.clipPath(path);
super.dispatchDraw(canvas);
canvas.restoreToCount(save);
}

private void resetPath() {
path.reset();
path.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW);
path.close();
}
}

You'll get following output:

The implementation is shamelessly stolen from RoundKornerLayouts project.

Android - drawable with rounded corners at the top only

Try giving these values:

 <corners android:topLeftRadius="6dp" android:topRightRadius="6dp"
android:bottomLeftRadius="0.1dp" android:bottomRightRadius="0.1dp"/>

Note that I have changed 0dp to 0.1dp.

EDIT: See Aleks G comment below for a cleaner version

clipToOutline with cornerRadii with background

if i use background.cornerRadius it works predictable

It is because clipping only supports rectangle, circle, or round rect.

When you use background.cornerRadius it uses RoundRect to draw, but when you use background.cornerRadii it uses Path to draw, and path clipping is not supported until API 33. Check outline documentation.

You cannot use variable corners radius, but you can do a workaround to keep rounded corners at desired positions by using ViewOutlineProvider and RoundRect to draw the outline. You can read more detailed answers about it here.



Related Topics



Leave a reply



Submit