Сделать круглые углы сверху слева сверху справа снизу слева снизу справа через пути и RectF в Android
Сделав пользовательский ImageView и переопределив метод onDraw следующим образом, ImageView будет иметь скругленные углы. Ссылка
@Override
protected void onDraw(Canvas canvas) {
float radius = getContext().getResources().getDimension(R.dimen.round_corner_radius);
Path path = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
path.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(path);
super.onDraw(canvas);
}
Как я могу выборочно сделать круглые углы вместо того, чтобы сделать все четыре угла круглыми? Например, только сделать верхний левый и верхний правый углы круглыми и оставить нижние углы нетронутыми. Вот решение , которое нужно сделать с помощью растрового изображения. Я ищу, чтобы сделать это в этом методе onDraw и ТОЛЬКО используя путь и RectF.
1 ответ:
Существует перегрузка
Path#addRoundRect()
, которая принимает массив из восьми значенийfloat
, в котором мы можем указать радиус x и y для каждого из четырех углов. Эти значения находятся в парах [x, y], начиная с верхнего левого угла и по часовой стрелке вокруг остальных. Для тех углов, которые мы хотим округлить, мы устанавливаем оба значения пары на значение радиуса и оставляем их на нуле для тех, которые мы не делаем.В качестве наглядного примера, простой метод, который вернет
Path
, который может быть использован в вашем фрагмент:private Path getPath(float radius, boolean topLeft, boolean topRight, boolean bottomRight, boolean bottomLeft) { final Path path = new Path(); final float[] radii = new float[8]; if (topLeft) { radii[0] = radius; radii[1] = radius; } if (topRight) { radii[2] = radius; radii[3] = radius; } if (bottomRight) { radii[4] = radius; radii[5] = radius; } if (bottomLeft) { radii[6] = radius; radii[7] = radius; } path.addRoundRect(new RectF(0, 0, getWidth(), getHeight()), radii, Path.Direction.CW); return path; }
В соответствии с вашим описанием примера, округляя верхний левый и верхний правый углы:
Как всегда, я бы рекомендовал держать метод@Override protected void onDraw(Canvas canvas) { float radius = getContext().getResources().getDimension(R.dimen.round_corner_radius); Path path = getPath(radius, true, true, false, false); canvas.clipPath(path); super.onDraw(canvas); }
onDraw()
как можно более плотным, перемещая все, что не обязательно должно быть в другом месте. Например, значение ресурса для radius может быть извлечено в конструкторе и сохранено в поле. Кроме того,Path
может быть построен только в случае необходимости, т. е. при изменении размераView
или при изменении радиуса или выбранные углы меняются.Поскольку я собрал простой обычай
ImageView
, чтобы проверить это, я включу его сюда, поскольку он демонстрирует вышеупомянутые пункты. Этот пользовательскийView
также предлагает XML-атрибуты, которые позволяют задать радиус угла и закругленные углы в макете.public class RoundishImageView extends ImageView { public static final int CORNER_NONE = 0; public static final int CORNER_TOP_LEFT = 1; public static final int CORNER_TOP_RIGHT = 2; public static final int CORNER_BOTTOM_RIGHT = 4; public static final int CORNER_BOTTOM_LEFT = 8; public static final int CORNER_ALL = 15; private static final int[] CORNERS = {CORNER_TOP_LEFT, CORNER_TOP_RIGHT, CORNER_BOTTOM_RIGHT, CORNER_BOTTOM_LEFT}; private final Path path = new Path(); private int cornerRadius; private int roundedCorners; public RoundishImageView(Context context) { this(context, null); } public RoundishImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundishImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundishImageView); cornerRadius = a.getDimensionPixelSize(R.styleable.RoundishImageView_cornerRadius, 0); roundedCorners = a.getInt(R.styleable.RoundishImageView_roundedCorners, CORNER_NONE); a.recycle(); } public void setCornerRadius(int radius) { if (cornerRadius != radius) { cornerRadius = radius; setPath(); invalidate(); } } public int getCornerRadius() { return cornerRadius; } public void setRoundedCorners(int corners) { if (roundedCorners != corners) { roundedCorners = corners; setPath(); invalidate(); } } public boolean isCornerRounded(int corner) { return (roundedCorners & corner) == corner; } @Override protected void onDraw(Canvas canvas) { if (!path.isEmpty()) { canvas.clipPath(path); } super.onDraw(canvas); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); setPath(); } private void setPath() { path.rewind(); if (cornerRadius >= 1f && roundedCorners != CORNER_NONE) { final float[] radii = new float[8]; for (int i = 0; i < 4; i++) { if (isCornerRounded(CORNERS[i])) { radii[2 * i] = cornerRadius; radii[2 * i + 1] = cornerRadius; } } path.addRoundRect(new RectF(0, 0, getWidth(), getHeight()), radii, Path.Direction.CW); } } }
Чтобы атрибуты XML работали, в вашем
<resources>
должно быть следующее, что вы можете сделать, поместив этот файл в папку вашего проектаres/values/
, или добавив в ту, которая уже может быть там.
attrs.xml
<resources> <declare-styleable name="RoundishImageView"> <attr name="cornerRadius" format="dimension" /> <attr name="roundedCorners"> <flag name="topLeft" value="1" /> <flag name="topRight" value="2" /> <flag name="bottomRight" value="4" /> <flag name="bottomLeft" value="8" /> <flag name="all" value="15" /> </attr> </declare-styleable> </resources>
cornerRadius
является атрибутом измерения и должен быть указан какdp
илиpx
значение.roundedCorners
является атрибутом флага, и несколько углов могут быть выбраны с помощью символа трубы,|
. Например:<com.mycompany.myapp.RoundishImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/riv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="fitXY" android:src="@drawable/magritte" app:cornerRadius="@dimen/round_corner_radius" app:roundedCorners="topLeft|topRight" />