Футбольное табло android studio

Овладение Coordinator Layout

На презентации Google I/O 15, компания Google представила новую версию библиотеки поддержки которая реализует несколько компонентов, сильно связанных со спецификациями Material Design, среди этих компонентов вы можете найти новые типы ViewGroup такие как AppbarLayout , CollapsingToolbarLayout и CoordinatorLayout .

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

CoordinatorLayout

Как и предполагает его название, цель и философия этой ViewGroup является координация view элементов, которые находятся внутри него.

Рассмотрим следующую картинку:

В этом примере можем видеть как view элементы размещены друг относительно друга, не прибегая к детальному просмотру, мы видим как одни View зависят от других. (мы поговорим об этом позже).

Это будет простейшая структура использования CoordinatorLayout :

Рассмотрим скелет данного layout. У этого CoordinatorLayout имеется только три дочерних элемента: AppbarLayout , прокручиваемый view и закрепленный FloatingActionBar .

AppBarLayout

Проще говоря, AppBarLayout это LinearLayout на стероидах, их элементы размещены вертикально, с определенными параметрами элементы могут управлять их поведением, когда содержимое прокручивается.

Это может прозвучать запутано сначала, но как, — «Лучше один раз увидеть, чем сто раз услышать», к вашему вниманию .gif-пример:

В данном случае AppBarLayout это синяя view, размещенная под исчезающим изображением, она содержит Toolbar , LinearLayout с заголовком и подзаголовком и TabLayout с несколькими вкладками.

Мы можем управлять поведением элементов AppbarLayout с помощью параметров: layout_scrollFlags . Значение: scroll в данном случае присутствует почти во всех элементах view, если бы этот параметр не был указан ни в одном из элементов AppbarLayout, он остался бы неизменным, позволяя прокручиваемому контенту проходить позади него.

Со значением: snap , мы избегаем попадания в полу-анимационного-состояния, это значит, что анимация всегда скрывает или отображает полный размер view.

LinearLayout который содержит заголовок и подзаголовок будет всегда отображен при прокручивании вверх, ( enterAlways значение), и TabLayout будет видим всегда так как на него не установлен ни один флаг.

Как видите настоящая мощь AppbarLayout определяется должным управлением его флагами прокрутки в определенных view.

Все эти параметры доступны в документации Google Developers. В любом случае, я рекомендую поиграть с примерами. В конце статьи размещены ссылки на репозитории Github с реализацией примеров.

Флаги AppbarLayout

SCROLL_FLAG_ENTER_ALWAYS : При использовании флага, view будет прокручиваться вниз не зависимо от других прокручиваемых view.
SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED : Дополнительный флаг для ‘enterAlways’, который изменяет возвращаемый view к изначально прокручиваемому, при исчезновении высоты.
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED : При выходе, view будет прокручен до тех пор пока не исчезнет.
SCROLL_FLAG_SCROLL : Элемент view будет прокручиваться в направлении события прокрутки.
SCROLL_FLAG_SNAP : В конце прокрутки, если view видим только частично, он будет докручен до его ближайшего края.

CoordinatorLayout Behaviors

Проведем не большой эксперимент, запустим Android Studio (>= 1.4) и создадим проект из шаблона: Scrolling Activity, ничего не изменяя, компилирием и вот что мы видим:

При рассмотрении сгенерированного кода, ни макеты layout ни java классы не имеют ничего относящегося к маштабированию анимации плавающей кнопки при прокрутке. Почему?

Ответ находится в исходном коде FloatingActionButton , с тех пор как Android Studio v1.2 включает java декомпилятор, с помощью ctrl/cmd + click мы можем проверить исходный код и посмотреть что происходит:

За маштабирование анимации отвечает новый элемент, представленый вместе с design library, под названием Behavior . В данном случае , который зависит от некоторых факторов включая прокрутку, показывать FAB или нет, интересно, не правда ли?

SwipeDismissBehavior

Продолжим углубление в код, если вы посмотрите внутрь пакета виджетов design support library, то сможете найти открытй клас под названием: SwipeDismissBehavior . С этим новым Behavior мы можем очень легко реализовать функцию свайп для отмены в наших шаблонах с CoordinatorLayout :

Custom Behaviors

Создать свой шаблон поведения (Behavior) не так и сложно как может показаться, для начала мы должны принять во внимание несколько основных элементов: child и dependency.

Читайте также:  Как защитить android от взлома

Child и dependency

child это элемент который усиливает поведение, dependency — тот кто будет обслуживать его как тригер для взаимодействия с child элементом. Посмотрим на пример, child — элемент ImageView, а dependency это Toolbar, таким образом, если Toolbar движется, ImageView тоже движется.

Теперь, когда мы определили концепт, можем поговорить о реализации, первым шагом будет наследование от:
, значение T будет класс который принадлежит view, что необходим нам для координации, в данном случае ImageView, после чего мы должны переопределить следующие методы:

  • layoutDependsOn
  • onDependentViewChanged

Метод: layoutDependsOn будет вызван каждый раз когда что-то случится в layout, чтобы вернуть true , как только мы определили dependency, в примере, этот метод срабатывает автоматически при прокручивании (т.к. Toolbar будет двигаться), таким образом, мы можем подать знак нашему child отреагировать соответствующим образом.

Всякий раз когда layoutDependsOn возвращает true будет вызван второй onDependentViewChanged . Вот тут-то мы и должны реализовать нашу анимацию, перевод или движения всегда зависят от предоставленной зависимости.

Источник

Футбольное табло android studio

Андроид приложение «Футбольное табло»

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

  1. Разметка экрана должна содержать текстовые элементы для отображения счета в формате 5 : 0.
  2. Две кнопки в качестве надписей должны содержать названия команд.
  3. Дополнительно может быть создана кнопка «Сброс» для обнуления счета.
  4. Дополнительно можно разместить эмблемы или флаги команд.
  5. Предусмотреть локализацию для англоязычных и русскоязычных стран.
  6. Щелчок по кнопке должен увеличивать счет соответствующей команды на 1.
  7. Предусмотреть сохранение состояния Activity при повороте экрана.
  • Отрисовать интерфейс приложения с использованием сервиса https://ninjamock.com
  • Создать ресурсы приложения
  • Разработать код в соответствии с требованиями задачи
  • Выполнить тестирование приложения на реальном устройстве
  1. Вертикальный (русский и англиский)

  1. Горизонтальный (русский и английский)

Результаты работы приложения на реальном устройстве

Источник

Информационное табло своим руками

Всем привет. Это мой второй пост. И в нем будем собирать своими руками спортивное табло.

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

Естественно первым делом, я пошел в Гугл посмотреть что имеется на рынке. И если в общем случае спортивные табло имеются, к примеру для футбола/хоккея…

то для дартс ничего нет. Ну как нет, какая-то контора предлагает изготовление, но ни фоток готового результата, ни цен — нет.

При игре в 501 игроки используют мобильное приложение для подсчета результата игрока. Коих большое количество. Ну конечно, это же по сути просто калькулятор — его только ленивый не напишет на том же Андроиде. Однако некоторые приложения помимо счета игры имеют на своем борту и ведение статистики по игрокам. Соответственно задача сводилась к тому, чтобы счет игроков отображаемый в приложении продублировать этом спортивном табло.

Мне показали одно из приложений, которым пользуются игроки. Я обратился к разработчику, в братскую Белоруссию, с вопросом, сможет ли он внедрить в свою программу вывод информации на внешнее устройство через BlueTooth. На что он мне ответил, что он сам только-только учится писать приложения на андроиде, и не хочет заморачиваться.

Ну что делать, придется делать самом… Всё сам, своими руками (с)

К слову сказать, к программированию на Андроиде я ни разу не приступал.

В голове нарисовалась такая схема.

Имеется телефон/планшет с приложением, имеется табло с микроконтроллером, модулем Блютус, и светодиодными индикаторами.

Первый же вопрос — какие индикаторы использовать? Однозначно высокие (высотой 15 20 см), однозначно светодиодные.

  • высокая цена
  • неремонтопригодный
  • необходима схема управления и питания
  • не нашел нужного размера (максимум 5 см)

Наборные из сегментов?

Тоже нет, по тем же причинам кроме второй и последней.

И тут в результате мозгового штурма прилетает идея сделать цифры из светодиодной ленты на ws2812b — «умных» управляемых светодиодах. «Даааа, точно же. », — крикнул я, «Спасибо, Костя.» Гениальнее решения и быть не может.

Преимущества данного выбора:

  • дешево (на моем варианте вышло 250 руб за цифру высотой 20 сантиметров),
  • можно легко заменить вышедший из строя светодиод (это важно при использовании ws2812b),
  • управляется всего по одному проводу от микроконтроллера. Не надо городить схему динамический индикации, сдвиговых регистров, драйвер питания. Лента питается от 5 вольт.
  • можно создать цифру любой формы и любого размера.
Читайте также:  Open the camera android

Ну все схему утвердил: 1.приложение -> 2.блютус модуль HC-05 -> 3.микроконтроллер (ардуйня, или stm32) -> 4.лента ws2812b.

Из этой схемы самым сложным(почти невыполнимым) для меня был первый пункт. Со всем остальным я работаю.

Для создания приложений используется среда Android Studiо, которая на моем старом компе очень тяжело работала. (2 ядра, 2 гига, включается запускается минут 5). Я нашел вариант создания простых приложений в онлайн среде Thunkable, которое позволяет программировать в графической среде «блоками». Там накидал простое приложение, настроил блютус. И отобразил на табло нужную информацию.

В какой то момент времени я понял, что использовать эту онлайн среду — это не правильно, надо всё-таки освоить Android Studio. Купил новый комп, установил запустил Studiо. Начал конечно же с HelloWorld. Пришлось разбираться с разметками, лэйаутами, классами, явами и прочей фигнёй. Параллельно купил учетку в Гугль Плей заплатив за это 25 долларов.

Ну а дальше дело времени, осваивать Android и писать код.

Вот как это выглядит в среде разработки Android Studio:

Так выглядит процесс разработки для микроконтроллере stm32:

Само табло изготовили из куска ламината, на который наклеил собранные цифры, ардуину и блютус модуль. Спереди закрыли оргстеклом. И отдали в тестовую эксплуатацию.

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

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

лента ws2812b 1300 руб
контроллер stm32 150 руб
блютус HC-05 200 руб
блок питания 5В 250 руб.
ламинат, оргстекло, крепежи, тонировка — из всяких остатков.

ПС. Главный вдохновитель, Заказчик и участник Дартс-клуба через пару недель будет защищать честь России на Чемпионате Мира по Дартс в Лондоне. Пожелаем ему удачи.

Источник

Полный список

— разбираем как можно использовать LayoutInflater

После изучения SQLite самое время приступить к изучению списков – List. Но перед этим полезно будет узнать про LayoutInflater. Это знание пригодится нам в создании расширенных списков. Также перед этим уроком рекомендую снова прочесть урок про LayoutParams, освежить знания.

LayoutInflater – это класс, который умеет из содержимого layout-файла создать View-элемент. Метод который это делает называется inflate. Есть несколько реализаций этого метода с различными параметрами. Но все они используют друг друга и результат их выполнения один – View.

Как видим, на вход метод принимает три параметра:

resource — ID layout-файла, который будет использован для создания View. Например — R.layout.main
root – родительский ViewGroup-элемент для создаваемого View. LayoutParams от этого ViewGroup присваиваются создаваемому View.
attachToRoot – присоединять ли создаваемый View к root. Если true, то root становится родителем создаваемого View. Т.е. это равносильно команде root.addView(View). Если false – то создаваемый View просто получает LayoutParams от root, но его дочерним элементом не становится.

Посмотрим на практике.

Project name: P0401_LayoutInflater
Build Target: Android 2.3.3
Application name: LayoutInflater
Package name: ru.startandroid.develop.p0401layoutinflater
Create Activity: MainActivity

Открываем main.xml и рисуем такой экран:

На экране две ViewGroup — linLayout и relLayout. В них по TextView с соответствующим текстом.

Создадим еще один layout-файл text.xml:

Тут просто TextView без всяких ViewGroup. На нем мы и будем испытывать LayoutInflater.

Открываем MainActivity.java и пишем код:

Мы получаем LayoutInflater методом getLayoutInflater, используем его для получения View-элемента из layout-файла text.xml и считываем LayoutParams у свежесозданного view.

Обратите внимание на параметры, которые мы использовали для метода inflate. Мы указали ID layout-ресурса, передали null в качестве родительского элемента и, соответственно, привязка к родителю — false.

Все сохраним и запустим.

На экране ничего не изменилось. Т.к. мы конвертнули layout в view, но никуда его не поместили. Он просто висит в памяти.

Читайте также:  Как поставить живые обои андроид хонор

Class of view: class android.widget.TextView
LayoutParams of view is null: true
Text of view: Layout with TextView

Мы видим класс созданного элемента — TextView. Все верно — этот элемент и был в файле text.xml. Далее видим null вместо LayoutParams. Это произошло потому, что родителя в методе inflate мы указали null. А именно от родителя view и должен был получить LayoutParams. Третья строка лога показывает текст TextView. Он тот же, что и в layout-файле text.xml – все верно.

Давайте немного изменим программу. Будем добавлять наш созданный элемент в linLayout из main.xml. Делается это просто – командой addView.

(добавляете только выделенные строки)

Мы нашли linLayout с экрана и добавили в него созданный с помощью LayoutInflater элемент.

Сохраняем, запускаем. Видим, что элемент добавился на экран в linLayout.

Теперь давайте попробуем указать родителя (root) при вызове метода inflate. Перепишем метод onCreate:

Мы находим элементы linLayout и relLayout с экрана и с помощью LayoutInflater создаем два View-элемента из layout-файла text.xml. Для первого указываем root – linLayout, для второгоrelLayout. Но третий параметр attachToRoot оставляем false. Это значит, что созданный View-элемент получит LayoutParams от root-элемента, но не добавится к нему.

Все сохраним, запустим. На экране ничего не поменялось. Т.к. мы ни к чему новые элементы не добавляли и attachToRoot = false.

Class of view1: class android.widget.TextView
Class of layoutParams of view1: class android.widget.LinearLayout$LayoutParams
Text of view1: Layout with TextView
Class of view2: class android.widget.TextView
Class of layoutParams of view2: class android.widget.RelativeLayout$LayoutParams
Text of view2: Layout with TextView

По логам видно, что класс созданных элементов – TextView. А класс LayoutParams различается. В первом случае – это LinearLayout$LayoutParams, т.к. в качестве root элемента в методе inflate мы указали linLayout, а это объект класса LinearLayout. Во втором случае класс LayoutParams у созданного элемента — RelativeLayout$LayoutParams. Потому, что в качестве root указали relLayout (класс RelativeLayout).

Теперь у нас два варианта, как добавить созданные view1 и view2 на экран.

1) Снова использовать методы addView

2) Передавать true в качестве третьего параметра метода inflate. Тогда созданный View-элемент будет добавлен к root.

Выберем второй вариант и внесем изменения в код:

Передаем true в качестве третьего параметра в методе inflate и убираем строки выведения в лог текстов из TextView. Сейчас будет понятно почему.

Все сохраним и запустим приложение.

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

Class of view1: class android.widget.LinearLayout
Class of layoutParams of view1: class android.widget.LinearLayout$LayoutParams
Class of view2: class android.widget.RelativeLayout
Class of layoutParams of view2: class android.widget.LinearLayout$LayoutParams

Обратите внимание на класс элементов. В первом случае — это LinearLayout, а во втором — RelativeLayout. Т.е. метод inflate вернул нам не созданные из layout-файла View-элементы, а те, что мы указывали как root. А созданные из layout-файла View элементы он добавил в root как дочерние аналогично команде addView. Это произошло потому, что мы указали true в третьем параметре (attachToRoot) метода inflate.

Соответственно LayoutParams для view1 и view2 будет LinearLayout$LayoutParams, т.к. linLayout и relLayout имеют родителя LinearLayout. И LayoutParams берут от него.

Для закрепления темы на следующем уроке сделаем пример поинтереснее.

На следующем уроке:

— делаем свой вариант списка

getLayoutInflater

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

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