Кастомные View
Жизненный цикл кастомного View в Android — onMeasure, onLayout, onDraw и MeasureSpec.
3 вопросов
JuniorДизайнИногдаСохранить кастомный View в фиксированном соотношении 4:3 при любой ширине родителя
Сохранить кастомный View в фиксированном соотношении 4:3 при любой ширине родителя
Переопределите onMeasure: возьмите ширину родителя из width MeasureSpec, задайте высоту width * 3 / 4, затем вызовите setMeasuredDimension. Альтернатива без кода — ConstraintLayout с app:layout_constraintDimensionRatio="4:3".
Типичные ошибки
- ✗Жёстко задавать высоту в пикселях вместо вычисления из измеренной ширины
- ✗Вызывать
setMeasuredDimensionс сырыми значениямиMeasureSpec, не вычислив соотношение - ✗Пытаться задать соотношение в
onDrawилиonLayout, а не вonMeasure
Уточняющие вопросы
- →Как извлечь размер и режим из width
MeasureSpec? - →Что изменится, если родитель передаст высоту в режиме
EXACTLY, а неAT_MOST?
SeniorДизайнИногдаСпроектируйте View со списком тегов, переносящий приоритетно упорядоченный список текстовых тегов максимум в ДВЕ строки. Правила: теги размещаются по приоритету (сначала самый высокий); занято не более двух строк; если тег не влезает на текущую строку — пропустите его и попробуйте СЛЕДУЮЩИЙ влезающий; и если тег влез бы только на следующую строку, а более поздний тег ещё влезает на ТЕКУЩУЮ — поставьте этот поздний тег на текущую строку первым (менее приоритетные теги всплывают, заполняя пробелы). Пример порядка входа: ["Как", "Вам", "Такое", "И", "Ещё вот такое при такое", "А?"]. Опишите реализацию как кастомный ViewGroup — что вы делаете в onMeasure и onLayout, как жадно упаковываете теги по двум рядам с правилом всплытия и как определяете ширину тега (грубое сравнение по длине текста допустимо). Всплытие можно опустить в первом приближении.
Спроектируйте View со списком тегов, переносящий приоритетно упорядоченный список текстовых тегов максимум в ДВЕ строки. Правила: теги размещаются по приоритету (сначала самый высокий); занято не более двух строк; если тег не влезает на текущую строку — пропустите его и попробуйте СЛЕДУЮЩИЙ влезающий; и если тег влез бы только на следующую строку, а более поздний тег ещё влезает на ТЕКУЩУЮ — поставьте этот поздний тег на текущую строку первым (менее приоритетные теги всплывают, заполняя пробелы). Пример порядка входа: ["Как", "Вам", "Такое", "И", "Ещё вот такое при такое", "А?"]. Опишите реализацию как кастомный ViewGroup — что вы делаете в onMeasure и onLayout, как жадно упаковываете теги по двум рядам с правилом всплытия и как определяете ширину тега (грубое сравнение по длине текста допустимо). Всплытие можно опустить в первом приближении.
Кастомный ViewGroup: в onMeasure измерьте каждого ребёнка, затем жадно упакуйте теги по приоритету в два ряда — берите тег, если влезает в текущий ряд, иначе пробуйте более поздние влезающие перед переходом дальше, останавливаясь после двух рядов. Размер сообщите через setMeasuredDimension; в onLayout разместите каждого по ряду/x.
Типичные ошибки
- ✗Хвататься за готовый layout manager, который не обеспечивает лимит в две строки и правило всплытия
- ✗Останавливаться на первом не влезшем теге вместо попытки взять более поздние влезающие в ряд
- ✗Делать упаковку в
onDraw, а не вonMeasure/onLayout
Уточняющие вопросы
- →Как удержать жадную упаковку по двум рядам в рамках одного прохода
onMeasure? - →Как немоноширинный шрифт изменит вашу грубую оценку ширины по длине текста?
MiddleДизайнРедкоДва однострочных текстовых поля рядом — сокращать первое, когда оба не влезают
Два однострочных текстовых поля рядом — сокращать первое, когда оба не влезают
Разместите два однострочных поля слева направо; при нехватке места сокращайте ПЕРВОЕ. Используйте цепочку ConstraintLayout с layout_constrainedWidth и ellipsize=end, отдавая приоритет ширине второго. Или свой onMeasure, который сначала меряет второе поле, а остаток ширины отдаёт первому.
Типичные ошибки
- ✗Делить ширину равными весами — тогда сокращаются оба поля, а не только первое
- ✗Мерить первое поле раньше второго, и первое забирает место, нужное второму
- ✗Забыть
ellipsize, из-за чего переполненное поле обрезается без многоточия
Уточняющие вопросы
- →Как в своём
onMeasureзарезервировать ширину второго поля до измерения первого? - →Какие настройки
ellipsizeиmaxLinesдержат каждое поле в одну строку?