Как сделать круглый imageview android studio

Как сделать ImageView с закругленными углами?

В Android ImageView по умолчанию является прямоугольником. Как я могу сделать его закругленным прямоугольником (обрезать все 4 угла моего растрового изображения, чтобы быть закругленными прямоугольниками) в ImageView?

30 ответов

Это довольно поздно в ответ, но для тех, кто ищет это, вы можете сделать следующий код вручную по углам ваших изображений.

Это не мой код, но я использовал его и он работает прекрасно. Я использовал его в качестве помощника в классе ImageHelper и немного расширил его, чтобы передать количество перьев, необходимое для данного изображения.

окончательный код выглядит следующим образом это:

надеюсь, это кому-то поможет!

в то время как вышеуказанный ответ работает, Romain Guy (основной разработчик Android) показывает лучший метод в своем блоге, который использует меньше памяти, используя шейдер, не создавая копию растрового изображения. Общая суть функциональности здесь:

преимущества этого над другими методами в том, что он:

  • не создает отдельную копию растрового изображения,, который использует много памяти с большими изображениями [против большинства других ответов здесь]
  • поддерживает antialisasing [против метода clipPath]
  • поддерживает Альфа [vs xfermode+метод porterduff]
  • поддерживает аппаратное ускорение [против метода clipPath]
  • только рисует один раз на холсте [против методов xfermode и clippath]

Я создал RoundedImageView на основе этого кода, который обертывает эту логику в ImageView и добавляет правильная ScaleType поддержка и необязательная закругленная граница.

в v21 библиотеки поддержки теперь есть решение этого: это называется RoundedBitmapDrawable.

это в основном так же, как обычный Drawable, за исключением того, что вы даете ему радиус угла для обрезки с:

Итак, начиная с Bitmap src и элемент ImageView , это будет выглядеть примерно так:

еще один простой способ-использовать CardView с радиусом угла и ImageView внутри:

вырезка на округлые формы была добавлена в View класс в API 21.

просто сделать это:

  • создать округлую форму drawable, что-то вроде этого:

res/drawable / round_outline.в XML

  • установите drawable в качестве фона вашего ImageView: android:background=»@drawable/round_outline»
  • по этому документация, то все, что вам нужно сделать, это добавить android:clipToOutline=»true»

к сожалению, нет ошибка и этот атрибут XML не признал. К счастью, мы все еще можем настроить отсечение на Java:

  • в вашей деятельности или фрагмент: ImageView.setClipToOutline(true)

вот как это будет выглядеть:

Примечание:

этот метод работает для любой drawable форма (не только округлые). Это будет клип в ImageView для любой формы контура заданы в Катры в формате XML.

специальное примечание об ImageViews

setClipToOutline() работает только тогда, когда фон представления установлен на фигуру drawable. Если эта фоновая фигура существует, представление рассматривает контур фигуры как границы для обрезки и затенения.

это означает, если вы хотите использовать setClipToOutline() чтобы закруглить углы на ImageView, ваше изображение должно быть установлено с помощью android:src вместо android:background (так как фон должен быть установлен на вашу округлую форму). Если вы должны использовать фон для установки изображения вместо src, вы можете использовать этот обходной путь:

  • создайте макет и установите его фон для вашей фигуры drawable
  • оберните этот макет вокруг вашего ImageView (без заполнения)
  • ImageView (включая все остальное в макете) теперь будет отображаться с округлой формой макета.

я обнаружил, что оба метода были очень полезны в разработке рабочего решения. Вот моя составная версия, которая не зависит от пикселей и позволяет вам иметь некоторые квадратные углы с остальными углами, имеющими одинаковый радиус (что является обычным случаем использования). Благодаря обоим вышеперечисленным решениям:

кроме того, я перешел ImageView, чтобы поместить это, чтобы я мог определить его в xml. Возможно, вы захотите добавить немного логики, которую здесь делает super call, но я прокомментировал это как это не полезно в моем случае.

надеюсь, что это помогает!

округленное изображение с помощью ImageLoader здесь

или вы можете пользователей Picasso библиотека с площади.

вы можете скачать файл RoundedTransformation здесь здесь

Я сделал по пользовательскому ImageView:

выход:

надеюсь, это поможет вам.

поскольку все ответы казались слишком сложными для меня только для круглых углов, я подумал и пришел к другому решению, которое, я думаю, стоит поделиться, просто с XML, если у вас есть пространство вокруг изображения:

создайте граничную форму с прозрачным содержимым, например:

затем в RelativeLayout вы можете сначала поместить свое изображение, а затем в том же месте над формой с другим ImageView. Форма крышки должна быть больше по размеру на величину ширины границы. Будьте осторожны, чтобы взять больший радиус угла, поскольку внешний радиус определен, но внутренний радиус-это то, что покрывает ваше изображение.

Читайте также:  Выключить специальные возможности для андроид

надеюсь, что это тоже кому-то поможет.

редактировать в соответствии с запросом CQM пример относительного макета:

моя реализация виджет ImageView с закругленными углами, что (вниз|вверх)размеры изображения до нужных размеров. Он использует кодовую форму CaspNZ.

вы должны продлить ImageView и нарисуйте свой собственный закругленный прямоугольник.

если вы хотите рамку вокруг изображения, вы также можете наложить округлую рамку поверх представления изображения в макете.

[edit] наложите рамку на исходное изображение, используя FrameLayout например. Первый элемент FrameLayout будет изображение, которое вы хотите отображать округлые. Затем добавьте еще ImageView с рамой. Второй ImageView будет отображаться поверх оригинал ImageView и, таким образом, Android будет рисовать его содержимое выше orignal ImageView .

Я знаю, что этот поток немного стар, но его один из лучших результатов для запросов на Google для того, как округлить углы ImageViews на Android.

Ромен Гай, где он находится.

уменьшенная версия выглядит следующим образом.

ниже создается объект макета закругленного прямоугольника, который рисует закругленный прямоугольник вокруг любых дочерних объектов, помещенных в него. Он также демонстрирует, как создавать представления и макеты программно без использования XML-файлов макета.

класс для объекта макета RoundedRectangle определен здесь:

почему бы не обрезать в draw ()?

вот мое решение:

  • расширить RelativeLayout с отсечения
  • поместите ImageView (или другие представления) в макет:

большое спасибо за первый ответ. Здесь изменена версия для преобразования прямоугольного изображения в квадратное (и округленное), а цвет заливки передается в качестве параметра.

применить форму к вашему imageView , как показано ниже:

Источник

ImageView

Общая информация

Компонент ImageView предназначен для отображения изображений. Находится в разделе Widgets.

Для загрузки изображения в XML-файле используется атрибут android:src, в последнее время чаще используется атрибут app:srcCompat.

ImageView является базовым элементом-контейнером для использования графики. Можно загружать изображения из разных источников, например, из ресурсов программы, контент-провайдеров. В классе ImageView существует несколько методов для загрузки изображений:

  • setImageResource(int resId) — загружает изображение по идентификатору ресурса
  • setImageBitmap(Bitmap bitmap) — загружает растровое изображение
  • setImageDrawable(Drawable drawable) — загружает готовое изображение
  • setImageURI(Uri uri) — загружает изображение по его URI

Метод setImageResource()

Сначала нужно получить ссылку на ImageView, а затем используется идентификатор изображения из ресурсов:

Метод setImageBitmap()

Используется класс BitmapFactory для чтения ресурса изображения в объект Bitmap, а затем в ImageView указывается полученный Bitmap. Могут быть и другие варианты.

Метод setImageDrawable()

Если у вас есть готовое изображение, например, на SD-карте, то его можно использовать в качестве объекта Drawable.

Drawable можно получить и из ресурсов, хотя такой код выглядит избыточным, если можно сразу вызвать setImageResource().

Метод setImageURI()

Берётся URI файла изображения и используется в качестве источника изображения. Этот способ годится для работы с локальными изображениями.

Загружаем Drawable через URI.

Другие методы

Также вам часто придется использовать методы, связанные с размерами и масштабированием: setMaxHeight(), setMaxWidth(), getMinimunHeight(), getMinimunWidth(), getScaleType(), setScaleType().

Масштабирование через свойство Scale Type

Для масштабирования картинки в ImageView есть свойство Scale Type и соответствующий ему атрибут android:scaleType и перечисление ImageView.ScaleType.

  • CENTER
  • CENTER_CROP
  • CENTER_INSIDE
  • FIT_CENTER
  • FIT_START
  • FIT_END
  • FIT_XY
  • MATRIX

Чтобы увидеть разницу между разными режимами, желательно использовать большую картинку, превосходящую по ширине экрана устройства. Допустим, у нас есть простенькая разметка:

Для наглядности я задал красный цвет для фона ImageView.

Режим android:scaleType=»center» выводит картинку в центре без масштабирования. Если у вас будет картинка большего размера, то края могут быть обрезаны.

Режим android:scaleType=»centerCrop» также размещает картинку в центре, но учитывает ширину или высоту контейнера. Режим попытается сделать так, чтобы ширина (или высота) картинки совпала с шириной (или высотой) контейнера, а остальное обрезается.

Режим android:scaleType=»centerInside» масштабирует картинку, сохраняя пропорции. Можно увидеть задний фон контейнера, если его размеры отличаются от размера картинки.

Режим android:scaleType=»fitCenter» (по умолчанию) похож на предыдущий, но может не сохранять пропорции.

Если выбрать режим android:scaleType=»fitStart», то картинка прижимается к левому верхнему углу и таким образом заполняет верхнюю половину контейнера.

Значение android:scaleType=»fitEnd» сместит картинку в нижнюю часть контейнера.

Режим android:scaleType=»fitXY» растягивает/сжимает картинку, чтобы подогнать её к контейнеру. Может получиться вытянутая картинка, поэтому будьте осторожны.

Последний атрибут android:scaleType=»matrix» вывел картинку без изменений в левом верхнем углу с обрезанными краями.

Атрибут android:adjustViewBounds=»true»

При использовании атрибута scaleType=»fitCenter» из предыдущего примера Android вычисляет размеры самой картинки, игнорируя размеры ImageView. В этом случае ваша разметка может «поехать». Атрибут adjustViewBounds заставляет картинку подчиниться размеру компонента-контейнера. В некоторых случаях это может не сработать, например, если у ImageView установлен атрибут layout_width=»0dip». В таком случае поместите ImageView в RelativeLayout или FrameLayout и используйте значение 0dip для этих контейнеров.

Загрузка изображения из галереи

Предположим, у вас есть на экране компонент ImageView, и вы хотите загрузить в него какое-нибудь изображение из галереи по нажатию кнопки:

Намерение ACTION_PICK вызывает отображение галереи всех изображений, хранящихся на телефоне, позволяя выбрать одно изображение. При этом возвращается адрес URI, определяющий местоположение выбранного изображения. Для его получения используется метод getData(). Далее для преобразования URI-адреса в соответствующий экземпляр класса Bitmap используется специальный метод Media.getBitmap(). И у нас появляется возможность установить изображение в ImageView при помощи setImageBitmap().

Читайте также:  Телевизоры с системой андроид сони

На самом деле можно поступить ещё проще и использовать метод setImageURI.

Сравните с предыдущим примером — чувствуете разницу? Тем не менее, приходится часто наблюдать подобный избыточный код во многих проектах. Это связано с тем, что метод порой кэширует адрес и не происходит изменений. Рекомендуется использовать инструкцию setImageURI(null) для сброса кэша и повторный вызов метода с нужным Uri.

В последних версиях системных эмуляторов два примера не работают. Проверяйте на реальных устройствах.

Получить размеры ImageView — будьте осторожны

У элемента ImageView есть два метода getWidth() и getHeight(), позволяющие получить его ширину и высоту. Но если вы попробуете вызвать указанные методы сразу в методе onCreate(), то они возвратят нулевые значения. Можно добавить кнопку и вызвать данные методы через нажатие, тогда будут получены правильные результаты. Либо использовать другой метод активности, который наступает позже.

Копирование изображений между ImageView

Если вам надо скопировать изображение из одного ImageView в другой, то можно получить объект Drawable через метод getDrawable() и присвоить ему второму компоненту.

Примеры

В моих статьях можно найти примеры использования ImageView.

Источник

Скругление углов в Android. Быстро, качественно, недорого.

Привет, меня зовут Дмитрий @dmitriy1984g , я больше трех лет разрабатываю android-приложения в калининградской компании KODE.

Довольно часто при разработке мобильных приложений требуется придавать содержимому некую форму, например, сделать круглое изображение для аватарки. Если для статичных элементов (ImageView) можно обойтись таким инструментом как Picasso transformation, то для динамического содержимого дела обстоят сложнее. Например, есть список элементов, который можно прокручивать и нужно закруглить края. Для этого вполне может подойти виджет CardView.

Но что если нужно задать форму отличную от прямоугольника, и при этом эта форма будет динамически меняться? Это и потребовалось сделать в одном из наших проектов. Подходящих стандартных компонентов UI для данных целей не нашлось, что сподвигло меня на исследование, какие вообще есть инструменты Android для придания формы контенту.

Статья длинная — для тех, кому лень читать всё, самое важное и исходный код в конце статьи.

Дизайнерская верстка

В нашей компании работают довольно креативные дизайнеры. Их безумные идеи порой могут озадачить даже самого опытного разработчика. Посмотрим, что на этот раз нам приготовили.

У нас есть некая карточка с содержимым, которое может прокручиваться. У карточки есть закругление верхних углов, нижние углы должны быть прямыми. Карточку можно потянуть вверх, и, когда карточка заполняет весь экран, закругление убирается.
Все просто, на первый взгляд.

Протоптанная дорожка

На первый взгляд, можно использовать виджет CardView, но в процессе разработки был выявлен ряд недостатков:

  • нельзя задать радиус для каждого угла отдельно;
  • “честное” закругление работает только на версиях, начиная с Android Lollipop. До этой версии добавляется отступ содержимого на размер радиуса углов. Это заметно при прокрутке, появляются пробелы между краями карточки;
  • при установке нулевого радиуса приложение, запущенное на устройстве с версией ниже Andrid Lollipop, падает. В документации такие случаи просто не описаны.

Тернистый путь

Итак, стандартный виджет нам не подходит. Придется искать подходящее решение и писать инструмент самостоятельно. А для начала разобраться, какие есть возможности в этом направлении у других Android инструментов.

Критерии для реализации инструмента:

  • возможность использовать в версиях Android до Lollipop и после. В крайнем случае комбинировать подходы;
  • возможность задавать любую форму. Например, с помощью класса Path;
  • наличие плавных линий и возможности сглаживания (antialiasing);
  • и конечно же, производительность. Придание формы содержимому должно происходить с минимальным воздействием на производительность устройства, особенно для динамически меняющегося содержимого и формы.

Это, конечно, был бы универсальный инструмент. В вариантах, которые я исследовал, не все критерии соблюдаются, но для реализации части случаев вполне подходят.

Я попробовал 4 различных варианта:

  • Свойство View.clipToOutline
  • Метод Canvas.clipPath() при отрисовке дочерних элементов в контейнере
  • Метод Canvas.drawPath() при отрисовке дочерних элементов в контейнере. Настройки PorterDuff.Mode + View.LAYER_TYPE_SOFTWARE
  • Метод Canvas.drawPath() при отрисовке дочерних элементов в контейнере. Настройки PorterDuff.Mode + View.LAYER_TYPE_HARDWARE

Свойство View.clipToOutline

Этот подход используется в виджете CardView. Глянем, что он умеет.

Как это работает:
Задаем фоновое изображение нужной формы и выставляем в поле View.clipToOutline значение “true”.
Но мы знаем, что работаем с API Android, и слишком легко, чтобы быть правдой. Смотрим документацию метода View.setClipToOutline()

Sets whether the View’s Outline should be used to clip the contents of the View…Note that this flag will only be respected if the View’s Outline returns true from Outline.canClip()

Всего-то достаточно, чтобы Outline.canClip() возвращал true . Смотрим документацию и для этого метода:

Returns whether the outline can be used to clip a View. Currently, only Outlines that can be represented as a rectangle, circle, or round rect support clipping.

Получается, что пока доступен ограниченный набор форм. Вот так, задумка хорошая, но возможности не позволяют реализовать весь полет фантазий.
Для того, чтобы динамически менять форму фонового изображения, можно создать класс, наследованный от Drawable. В методе getOutline() задаем нужный контур.

  • Хорошая производительность;
  • Сглаживание линий.
  • Работает только на Lollipop и выше;
  • Ограничение форм: прямоугольник, овал и прямоугольник со скругленными краями.
Читайте также:  Поменять айди для андроид

Хорошо подходит для ситуации, когда нужно задать форму прямоугольника, овала и прямоугольника со скругленными краями, при условии, что приложение разрабатывается для версий Android Lollipop и выше. Возможно, в будущем появится поддержка любой формы контура, но это в будущем.

Метод Canvas.clipPath() при отрисовке дочерних элементов в контейнере

Данный подход состоит в наследовании от класса контейнера. В методе dispatchDraw() делаем обрезку по нужной форме с помощью метода Canvas.clipPath()

Все что нужно — это задать необходимый контур с помощью объекта класса Path . Недочеты видны после запуска приложения — отсутствует сглаживание линий (antialiasing), а как его добавить — непонятно.

  • Работает на версиях до/после Lollipop;
  • Хорошая производительность.

Подход относительно прост в реализации и подойдет для случаев, когда требуется быстро добавить в проект необходимую функциональность, а сглаживание линий непринципиально.

Метод Canvas.drawPath() при отрисовке дочерних элементов в контейнере, View.LAYER_TYPE_SOFTWARE

Этот подход также требует наследования от контейнера. В методе dispatchDraw() делаем обрезку по нужной форме с помощью метода Canvas.drawPath() , в который передаем контур и объект класса Paint с инициализацией свойства xfermode .

Объект PorterDuffXfermode(PorterDuff.Mode.CLEAR) позволяет вырезать нужную область на экране, используя режим наложения одного изображения на другое. Зачем тогда вызов setLayerType(View.LAYER_TYPE_SOFTWARE, null) ? Дело в том, что этот режим некорректно работает в других типах Layer. В ином случае за обрезанной фигурой будет белый фон, а нам нужен прозрачный.
Подробнее про PorterDuff в документации .

Соответственно, данная настройка ведет к падению производительности. Но насколько это критично, видно на графике производительности.

В процессе тестирования выяснилось, что перестают работать такие вещи как тень у кнопки. Похоже, проблема именно в View.LAYER_TYPE_SOFTWARE.

  • Работает на версиях до/после Lollipop;
  • Гладкие, плавные линии.
  • Плохая производительность;
  • Не отображается тень на кнопках. Похоже, проблема именно в View.LAYER_TYPE_SOFTWARE;
  • Работают не все виды PorterDuff.Mode.

Метод Canvas.drawPath() при отрисовке дочерних элементов в контейнере, View.LAYER_TYPE_HARDWARE

Ключевым моментом, как и в предыдущем подходе, является переопределение метода dispatchDraw() , в котором используем метод canvas.drawPath() для обрезки. Для корректной работы PorterDuffXfermode при настройке View.LAYER_TYPE_HARDWARE нужно дописать дополнительную логику с объектом Canvas в методе dispatchDraw() .За подсказку спасибо Ilya Nekrasov

Как это выглядит в реализации:

  • Работает на версиях до/после Lollipop;
  • Хорошая производительность;
  • Гладкие, плавные линии.
  • Иногда происходит мерцание, если в контейнере два View и у каждого меняется Alpha, т.е. один объект появляется, другой исчезает. При этом объект, который исчезает, может на доли секунды появляться при 100% Alpha. Мерцание не замечено в версии Android до Lollipop.

Для решения проблемы с закруглением углов в нашем проекте мы использовали данный метод. Избавились от мерцания при переходе между экранами, создав для каждого экрана свой контейнер. Это сказалось на производительности при смене экранов, но не критично и практически незаметно, так как переход занимает менее секунды.

Схематично было так:

Данный подход может быть применен для большинства задач. Учитывая, что в объекте Path можно задать любую форму, это дает практически безграничные возможности. Радует и относительно хорошая производительность. Но из-за дополнительных манипуляций с объектом Canvas , могут возникать побочные эффекты, как это произошло у нас.

Extra

Получив достаточно информации по методам отсечения в Android, хочется проверить, как это работает с изменяемой формой в виде анимации. За основу анимации взял следующее: трансформация звезды в многоугольник и обратно в звезду. Все это вращается вокруг своего центра. Посмотрим, что получилось и как это влияет на производительность.

Метод PorterDuff.Mode + View.LAYER_TYPE_HARDWARE

Метод Canvas.clipPath()

Мнение автора

Каждый из подходов хорошо применим в определенной ситуации.

Больше всего мне понравился подход со свойством View.clipToOutline , так как не нужно делать наследование от классов и он прост в реализации, а возможность задавать форму с помощью объекта Drawable упрощает задание контура для обрезки. Хотелось бы надеяться, что в будущем расширятся возможности для задания формы с помощью View.clipToOutline .

Интересный подход с методом Canvas.clipPath() . Минимум кода для реализации, менее “прихотлив” к версии Android, можно задавать любую форму. Если бы можно было добавить Antialiasing, то это было бы практически идеальным решением.

Что не советовал бы использовать, так это метод с View.LAYER_TYPE_SOFTWARE PorterDuffXfermode — сплошные минусы.

И как более универсальное средство — это реализация с помощью View.LAYER_TYPE_HARDWARE и PorterDuffXfermode . Данное решение работает на всех версиях Android, довольно хорошая производительность, можно задать любую форму контура, но нужно помнить об предостережениях, описанных выше.

В целом, результат исследования меня не особо обрадовал. Может быть я слишком требователен. 😀 Да, мы нашли способ сделать то, что было задумано, но хотелось бы более простого решения, так как наследование не самый лучший вариант. И к тому же нужен более удобный в использовании метод, как в случае с View.clipToOutline . Возможно, в будущем Android API этим нас обрадует. Ну или, может, это проще сделать в Flutter и пора переходить на него?🙂

Ух, это была довольно большая статья. Кто дочитал, тому виртуальный приз 🍬

Ссылка на исходный код . Тестовое устройство: Xiaomi Redmi 4x

Удачного кода, меньше багов, больше счастливых пользователей!

Источник

Оцените статью