Кастомные View
Кастомный View в Android нужен, когда стандартных виджетов недостаточно — свой график, свой layout-контейнер, точное измерение под пропорцию. Ключ к нему — понимать, что система рисует любой View строго в три фазы: сначала спрашивает нужный размер (onMeasure), потом сообщает окончательное место (onLayout), потом просит нарисоваться (onDraw). Каждый механизм кастомного View встраивается в свою фазу.
Главные ловушки — не про синтаксис, а про фазу и про режим. Задать размер в onDraw поздно: родитель уже посчитал раскладку по тому, что вернул onMeasure. А вернуть из onMeasure сырой размер, не прочитав режим MeasureSpec, — значит сломать wrap_content. Полная карта — в слоях ниже.
Карта темы
- Жизненный цикл кастомного View — три фазы
onMeasure→onLayout→onDrawи что делать в каждой. - MeasureSpec — как родитель передаёт размер и режим (
EXACTLY/AT_MOST/UNSPECIFIED) и как их читать. - Фиксированное соотношение сторон — как удержать пропорцию 4:3 через
onMeasure. - Усечение текста — как сокращать нужное поле при нехватке ширины.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Задавать размер в onLayout или onDraw | Поздно — родитель уже разложил view по onMeasure |
Возвращать сырой getSize(spec), игнорируя режим | wrap_content растягивается на весь родитель |
Аллоцировать Paint/Rect внутри onDraw | Аллокации на каждый кадр — рывки при отрисовке |
| Жёстко задавать высоту в пикселях вместо вычисления из ширины | Пропорция ломается при другой ширине родителя |
| Делить ширину двух полей равными весами | Сокращаются оба поля, а не только нужное |
Значение для собеседований
Кастомные View проверяют, понимаете ли вы конвейер отрисовки Android, а не только API виджетов. Кандидат, который называет три фазы по порядку и говорит «размер — в onMeasure через setMeasuredDimension», сразу опережает того, кто «рисует всё в onDraw».
Что обычно проверяют:
- Порядок и назначение
onMeasure,onLayout,onDraw. - Что такое
MeasureSpecи три его режима. - Как удержать соотношение сторон и почему это делают в
onMeasure. - Как сократить нужное из двух полей и роль
ellipsize.
Типичный неверный ответ: «размер view задаётся в onDraw / onLayout». На деле желаемый размер сообщается только в onMeasure через setMeasuredDimension; onLayout расставляет детей, а onDraw уже рисует по посчитанным размерам.