Created
January 11, 2021 20:30
-
-
Save Abdallah-Abdelazim/17f4fcf6342bdfb0fac262d6104f5a61 to your computer and use it in GitHub Desktop.
A custom FrameLayout that allows you to round & clip the corners of this layout, and its children, with radii that you specify either in XML or with code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<resources> | |
<declare-styleable name="RoundedFrameLayout"> | |
<attr name="radius" format="dimension" /> | |
<attr name="top_right_radius" format="dimension" /> | |
<attr name="top_left_radius" format="dimension" /> | |
<attr name="bottom_right_radius" format="dimension" /> | |
<attr name="bottom_left_radius" format="dimension" /> | |
</declare-styleable> | |
</resources> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example; | |
import android.content.Context; | |
import android.content.res.TypedArray; | |
import android.graphics.Canvas; | |
import android.graphics.Path; | |
import android.graphics.RectF; | |
import android.util.AttributeSet; | |
import android.widget.FrameLayout; | |
import app.mongez.mongezapp.R; | |
/** | |
* A custom {@link FrameLayout} that allows you to round & clip the corners of this layout, and its children, | |
* with radii that you specify either in XML or with code. | |
* | |
* @author Abdallah Abdelazim | |
*/ | |
public class RoundedFrameLayout extends FrameLayout { | |
private float topRightRadius; | |
private float topLeftRadius; | |
private float bottomRightRadius; | |
private float bottomLeftRadius; | |
private Path path; | |
public RoundedFrameLayout(Context context) { | |
super(context); | |
init(null, 0); | |
} | |
public RoundedFrameLayout(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
init(attrs, 0); | |
} | |
public RoundedFrameLayout(Context context, AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
init(attrs, defStyle); | |
} | |
private void init(AttributeSet attrs, int defStyle) { | |
// Load attributes | |
final TypedArray a = getContext().obtainStyledAttributes( | |
attrs, R.styleable.RoundedFrameLayout, defStyle, 0); | |
if (a.hasValue(R.styleable.RoundedFrameLayout_radius)) { | |
topLeftRadius = topRightRadius = bottomLeftRadius = bottomRightRadius = a.getDimension( | |
R.styleable.RoundedFrameLayout_radius, | |
0F); | |
} else { | |
topLeftRadius = a.getDimension( | |
R.styleable.RoundedFrameLayout_top_left_radius, | |
0F); | |
topRightRadius = a.getDimension( | |
R.styleable.RoundedFrameLayout_top_right_radius, | |
0F); | |
bottomLeftRadius = a.getDimension( | |
R.styleable.RoundedFrameLayout_bottom_left_radius, | |
0F); | |
bottomRightRadius = a.getDimension( | |
R.styleable.RoundedFrameLayout_bottom_right_radius, | |
0F); | |
} | |
a.recycle(); | |
} | |
@Override | |
public void draw(Canvas canvas) { | |
canvas.save(); | |
canvas.clipPath(path); | |
super.draw(canvas); | |
canvas.restore(); | |
} | |
@Override | |
protected void dispatchDraw(Canvas canvas) { | |
canvas.save(); | |
canvas.clipPath(path); | |
super.dispatchDraw(canvas); | |
canvas.restore(); | |
} | |
@Override | |
protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |
super.onSizeChanged(w, h, oldw, oldh); | |
RectF r = new RectF(0, 0, w, h); | |
path = new Path(); | |
// The corners radii in the order: top-left, top-right, bottom-right, bottom-left | |
float[] radii = {topLeftRadius, topLeftRadius, topRightRadius, topRightRadius, | |
bottomRightRadius, bottomRightRadius, bottomLeftRadius, bottomLeftRadius}; | |
path.addRoundRect(r, radii, Path.Direction.CW); | |
path.close(); | |
} | |
public float getTopRightRadius() { | |
return topRightRadius; | |
} | |
public void setTopRightRadius(float topRightRadius) { | |
this.topRightRadius = topRightRadius; | |
invalidate(); | |
} | |
public float getTopLeftRadius() { | |
return topLeftRadius; | |
} | |
public void setTopLeftRadius(float topLeftRadius) { | |
this.topLeftRadius = topLeftRadius; | |
invalidate(); | |
} | |
public float getBottomRightRadius() { | |
return bottomRightRadius; | |
} | |
public void setBottomRightRadius(float bottomRightRadius) { | |
this.bottomRightRadius = bottomRightRadius; | |
invalidate(); | |
} | |
public float getBottomLeftRadius() { | |
return bottomLeftRadius; | |
} | |
public void setBottomLeftRadius(float bottomLeftRadius) { | |
this.bottomLeftRadius = bottomLeftRadius; | |
invalidate(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment