Skip to content

Instantly share code, notes, and snippets.

@sagix
Last active December 22, 2016 03:26
Show Gist options
  • Save sagix/43c4c47a3dfa0c42d347 to your computer and use it in GitHub Desktop.
Save sagix/43c4c47a3dfa0c42d347 to your computer and use it in GitHub Desktop.
Create a layout with border radius and shadow that mask content inside the rounded rect.
package com.octo.nicolasmouchel;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.LinearLayout;
import com.rmwallet.wallet.R;
public class RoundedShadowedLayout extends LinearLayout {
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint blackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private RectF rect = new RectF();
private float shadowWidth = 12;
private int radius = 16;
private Bitmap mask;
public RoundedShadowedLayout(Context context) {
super(context);
init();
}
public RoundedShadowedLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedShadowedLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@SuppressWarnings("unused")
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RoundedShadowedLayout(
Context context,
AttributeSet attrs,
int defStyleAttr,
int defStyleRes
) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
setWillNotDraw(false);
setLayerType(LAYER_TYPE_SOFTWARE, null);
paint.setColor(Color.WHITE);
paint.setShadowLayer(shadowWidth, 0, 0, 0xFF888888);
paint.setStyle(Paint.Style.FILL);
blackPaint.setColor(Color.BLACK);
blackPaint.setStyle(Paint.Style.FILL);
maskPaint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.DST_IN)));
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
rect.set(shadowWidth, shadowWidth, w - shadowWidth, h - shadowWidth);
if (mask != null && !mask.isRecycled()) {
mask.recycle();
}
mask = makeBitmapMask();
}
@Override
protected void dispatchDraw(Canvas canvas) {
int sc = canvas.saveLayer(0, 0, getMeasuredWidth(), getMeasuredHeight(), null,
Canvas.MATRIX_SAVE_FLAG
| Canvas.CLIP_SAVE_FLAG
| Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
| Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);
super.dispatchDraw(canvas);
canvas.drawBitmap(mask, 0F, 0F, maskPaint);
canvas.restoreToCount(sc);
}
@Nullable
private Bitmap makeBitmapMask() {
if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
final Bitmap mask = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(mask);
canvas.drawRoundRect(rect, radius, radius, blackPaint);
return mask;
} else {
Log.e("",
"Can't create a mask with height 0 or width 0. Or the layout has no children and is wrap content");
return null;
}
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawRoundRect(rect, radius, radius, paint);
super.onDraw(canvas);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment