Это не работает как вы установили, это фон, поэтому контент переопределяет закругленные углы, и если у вас есть контент, который рисует по углам, вы не увидите, что они закруглены.
Android-разработчик
22
Почти всегда мой контент никогда не покрывает углы. Это работает отлично.
Дэвид JY Тан
2
Как избежать ошибки Element shape doesn't have the required attribute android:layout_height?
Лоренц
2
Element shape doesn't have the required attribute android:layout_heightПричина ошибки была показана, потому что layout_bg.xml не было в папке drawable.
Атул
8
@ nhouser9: на самом деле это больше похоже на «Это работает, но имейте в виду, что ваш передний план / контент может рисовать по углам». Так что в зависимости от варианта использования это может работать на 100%. Я рад, что у ответа не так много отрицательных отзывов, потому что он полезен, и я рад, что в комментарии есть сотня отрицательных голосов, потому что с этим решением легко обнаружить ограничение. Лучшее из обоих миров.
Бенуа Даффес
125
Для API 21+ используйте представления клипов
В ViewAPI 21 был добавлен скругленный контурный вырез класса. См. Этот учебный документ или эту ссылку для получения дополнительной информации.
Эта встроенная функция делает закругленные углы очень простыми в реализации. Он работает на любом виде или макете и поддерживает правильное отсечение.
Вот что делать:
Создайте рисованную скругленную форму и установите ее в качестве фона вашего вида:
android:background="@drawable/round_outline"
Согласно документации, все, что вам нужно сделать, это: android:clipToOutline="true"
К сожалению, кажется, что есть ошибка, и этот атрибут XML в настоящее время не распознается. К счастью, мы можем установить отсечение в Java:
В вашей деятельности или фрагменте: View.setClipToOutline(true)
На что это похоже:
Специальное примечание о ImageViews
setClipToOutline()работает только в том случае, если фон представления установлен на форму для рисования. Если эта фоновая форма существует, View обрабатывает контур фона как границы для отсечения и затенения.
Это означает, что если вы хотите скруглить углы в ImageView с setClipToOutline(), ваше изображение должно получаться android:srcвместо android:background(поскольку фон используется для округлой формы). Если вы ДОЛЖНЫ использовать фон, чтобы установить изображение вместо src, вы можете использовать этот обходной путь для вложенных представлений:
Создайте внешний макет с заданным фоном для рисования
Оберните этот макет вокруг вашего ImageView (без заполнения)
ImageView (включая все остальное в макете) теперь будет обрезано до округлой формы внешнего макета.
Не работает на API менее 21. Не могу дождаться, пока я смогу поддерживать только API 21.
startoftext
Использование 'setClipToOutline' работает, но оно также удаляет сам фрейм (рисунок, который вы используете для фона). Есть ли способ избежать этого?
разработчик Android
Вы читали мою заметку об использовании src=@drawable...вместо background=@drawable? Вы можете сделать это или вложить свой ImageView в контейнерное представление, которое содержит контур формы.
Hungryghost
9
Все комментируют эту ошибку - ей почти три года, и в течение этого десятилетия нет никаких признаков ее исправления. Давайте окажем некоторое давление на.
Джош Хансен
Как эта ошибка еще не исправлена
P Fuster
74
Вот копия XML-файла для создания нарисованного с белым фоном, черной рамкой и закругленными углами:
сохраните его как XML-файл в каталоге drawable. Используйте его так, как если бы вы использовали любой нарисованный фон (значок или файл ресурсов), используя его имя ресурса (R.drawable.your_xml_name)
Понравилась возможность округления определенных углов
Меркурий
1
Этот ответ в значительной степени является ответом, как указано выше. Единственное реальное изменение здесь - это определение каждого радиуса угла, и учитывая его одинаковое значение для каждого угла, я бы написал его в одну строку вместо этого: <corners android:radius="7dp" />:)
ZooMagic
это ЛУЧШИЙ ответ для меня, так как он охватывает возможность скругления определенных углов ... хорошая работа, работает на 100%
Махмуд Айман
Углы ImageView не закруглены (обрезаны), как мне решить эту проблему?
Примож Краль
До сих пор работает в сентябре 2019 года. Ницца.
Николас Рибл
36
Используйте CardView в библиотеке поддержки Android v7. Хотя он немного тяжелый, он решает все проблемы и достаточно прост. Не похож на метод set drawable background, он может успешно обрезать подпредставления.
Гораздо лучше для всех, кто может «позволить» это, чем что-либо еще. Меня сбивает с толку, что такая базовая вещь не является частью стандартных представлений Android, будучи основным элементом CSS практически для любого веб-браузера
Бен Филипп
29
Я сделал так:
Проверьте скриншот:
Создайте нарисованный файл с именем custom_rectangle.xmlв папке drawable :
Это не работает как вы установили, это фон, поэтому контент переопределяет закругленные углы, и если у вас есть контент, который рисует по углам, вы не увидите, что они закруглены.
Android-разработчик
25
Я думаю, что лучший способ сделать это - объединить 2 вещи:
сделайте растровое изображение макета, как показано здесь .
сделать округлый рисунок из растрового изображения, как показано здесь
установить рисование на imageView.
Это будет обрабатывать случаи, которые другие решения не смогли решить, например, наличие контента, который имеет углы.
Я думаю, что он также немного более дружественен к GPU, так как показывает один слой вместо 2.
Единственный лучший способ - создать полностью настроенное представление, но это много кода и может занять много времени. Я думаю, что то, что я предложил здесь, является лучшим из обоих миров.
Вот фрагмент того, как это можно сделать:
RoundedCornersDrawable.java
/**
* shows a bitmap as if it had rounded corners. based on :
* http://rahulswackyworld.blogspot.co.il/2013/04/android-drawables-with-rounded_7.html
* easy alternative from support library: RoundedBitmapDrawableFactory.create( ...) ;
*/
public class RoundedCornersDrawable extends BitmapDrawable {
private final BitmapShader bitmapShader;
private final Paint p;
private final RectF rect;
private final float borderRadius;
public RoundedCornersDrawable(final Resources resources, final Bitmap bitmap, final float borderRadius) {
super(resources, bitmap);
bitmapShader = new BitmapShader(getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
final Bitmap b = getBitmap();
p = getPaint();
p.setAntiAlias(true);
p.setShader(bitmapShader);
final int w = b.getWidth(), h = b.getHeight();
rect = new RectF(0, 0, w, h);
this.borderRadius = borderRadius < 0 ? 0.15f * Math.min(w, h) : borderRadius;
}
@Override
public void draw(final Canvas canvas) {
canvas.drawRoundRect(rect, borderRadius, borderRadius, p);
}
}
CustomView.java
public class CustomView extends ImageView {
private View mMainContainer;
private boolean mIsDirty=false;
// TODO for each change of views/content, set mIsDirty to true and call invalidate
@Override
protected void onDraw(final Canvas canvas) {
if (mIsDirty) {
mIsDirty = false;
drawContent();
return;
}
super.onDraw(canvas);
}
/**
* draws the view's content to a bitmap. code based on :
* http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/
*/
public static Bitmap drawToBitmap(final View viewToDrawFrom, final int width, final int height) {
// Create a new bitmap and a new canvas using that bitmap
final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bmp);
viewToDrawFrom.setDrawingCacheEnabled(true);
// Supply measurements
viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
// Apply the measures so the layout would resize before drawing.
viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight());
// and now the bmp object will actually contain the requested layout
canvas.drawBitmap(viewToDrawFrom.getDrawingCache(), 0, 0, new Paint());
return bmp;
}
private void drawContent() {
if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0)
return;
final Bitmap bitmap = drawToBitmap(mMainContainer, getMeasuredWidth(), getMeasuredHeight());
final RoundedCornersDrawable drawable = new RoundedCornersDrawable(getResources(), bitmap, 15);
setImageDrawable(drawable);
}
}
РЕДАКТИРОВАТЬ: нашел хорошую альтернативу, основанную на библиотеке "RoundKornersLayouts" . Иметь класс, который будет использоваться для всех классов макетов, которые вы хотите расширить, для округления:
//based on https://github.com/JcMinarro/RoundKornerLayouts
class CanvasRounder(cornerRadius: Float, cornerStrokeColor: Int = 0, cornerStrokeWidth: Float = 0F) {
private val path = android.graphics.Path()
private lateinit var rectF: RectF
private var strokePaint: Paint?
var cornerRadius: Float = cornerRadius
set(value) {
field = value
resetPath()
}
init {
if (cornerStrokeWidth <= 0)
strokePaint = null
else {
strokePaint = Paint()
strokePaint!!.style = Paint.Style.STROKE
strokePaint!!.isAntiAlias = true
strokePaint!!.color = cornerStrokeColor
strokePaint!!.strokeWidth = cornerStrokeWidth
}
}
fun round(canvas: Canvas, drawFunction: (Canvas) -> Unit) {
val save = canvas.save()
canvas.clipPath(path)
drawFunction(canvas)
if (strokePaint != null)
canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, strokePaint)
canvas.restoreToCount(save)
}
fun updateSize(currentWidth: Int, currentHeight: Int) {
rectF = android.graphics.RectF(0f, 0f, currentWidth.toFloat(), currentHeight.toFloat())
resetPath()
}
private fun resetPath() {
path.reset()
path.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW)
path.close()
}
}
Затем в каждом из ваших настроенных классов макета добавьте код, подобный этому:
Другая альтернатива, которая может быть проще для большинства применений: используйте MaterialCardView. Это позволяет настроить закругленные углы, цвет и ширину обводки, а также высоту.
Обратите внимание, что по краям обводки возникает небольшая проблема с артефактами (при этом остаются некоторые пиксели содержимого), если вы ее используете. Вы можете заметить это, если увеличите масштаб. Я сообщил об этой проблеме здесь .
РЕДАКТИРОВАТЬ: кажется, исправлено, но не на IDE. Сообщается здесь .
Спасибо за сборку этого удивительного ответа, это заставило меня двигаться в правильном направлении, но я мог бы помочь с очень связанной проблемой здесь stackoverflow.com/questions/25877515/…
Will Thomson
Это приводит к ошибке, поскольку в ImageView нет доступного конструктора по умолчанию.
Anuj
Это должен быть принят ответ. Вместо плоской логики вы пошли вниз и нашли отличное решение. Также это решает проблемы, которые вы упомянули в комментариях к другим ответам. Спасибо за ваши усилия и, возможно, вы можете создать полноценный класс и поделиться им через github. Я думаю, что это может помочь слишком многим людям.
Как я уже писал выше о подобном решении: это не работает. как вы установили, это фон, поэтому контент переопределяет закругленные углы, и если у вас есть контент, который рисует по углам, вы не увидите, что они закруглены.
разработчик Android
9
Если вы хотите, чтобы ваш макет был округлым, лучше всего использовать CardView, он предоставляет множество функций, чтобы сделать дизайн красивым.
Лучший и самый простой способ - использовать card_background в вашем макете. Это также соответствует рекомендациям Google по дизайну материалов. Просто включите это в вас LinearLayout:
android:background="@drawable/card_background"
Добавьте это в свой каталог drawable и назовите его card_background.xml :
Используйте CardView, чтобы получить закругленные края для любых макетов. Используйте card_view: cardCornerRadius = "5dp" для просмотра карты, чтобы получить закругленные края макета.
Это будет работать ниже API 21 и даст вам что-то вроде этого:
Если вы хотите приложить немного больше усилий для лучшего контроля, используйте android.support.v7.widget.CardViewего cardCornerRadiusатрибут (и установите elevationатрибут, чтобы 0dpизбавиться от любой сопровождающей тени с помощью cardView). Кроме того, это будет работать с уровня API до 15.
Если содержимое соответствует фону, оно переопределит его. Это на самом деле не ограничивает форму, которую вы установили.
разработчик Android
Вы имеете в виду другое мнение? Можете ли вы обновить код, чтобы показать, что вы имеете в виду? Идея состоит в том, что закругленные углы не поместили бы черную область. По углам должен быть прозрачный цвет.
разработчик Android
О, я понял ваш вопрос сейчас. Полагаю, что вы можете обойтись с небольшим фиксированным запасом на вашем контенте
Абдул Васай
Но тогда контент не будет обрезан по выбранной вами форме, потому что фиксированные поля имеют прямоугольную форму, а не в соответствии с выбранной формой.
Я взял ответ @gauravsapiens с моими комментариями, чтобы дать вам разумное представление о том, на что будут влиять параметры.
<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><!-- Background color --><solidandroid:color="@color/white"/><!-- Stroke around the background, width and color --><strokeandroid:width="4dp"android:color="@color/drop_shadow"/><!-- The corners of the shape --><cornersandroid:radius="4dp"/><!-- Padding for the background, e.g the Text inside a TextView will be
located differently --><paddingandroid:left="10dp"android:right="10dp"android:bottom="10dp"android:top="10dp"/></shape>
Если вы просто хотите создать форму, которая закругляет углы, удалится отступ и обводка. Если вы также удалите твердое тело, вы фактически создадите закругленные углы на прозрачном фоне.
Ради того, чтобы быть ленивым, я создал форму внизу, которая представляет собой сплошной белый фон с закругленными углами - наслаждайтесь! :)
<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><!-- Background color --><solidandroid:color="@color/white"/><!-- The corners of the shape --><cornersandroid:radius="4dp"/></shape>
Создайте свой XML в Drawable, layout_background.xml
<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><solidandroid:color="@color/your_colour"/><strokeandroid:width="2dp"android:color="@color/your_colour"/><cornersandroid:radius="10dp"/></shape>
<--width, color, radius should be as per your requirement-->
Тогда в вашем коде вы можете применить ShapeAppearanceModel. Что-то вроде:
float radius = getResources().getDimension(R.dimen.default_corner_radius);
LinearLayout linearLayout= findViewById(R.id.linear_rounded);
ShapeAppearanceModel shapeAppearanceModel = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius)
.build();
MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable(shapeAppearanceModel);
//Fill the LinearLayout with your color
shapeDrawable.setFillColor(ContextCompat.getColorStateList(this,R.color.secondaryLightColor));
ViewCompat.setBackground(linearLayout,shapeDrawable);
Примечание: для этого требуется версия 1.1.0 библиотеки компонентов материала.
Ответы:
1: Определите layout_bg.xml в чертежах :
2: добавить в
layout_bg.xml
качестве фона для вашего макетаисточник
Element shape doesn't have the required attribute android:layout_height
?Element shape doesn't have the required attribute android:layout_height
Причина ошибки была показана, потому что layout_bg.xml не было в папке drawable.Для API 21+ используйте представления клипов
В
View
API 21 был добавлен скругленный контурный вырез класса. См. Этот учебный документ или эту ссылку для получения дополнительной информации.Эта встроенная функция делает закругленные углы очень простыми в реализации. Он работает на любом виде или макете и поддерживает правильное отсечение.
Вот что делать:
android:background="@drawable/round_outline"
android:clipToOutline="true"
К сожалению, кажется, что есть ошибка, и этот атрибут XML в настоящее время не распознается. К счастью, мы можем установить отсечение в Java:
View.setClipToOutline(true)
На что это похоже:
Специальное примечание о ImageViews
setClipToOutline()
работает только в том случае, если фон представления установлен на форму для рисования. Если эта фоновая форма существует, View обрабатывает контур фона как границы для отсечения и затенения.Это означает, что если вы хотите скруглить углы в ImageView с
setClipToOutline()
, ваше изображение должно получатьсяandroid:src
вместоandroid:background
(поскольку фон используется для округлой формы). Если вы ДОЛЖНЫ использовать фон, чтобы установить изображение вместо src, вы можете использовать этот обходной путь для вложенных представлений:источник
src=@drawable...
вместоbackground=@drawable
? Вы можете сделать это или вложить свой ImageView в контейнерное представление, которое содержит контур формы.Вот копия XML-файла для создания нарисованного с белым фоном, черной рамкой и закругленными углами:
сохраните его как XML-файл в каталоге drawable. Используйте его так, как если бы вы использовали любой нарисованный фон (значок или файл ресурсов), используя его имя ресурса (R.drawable.your_xml_name)
источник
<corners android:radius="7dp" />
:)Используйте CardView в библиотеке поддержки Android v7. Хотя он немного тяжелый, он решает все проблемы и достаточно прост. Не похож на метод set drawable background, он может успешно обрезать подпредставления.
источник
Я сделал так:
Проверьте скриншот:
Создайте нарисованный файл с именем
custom_rectangle.xml
в папке drawable :Теперь примените фон Rectangle на View :
Выполнено
источник
Я думаю, что лучший способ сделать это - объединить 2 вещи:
сделайте растровое изображение макета, как показано здесь .
сделать округлый рисунок из растрового изображения, как показано здесь
установить рисование на imageView.
Это будет обрабатывать случаи, которые другие решения не смогли решить, например, наличие контента, который имеет углы.
Я думаю, что он также немного более дружественен к GPU, так как показывает один слой вместо 2.
Единственный лучший способ - создать полностью настроенное представление, но это много кода и может занять много времени. Я думаю, что то, что я предложил здесь, является лучшим из обоих миров.
Вот фрагмент того, как это можно сделать:
RoundedCornersDrawable.java
CustomView.java
РЕДАКТИРОВАТЬ: нашел хорошую альтернативу, основанную на библиотеке "RoundKornersLayouts" . Иметь класс, который будет использоваться для всех классов макетов, которые вы хотите расширить, для округления:
Затем в каждом из ваших настроенных классов макета добавьте код, подобный этому:
Если вы хотите поддерживать атрибуты, используйте это так, как написано в библиотеке:
Другая альтернатива, которая может быть проще для большинства применений: используйте MaterialCardView. Это позволяет настроить закругленные углы, цвет и ширину обводки, а также высоту.
Пример:
И результат:
Обратите внимание, что по краям обводки возникает небольшая проблема с артефактами (при этом остаются некоторые пиксели содержимого), если вы ее используете. Вы можете заметить это, если увеличите масштаб. Я сообщил об этой проблеме здесь .
РЕДАКТИРОВАТЬ: кажется, исправлено, но не на IDE. Сообщается здесь .
источник
Попробуй это...
1. создайте отрисовываемый xml (custom_layout.xml):
2. добавить свой фон просмотра
источник
Если вы хотите, чтобы ваш макет был округлым, лучше всего использовать CardView, он предоставляет множество функций, чтобы сделать дизайн красивым.
С этим card_view: cardCornerRadius = "5dp", вы можете изменить радиус.
источник
Лучший и самый простой способ - использовать card_background в вашем макете. Это также соответствует рекомендациям Google по дизайну материалов. Просто включите это в вас LinearLayout:
Добавьте это в свой каталог drawable и назовите его card_background.xml :
источник
Используйте CardView, чтобы получить закругленные края для любых макетов. Используйте card_view: cardCornerRadius = "5dp" для просмотра карты, чтобы получить закругленные края макета.
источник
Лучший способ сделать это будет:
background_activity.xml
Это будет работать ниже API 21 и даст вам что-то вроде этого:
Если вы хотите приложить немного больше усилий для лучшего контроля, используйте
android.support.v7.widget.CardView
егоcardCornerRadius
атрибут (и установитеelevation
атрибут, чтобы0dp
избавиться от любой сопровождающей тени с помощью cardView). Кроме того, это будет работать с уровня API до 15.источник
Функция для установки радиуса угла программно
С помощью
источник
@ Давид, просто поместите отступ, равный значению штриха, чтобы была видна граница, безразличный размер изображения
источник
Я взял ответ @gauravsapiens с моими комментариями, чтобы дать вам разумное представление о том, на что будут влиять параметры.
Если вы просто хотите создать форму, которая закругляет углы, удалится отступ и обводка. Если вы также удалите твердое тело, вы фактически создадите закругленные углы на прозрачном фоне.
Ради того, чтобы быть ленивым, я создал форму внизу, которая представляет собой сплошной белый фон с закругленными углами - наслаждайтесь! :)
источник
Создайте свой XML в Drawable,
layout_background.xml
а затем добавьте это в свой
layout.xml
источник
В библиотеке компонентов материалов вы можете использовать
MaterialShapeDrawable
для рисования пользовательских фигур .Просто поместите LinearLayout в свой XML-макет:
Тогда в вашем коде вы можете применить
ShapeAppearanceModel
. Что-то вроде:Примечание: для этого требуется версия 1.1.0 библиотеки компонентов материала.
источник
источник