Вы можете создать пользовательский View
, который будет рисовать прямоугольники на обрезанной части Canvas
:
public class RoundedCornersSegmentedView extends View {
private Paint paintA, paintB, paintC;
private float cornerRadius;
private float measuredWidth, measuredHeight;
private RectF rect = new RectF(0, 0, 0,0);
private Path rectPath = new Path();
public RoundedCornersSegmentedView(Context context) {
super(context);
init();
}
public RoundedCornersSegmentedView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedCornersSegmentedView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
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/5015207
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
paintA = new Paint(Paint.ANTI_ALIAS_FLAG);
paintA.setColor(Color.GREEN);
paintA.setStyle(Paint.Style.FILL);
paintB = new Paint(Paint.ANTI_ALIAS_FLAG);
paintB.setColor(Color.YELLOW);
paintB.setStyle(Paint.Style.FILL);
paintC = new Paint(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);
}
@Override
protected void onLayout(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);
}
@Override
protected void onDraw(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);
}
}
Если вы хотите добавить какой-то полупрозрачный край, вы можете использовать Paint
с прозрачным цветом и тип заливки Paint.Style.STROKE
и нарисовать прямоугольник со скругленными углами.
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);
Прямоугольник (создание экземпляра вне onLayout()
для лучшей производительности):
private RectF shadowRect = new RectF(0,0,0,0);
В onLayout()
:
int inset = 20;
shadowRect.set(inset, inset, measuredWidth - inset, measuredHeight - inset);
Вам следует переключать значение цвета / альфа-канала для тени Paint
, а также значения ширины обводки и вставки, пока вы не подумаете, что это выглядит хорошо.
Применить в onDraw()
после того, как вы нарисовали цветные сегменты:
canvas.drawRoundRect(shadowRect, cornerRadius, cornerRadius, shadowPaint);
Также может хорошо выглядеть (больше 3D), если вы сложите полупрозрачные Paint
s с уменьшением ширины обводки и увеличением вставки, как создание собственного цветового градиента.
Спасибо @wblaschko за то, что поделились фрагментом кода на ViewOutlineProvider
!
Я добавил его в свой пример и получил следующий эффект:
Изменения в моем коде (примечание: возможно только для уровня 21 + API)
Внутренний класс кастомного вида:
@TargetApi(21)
static class ScalingOutlineProvider extends ViewOutlineProvider {
private int cornerRadius;
ScalingOutlineProvider(int cornerRadius){
this.cornerRadius = cornerRadius;
}
@Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight (), cornerRadius);
}
}
И в конце init()
:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
// elevation of 4dp (cornerRadius was 60dp)
setElevation(cornerRadius/15);
setOutlineProvider(new ScalingOutlineProvider(cornerRadius));
}