How To Create A Rectangle With Rounded Corners With Different Sections In Different Colors
Solution 1:
You can create a custom View
which will draw rectangles on a clipped part of the Canvas
:
publicclassRoundedCornersSegmentedViewextendsView {
private Paint paintA, paintB, paintC;
privatefloat cornerRadius;
privatefloat measuredWidth, measuredHeight;
privateRectFrect=newRectF(0, 0, 0,0);
privatePathrectPath=newPath();
publicRoundedCornersSegmentedView(Context context) {
super(context);
init();
}
publicRoundedCornersSegmentedView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
publicRoundedCornersSegmentedView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
privatevoidinit() {
setWillNotDraw(false);
// add this so Canvas.clipPath() will give the desired result also for devices running Api level lower than 17,// see https://stackoverflow.com/a/30354461/5015207if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
paintA = newPaint(Paint.ANTI_ALIAS_FLAG);
paintA.setColor(Color.GREEN);
paintA.setStyle(Paint.Style.FILL);
paintB = newPaint(Paint.ANTI_ALIAS_FLAG);
paintB.setColor(Color.YELLOW);
paintB.setStyle(Paint.Style.FILL);
paintC = newPaint(Paint.ANTI_ALIAS_FLAG);
paintC.setColor(Color.MAGENTA);
paintC.setStyle(Paint.Style.FILL);
// with <dimen name="corner_radius">60dp</dimen> in res/values/dimens.xml
cornerRadius = getResources().getDimensionPixelSize(R.dimen.corner_radius);
}
@OverrideprotectedvoidonLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
measuredWidth = right - left;
measuredHeight = bottom - top;
rect.set(0, 0, measuredWidth, measuredHeight);
rectPath.reset();
rectPath.addRoundRect(rect, cornerRadius, cornerRadius, Path.Direction.CW);
}
@OverrideprotectedvoidonDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.clipPath(rectPath);
canvas.drawRect(0,0,measuredWidth/3f, measuredHeight, paintA);
canvas.drawRect(measuredWidth/3f,0,2 * measuredWidth/3f, measuredHeight, paintB);
canvas.drawRect(2 * measuredWidth/3f,0,measuredWidth, measuredHeight, paintC);
}
}
If you want to add some kind of semi-transparent edge, you can use a Paint
with a transparent color and fill type Paint.Style.STROKE
and draw a rounded rectangle.
Paint shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// material color "Blue Gray 400",
// see https://material.io/design/color/the-color-system.html
shadowPaint.setColor(Color.argb(30, 120, 144, 156));
shadowPaint.setStyle(Paint.Style.STROKE);
shadowPaint.setStrokeWidth(30);
The rectangle (instantiate outside of onLayout()
for better performance):
privateRectFshadowRect=newRectF(0,0,0,0);
In onLayout()
:
int inset = 20;
shadowRect.set(inset, inset, measuredWidth - inset, measuredHeight - inset);
You should toggle the color/ the alpha value for the shadow Paint
as well as the values for stroke width and inset until you think it looks good.
Apply in onDraw()
after you've drawn the colored segments:
canvas.drawRoundRect(shadowRect, cornerRadius, cornerRadius, shadowPaint);
It can also look nice (more 3D) if you stack semi-transparent Paint
s with decreasing stroke width and increasing inset, like building your own color gradient.
Thanks to @wblaschko for sharing the code snippet on ViewOutlineProvider
!
I added it to my example and got the following effect:
Changes to my code (note: only possible for Api level 21+)
An inner class of the custom View:
@TargetApi(21)staticclassScalingOutlineProviderextendsViewOutlineProvider {
privateint cornerRadius;
ScalingOutlineProvider(int cornerRadius){
this.cornerRadius = cornerRadius;
}
@OverridepublicvoidgetOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight (), cornerRadius);
}
}
And at the end of init()
:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
// elevation of 4dp (cornerRadius was 60dp)setElevation(cornerRadius/15);
setOutlineProvider(new ScalingOutlineProvider(cornerRadius));
}
Solution 2:
For the shadow follow-up question, you have two options. Use built-in methods or draw your own (depending on needs). The former is likely the correct way to do it, unless you need a custom shadow.
Built-In Methods
See the section on Outline in this blog post: https://android.jlelse.eu/mastering-shadows-in-android-e883ad2c9d5b
Example code from the post:
Create an OutlineProvider
publicclassScalingLayoutOutlineProviderextendsViewOutlineProvider {
@OverridepublicvoidgetOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, width, height, radius);
}
}
Add the Outline Provider to your View
publicclassScalingLayoutextendsFrameLayout {
//...
viewOutline = newScalingLayoutOutlineProvider(w, h, currentRadius);
setOutlineProvider(viewOutline);
//..
}
Drawing Your Own
For the border, you can use View.getElevation() to get the desired height: https://developer.android.com/reference/android/view/View#getElevation() and then draw another shape behind the bar for the shadow.
Solution 3:
For example (adjust colors to desired ones, margins, heights etc.):
You could create this using LinearLayout
as root layout with horizontal
orientation and assigning some weights
, create child layouts and add to them custom backgrounds. Simple without too much nesting layouts.
For example:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:layout_margin="20dp"android:orientation="horizontal"><LinearLayoutandroid:id="@+id/statsLayout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:clickable="true"android:background="@drawable/left_background"><TextViewandroid:id="@+id/stats"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="A%"android:textAppearance="@style/TextAppearance.AppCompat.Title"android:textColor="@android:color/black" /></LinearLayout><LinearLayoutandroid:id="@+id/ncaaInfoLayout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:clickable="true"android:background="@drawable/middle_background"><TextViewandroid:id="@+id/ncaaInfo"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="B%"android:textAppearance="@style/TextAppearance.AppCompat.Title"android:textColor="@android:color/black" /></LinearLayout><LinearLayoutandroid:id="@+id/accountLayout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:clickable="true"android:background="@drawable/right_background"><TextViewandroid:id="@+id/account"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="C%"android:textAppearance="@style/TextAppearance.AppCompat.Title"android:textColor="@android:color/black" /></LinearLayout></LinearLayout>
Than create background for each child LinearLayout
for left one left_bacground.xml
:
<shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><cornersandroid:bottomLeftRadius="30dp"android:topLeftRadius="30dp" /><solidandroid:color="@android:color/holo_green_dark" />
Than for LinearLayout in middle
middle_background.xml`:
<shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><solidandroid:color="@android:color/holo_orange_dark" />
And last one LinearLayout
for the right right_bacgkround.xml
:
<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><cornersandroid:bottomRightRadius="30dp"android:topRightRadius="30dp" /><solidandroid:color="@android:color/holo_blue_dark" />
Solution 4:
You should use a CardView
take a look at this example:
<androidx.cardview.widget.CardViewandroid:layout_width="match_parent"android:layout_height="180dp"android:layout_margin="@dimen/activity_vertical_margin"app:cardPreventCornerOverlap="false"app:cardCornerRadius="@dimen/activity_vertical_margin"android:foreground="?android:attr/selectableItemBackground"><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Viewandroid:id="@+id/view1"android:layout_width="0dp"android:layout_height="0dp"android:background="#0c21a9"app:layout_constraintWidth_percent="0.33"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toStartOf="parent" /><Viewandroid:id="@+id/view2"android:layout_width="0dp"android:layout_height="0dp"android:background="#51c914"app:layout_constraintWidth_percent="0.33"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toEndOf="@id/view1" /><Viewandroid:id="@+id/view3"android:layout_width="0dp"android:layout_height="0dp"android:background="#a90c0c"app:layout_constraintWidth_percent="0.33"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toEndOf="@id/view2" /></androidx.constraintlayout.widget.ConstraintLayout></androidx.cardview.widget.CardView>
This property prevents overlap in rounded corners app:cardPreventCornerOverlap="false"
Note that I am using the lib androidx
recommended by Google AndroidX. If you prefer, you can use the legacy support library.
Post a Comment for "How To Create A Rectangle With Rounded Corners With Different Sections In Different Colors"