Как сделать круглые виджеты

Добавил пользователь Владимир З.
Обновлено: 05.10.2024

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

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

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

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

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

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

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

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

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

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

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

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

enter image description here

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

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

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

res/drawable / round_outline.в XML

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

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

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

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

enter image description here

Примечание:

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

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

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

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

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

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

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

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

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

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

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

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

выход:

enter image description here

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Не нужно думать, что виджет у вас будет один.

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

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

И сделаем код iframe вида:

И это будет большой ошибкой по нескольким причинам.

Невозможность расширения

У iframe довольно много ограничений, связанных с защитой конфиденциальности в браузере. Даже просто растянуть iframe под размер его содержимого без внешнего javascript кода не получится. Стилизовать можно будет только то, что лежит непосредственно в iframe, на сам тэг и его обертку никак нельзя будет повлиять.

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

Про то, какие проблемы есть в работе с iframe и их решении, поговорим попозже.

Лишние запросы на бэкенд

Если на сайт будет установлено 5 таких одинаковых виджетов, то на ваш сервер придет 5 одинаковых запросов, хотя по факту нужен был только один. Конечно, можно сделать кеш на nginx и не пропускать запрос дальше, но зачем нам самим себе делать паразитные запросы? С таким кодом изменить логику получения данных не получится без изменения кода вставки виджета. Если виджет будет установлен на десятках сайтов, даже не самых популярных, в сумме они могут давать заметную нагрузку.

А как надо делать?

Если вы когда-нибудь устанавливали на сайт какой-нибудь виджет, например, от ВК, то могли заметить, что код виджета разделен на две части: библиотеку (SDK — Software Development Kit) и инициализацию виджетов:

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

Мы видим, что для вставки любого виджета нужно один раз подключить SDK и добавить один пустой тэг с инициализацией виджета. А дальше все делает javascript: он может делать любые запросы и любое их количество на бэкенд, и разработчики виджета могут в любой момент эту логику изменить без изменения кода виджета на сайте. В итоге из html на сайте для виджета должен быть только пустой контейнер с уникальным id. Чтобы не томить вас ожиданием, давайте сразу напишем пример SDK и рендер простого виджета.

А потом поговорим о том, что же у нас получилось и на что стоит обратить внимание.

Код библиотеки:

Код вставки:

Выглядит страшно и как-то избыточно, давайте разбираться, зачем все это.

Сразу в глаза бросается атрибут async у тэга script. Он позволит браузеру не ждать загрузки нашего скрипта и продолжить отрисовывать сайт. Это важно: если по каким-то причинам наш скрипт будет недоступен (недоступен сервер, фаервол компании), это не должно влиять на скорость загрузки сайта клиента. Но все не так просто. Раз скрипт загружается асинхронно, это значит, что когда браузер дойдет до места, где инициализируется наш виджет, наш SDK может быть еще не загружен, и если просто вызвать метод из библиотеки — будет ошибка, причем плавающая, в зависимости от того, успел загрузиться скрипт или нет.

Поэтому в месте вызова виджета мы должны обработать оба сценария, когда SDK загрузился и еще нет.

В первом случае мы просто вызываем функцию init(). Во втором — откладываем выполнение этой функции до момента, когда скрипт загрузится, добавляя замыкание в очередь. А последней строчкой в нашем SDK вызывается метод runInitCallbacks, который как раз и выполнит все отложенные инициализации.

Тут же есть защита от повторного подключения SDK, ведь пользователи могут проигнорировать ваши требования и вставить скрипт библиотеки десять раз.

Теперь наш код запускается всегда и не блокирует отрисовку страницы!

Название объекта SDK и id контейнеров должны быть уникальными, ведь наш код будет выполняться на совершенно разных сайтах. Ни в коем случае нельзя нарваться на совпадения. ID контейнеров желательно генерировать уникальными, например, через uniqid(). Нельзя надеяться и на сторонние библиотеки, установленные на сайте, и совсем не желательно приносить их с собой. Да, я о jQuery, как вы уже догадались.

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

На кодировку сайта тоже не стоит полагаться, и даже в наше время встречаются сайты на cp1251. Поэтому кодировку скрипта нужно явно задать в ответе сервера в заголовке Content-Type.

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

Мы будем постоянно дорабатывать наш SDK, но браузеры кэшируют скрипты, если разработчик не дал других инструкций. Мы должны сами задать время, на которое можно кешировать нашу библиотеку, через заголовок Expires, например, час — адекватное время. С кешированием на фронтенде разобрались, теперь поговорим про бэкенд. Как уже обсуждали выше, обслуживание запросов со сторонних виджетов может создавать ощутимую нагрузку просто от количества сайтов, где виджеты установлены. Но чаще всего данные для всех пользователей в этих виджетах одинаковые, нет смысла запускать приложение, а тем более ходить в базу данных за ними на каждый запрос. Такие запросы вообще дальше nginx можно не пропускать, настроив кеширование на нем.

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

Iframe — по сути, отображение сайта в сайте. Вернемся к нашему кейсу с кнопкой покупки билетов. Если мы хотим при клике открывать попап со страницей выбора места — без iframe нам не обойтись. Какие же там есть нюансы?

Неработающие cookie

Уже давно многие браузеры по умолчанию начинают запрещать использование cookie для сторонних сайтов (это когда домен iframe отличается от родительского сайта). Это значит, что при переходе между страницами внутри фрейма не получится отследить сессию (localStorage тоже не работает).Тут выход простой — не перезагружать страницы и делать SPA. Идентификатор сессии можно будет легко сохранить в переменной в js.

Общение с SDK

Спасибо за внимание, надеюсь, вы узнали для себя что-то новое.

Автор статьи: Сергей Никитченко, технический директор, Студия Валерия Комягина.

С выходом iOS 14 виджеты буквально получили вторую жизнь на iPhone. Если раньше это были небольшие информационные окна в отдельном разделе операционной системы, то сейчас виджеты можно размещать в любом месте экрана, на любом рабочем столе, причем сколько угодно! Но к удивлению популярностью стали пользоваться не столько виджеты от уже установленных приложений (вроде почты, календаря и прочего), а программы, позволяющие создавать собственные виджеты. Одним из самых популярных приложений для создания виджетов оказалось Widgetsmith. Что в нем такого особенного, и как создать свой виджет?


С этим приложением можно сделать какой угодно виджет

Что такое Widgetsmith

В приложении Widgetsmith на iPhone есть три различных размера виджетов на выбор: маленький, средний и большой. Каждый виджет может отображать различную информацию и настраиваться с использованием множества стилей, цветов шрифтов, фона и оттенков.

Первое, что вам нужно сделать, это выбрать, какую информацию вы хотите, чтобы виджет отображал на главном экране. Вот какие данные можно вывести в Widgetsmith:

  • Время;
  • Дата;
  • Пользовательские: фото, текст, альбом;
  • Календарь;
  • Напоминания;
  • Погода;
  • Здоровье и активность;
  • Приливы;
  • Астрономия.


Виджеты, созданные в Widgetsmith. Хотите так же? Читайте ниже

Как пользоваться Widgetsmith

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


Выберите размер и тип виджета

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


Типов виджетов очень много, некоторые бесплатные, другие за деньги

Вот, например, как создать текстовый виджет Widgetsmith. Выбираете размер виджета и настраиваете его: выбираете Text (тип данных), а затем меняете цвет шрифта, фон, тип шрифта — в общем, настраиваете так, как надо.


Создание текстового виджета


Выберите тип виджета Photo

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


Добавьте виджет на рабочий стол

А если еще добавить к виджетам Widgetsmith собственные иконки, можно вообще изменить рабочий стол на айфоне до неузнаваемости.

Как добавить виджет в iOS 14


Можно сделать несколько виджетов и переключаться между ними

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

Если вы еще не скачали это приложение, можете попробовать по ссылке ниже. Свои рабочие столы можете скидывать в нашем чате в Telegram, интересно, что у вас получится.


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

Введение

Представьте себе ситуацию, будто бы вы написали собственный лаунчер для андроид с поддержкой виджетов (возможно, в следующей статье я кратко расскажу, как это сделать). Трехмерный виджет фотографий будет выделять ваш лаунчер на фоне других. Как и в случае со стандартным виджетом фотографий Xperia, наш виджет представляет собой кастомный View, запущенный в процессе нашего лаунчера.

Основа виджета


Класс PhotoWidgetReceiver оставим пустым:


String className — имя класса, унаследованного от BroadcastReciever, в нашем случае это PhotoWidgetReceiver. Лаунчер ищет в виджете класс PhotoWidget, в котором находится описание виджета. Вот его содержание:


Структура этого класса должна быть строго постоянной во всех ваших нестандартных (advanced) виджетах, т.к. такая же структура методов и в классе AdvancedWidgetInfo вашего лаунчера.

Непосредственно View

ContentObserver регистрирует все изменения во внешней памяти. Например, при добавлении фотографии метод onChange(boolean selfChange) вызывается несколько раз с интервалом в пару миллисекунд. Метод loadThumbnails() грузит миниатюры всех фотографий в отдельном потоке. Каждый раз при срабатывании метода onChange ContentObserver'а создаётся новый поток для создания миниатюр. Возникает ситуация, когда при добавлении одной фотографии сразу же создаётся одновременно несколько потоков, делающих одно и то же действия. Для того, чтобы избежать этой ситуации в переменной loaderId хранится id последнего созданного потока, а во всех потоках присутствует сравнение сохраненного id и id данного потока. Если цифры не равны, поток уничтожается.

Жесты листания и броска не вызывают перемещение холста View, как это принято. Вместо этого происходит изменение переменной getScrollY. Integer getSelected() возвращает текущую позицию в массиве миниатюр, float getSelectedPercent() возвращает угол наклона миниатюр относительно зрителя. Значение 0,5 соответствует 45 градусам. Возможно, следующая картинка прояснит ситуацию:


В методе onTouchEvent(MotionEvent me) важно не забыть вызывать getParent().requestDisallowInterceptTouchEvent(true) для того, чтобы во время листания миниатюр в виджете не происходило листание столов в лаунчере.

Ну и в конце пару слов о классе Transformation. Он возвращает матрицу трансформации для миниатюр в зависимости от того, что возвращают описанные выше getSelected() и getSelectedPercent().

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

Заключение

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

Читайте также: