- Программное добавление и удаление виджета
- Добавляем виджет
- Удаляем виджет
- activity_main.xml
- layer1.xml
- layer2.xml
- Реализация Custom View-компонента в Android
- Рисуем!
- Constructor
- onAttachedToWindow
- onMeasure
- onLayout
- onDraw
- View Update
- Animation
- Creating Dynamic Layouts in Android
- What are Dynamic Layouts?
- Why do we need them?
- Where do Dynamic Layouts excel?
Программное добавление и удаление виджета
Обычно мы размещаем виджеты через XML. Но можно это делать и программно. Такой подход используется при динамическом размещении, когда неизвестно, сколько элементов должно быть на экране.
Добавляем виджет
Допустим у нас есть простейшая разметка.
Пустая компоновка LinearLayout с идентификатором mainlayout не содержит вложенных виджетов. Через метод addView(view) класса LinearLayout мы можем добавить нужный нам элемент.
Удаляем виджет
Существует и обратный метод для удаления вида — removeView(), а также метод removeAllViews(), удаляющий все дочерние элементы родителя. Рассмотрим следующий пример. Создадим разметку, где компонент LinearLayout с идентификатором master будет родителем для будущих элементов, которые мы будем добавлять или удалять:
activity_main.xml
Создадим пару дополнительных макетов, которые будет дочерними элементами для FrameLayout. Мы будем управлять ими программно.
layer1.xml
layer2.xml
Напишем код, который будет добавлять или удалять компоновки через флажки.
Обратите внимание, что добавление идёт в том порядке, как мы отмечаем флажки. Если мы отметим флажком второй CheckBox, то сначала на экране появится блок с компоновкой layer2.xml, а уже ниже компоновка layer1.xml. На скриншоте представлен этот вариант.
Получить доступ к дочерним элементам можно через методы getChildCount() и getChildAt().
Источник
Реализация Custom View-компонента в Android
Каждый день мы пользуемся разными приложениями и несмотря на их различные цели, большинство из них очень похожи между собой с точки зрения дизайна. Исходя из этого, многие заказчики просят специфичные, индивидуальные макеты внешний вид, который не воплотило ещё ни одно приложение, чтобы сделать своё Android приложение уникальным и отличающимся от других.
Если какая-то специфичная особенность, из тех которые просит заказчик, требует особые функциональные возможности, которые невозможно сделать с помощью встроенных в Android View-компонентов, тогда нужно реализовывать собственный View-компонент (Custom View). Это не значит, что нужно всё взять и бросить, просто потребуется некоторое время на его реализацию, к тому же это довольно интересный и увлекательный процесс.
Я недавно попал в похожую ситуацию: мне нужно было создать индикатор страниц для Android ViewPager. В отличи от iOS, Android не предоставляет такой View-компонент, поэтому мне пришлось делать его самому.
Я потратил довольно много времени на его реализацию. К счастью, этот Custom View-компонент можно использовать и в других проектах, поэтому чтобы сэкономить личное время и время других разработчиков, я решил оформить всё это дело в виде библиотеки. Если вам нужен похожий функционал и не хватает времени на его реализацию собственными силами, можете взять его с этого GitHub репозитория.
Рисуем!
Так как в большинстве случаев разработка Custom View-комопонента занимает больше времени, чем работа с обычными View-компонентами, создавать их целесообразно только тогда, когда нет более простого способа реализовать специфичную особенность, или когда у вас есть ниже перечисленные проблемы, которые Custom View-компонент может решить:
- Производительность. Если у вас есть много View-компонентов в одном layout-файле и вы хотите оптимизировать это с помощью создания единственного Custom View-компонента;
- Большая иерархия View-компонентов, которая сложна в эксплуатации и поддержке;
- Полностью настраиваемый View-компонент, которому нужна ручная отрисовка;
Если вы ещё не пробовали разрабатывать Custom View, то эта статья — отличная возможность окунуться в эту тему. Здесь будет показана общая структура View-компонента, как реализовывать специфичные вещи, как избежать распространённые ошибки и даже как анимировать ваш View-компонент!
Первая вещь, которую нам нужно сделать, это погрузиться в жизненный цикл View. По какой-то причине Google не предоставляет официальную диаграмму жизненного цикла View-компонента, это довольно распространённое среди разработчиков непонимание, поэтому давайте рассмотрим её.
Constructor
Каждый View-компонент начинается с Constructor’а. И это даёт нам отличную возможность подготовить его, делая различные вычисления, устанавливая значения по умолчанию, ну или вообще всё что нам нужно.
Но для того чтобы сделать наш View-компонент простым в использовании и установке, существует полезный интерфейс AttributeSet. Его довольно просто реализовать и определённо стоит потратить на это время, потому что он поможет вам (и вашей команде) в настройке вашего View-компонента с помощью некоторых статических параметров на последующих экранах. Во-первых, создайте новый файл и назовите его «attrs.xml». Этот файл может содержать все атрибуты для различных Custom View-компонентов. Как вы можете видеть в этом примере есть View-компонент названный PageIndicatorView и один атрибут piv_count.
Во-вторых, в конструкторе вашего View-компонента, вам нужно получить атрибуты и использовать их как показано ниже.
- При создании кастомных атрибутов, добавьте простой префикс к их имени, чтобы избежать конфликтов имён с другими View-компонентами. Обычно добавляют аббревиатуру от названия View-компонента, поэтому у нас префикс «piv_»;
- Если вы используете Android Studio, то Lint будет советовать вам использовать метод recycle() до тех пор пока вы сделаете это с вашими атрибутами. Причина заключается в том, что вы можете избавиться от неэффективно связанных данных, которые не будут использоваться снова;
onAttachedToWindow
После того как родительский View-компонент вызовет метод addView(View), этот View-компонент будет прикреплён к окну. На этой стадии наш View-компонент будет знать о других View-компонентах, которые его окружают. Если ваш View-компонент работает с View-компонентами пользователя, расположенными в том же самом «layout.xml» файле, то это хорошее место найти их по идентификатору (который вы можете установить с помощью атрибутов) и сохранить их в качестве глобальной ссылки (если нужно).
onMeasure
Этот метод означает, что наш Custom View-компонент находится на стадии определения собственного размера. Это очень важный метод, так как в большинстве случаев вам нужно определить специфичный размер для вашего View-компонента, чтобы поместиться на вашем макете.
При переопределении этого метода, всё что вам нужно сделать, это установить setMeasuredDimension(int width, int height).
При настройке размера Custom View-компонента вы должны обработать случай, когда у View-компонента может быть определённый размер, который пользователь (прим. переводчика: программист работающий с вашим View-компонентом) будет устанавливать в файле layout.xml или программно. Для вычисления этого свойства, нужно проделать несколько шагов:
- Рассчитать размер необходимый для содержимого вашего View-компонента (ширину и высоту);
- Получить MeasureSpec вашего View-компонента (ширину и высоту) для размера и режима;
- Проверить MeasureSpec режим, который пользователь устанавливает и регулирует (для ширины и высоты);
Посмотрите на значения MeasureSpec:
- MeasureSpec.EXACTLY означает, что пользователь жёстко задал значения размера, независимо от размера вашего View-компонента, вы должны установить определённую ширину и высоту;
- MeasureSpec.AT_MOST используется для создания вашего View-компонента в соответствии с размером родителя, поэтому он может быть настолько большим, насколько это возможно;
- MeasureSpec.UNSPECIFIED — на самом деле размер обёртки View-компонента. Таким образом, с этим параметром вы можете использовать желаемый размер, который вы расчитали выше.
Перед установкой окончательных значений в setMeasuredDimension, на всякий случай проверьте эти значения на отрицательность Это позволит избежать любых проблем в предпросмотре макета.
onLayout
Этот метод позволяет присваивать размер и позицию дочерним View-компонентам. У нас нет дочерних View-компонентов, поэтому нет смысла переопределять этот метод.
onDraw
Вот здесь происходит магия. Два объекта, Canvas и Paint, позволяют вам нарисовать всё что вам нужно. Экземпляр объекта Canvas приходит в качестве параметра для метода onDraw, и по существу отвечает за рисование различных фигур, в то время как объект Paint отвечает за цвет этой фигуры. Простыми словами, Canvas отвечает за рисование объекта, а Paint за его стилизацию. И используется он в основном везде, где будет линия, круг или прямоугольник.
Создавая Custom View-компонент, всегда учитывайте, что вызов onDraw занимает довольно много времени. При каких-то изменениях, сроллинге, свайпе вы будете перерисовывать. Поэтому Andorid Studio рекомендует избегать выделение объекта во время выполнения onDraw, вместо этого создайте его один раз и используйте в дальнейшем.
- При отрисовке, имейте в виду переиспользование объектов вместо создания новых. Не полагайтесь на вашу IDE, которая должна подсветить потенциальную проблему, а сделайте это самостоятельно, потому что IDE может не увидеть этого, если вы создаёте объекты внутри методов вызываемых в onDraw;
- Во время отрисовки, не задавайте размер прямо в коде. Обрабатывайте случай, когда у других разработчиков может быть тот же самый View-компонент, но с другим размером, поэтому делайте ваш View-компонент зависимым от того размера, который ему присвоен;
View Update
Из диаграммы жизненного цикла View-компонента, вы можете заметить что существует два метода, которые заставляют View-компонент перерисовываться. Методы invalidate() и requestLayout() могут помочь вам сделать ваш Custom View-компонент интерактивным, что собственно поможет изменять его внешний вид во время выполнения. Но почему их два?
Метод invalidate() используется когда просто нужно перерисовать View-компонент. Например, когда ваш View-компонент обновляет свой текст, цвет или обрабатывает прикосновение. Это значит, что View-компонент будет вызывать только метод onDraw, чтобы обновить своё состояние.
Метод requestLayout(), как вы можете заметить будет производить обновление View-компонента через его жизненный цикл, только из метода onMeasure(). А это означает, что сразу после обновления View-компонента вам нужно его измерить, чтобы отрисовать его в соответствии с новыми размерами.
Animation
Анимации в Custom View-компонентах, это по кадровый процесс. Это означает, что если вы например захотите сделать анимированным процесс изменения радиуса круга от маленького к большому, то вам нужно увеличивать его последовательно и после каждого шага вызывать метод invalidate для отрисовки.
Ваш лучший друг в анимации Custom View-компонентов — это ValueAnimator. Этот класс будет помогать вам анимировать любые значения от начала до конца и даже обеспечит поддержку Interpolator (если нужно).
Не забывайте вызывать метод Invalidate каждый раз, когда изменяется значение анимации.
Надеюсь, что эта статья поможет вам сделать свой первый Custom View-компонент. Если вы захотите получить больше информации по этой теме, то может посмотреть хорошее видео.
Источник
Creating Dynamic Layouts in Android
What are Dynamic Layouts?
Generally, we develop the layout for an Android application by creating the XML file. These are called static layouts.
Static you ask? Yes, because you can not add/delete any View Type in XML on runtime.
Dynamic layouts are developed using Java and can be used to create layouts that you would normally create using an XML file.
Why do we need them?
Let’s say we are fetching some data from our server and we want to create n number of fields/buttons/options in our layout. How do we do that using the only XML? That’s right!
But we can use Java to replicate the exact layout that we would normally create using XML.
It can be used to create LinearLayout, ScrollView, etc.which can further add TextView, EditText, RadioButtons, Checkbox inside it.
Where do Dynamic Layouts excel?
Let’s say we want to show some items in our layout that were frequently bought together(all items are of the same View Type).
There are quite a few ways to show them in our layout:
1. Adding static views in our XML(if we know the exact amount of items).
2. Using Recycler View to inflate the items in our layout.
3. Creating Dynamic Views using Java.
What if we do not know the exact number of items to be displayed and our
layout require different View Types( like 3 TextViews, 2 CheckBoxes, etc.)?
Possible solutions to tackle this problem:
1. Adding static views in our XML won’t work this time because we do not . know the exact number of views we need.
2. Using Recycler View could work but the same View Types should be grouped together in a list. There is not much flexibility in this case.
3. However, this is where Dynamic Layouts take the lead! They are flexible and can add multiple View Types to our layout in any order.
Источник