UI

https://developer.android.com/design/ui
https://developer.android.com/design/ui/mobile
https://developer.android.com/design/ui/large-screens
https://developer.android.com/design/ui/widget
https://developer.android.com/design/ui/wear
https://developer.android.com/design/ui/tv
https://developer.android.com/studio/write/draw9patch
https://developer.android.com/topic/performance/vitals/render
https://m3.material.io/Material3
https://m2.material.io/design/color/the-color-system.htmlMaterial2 Color system
https://fonts.google.com/Google Fonts
https://fonts.google.com/iconsGoogle Icons
https://pictogrammers.com/library/mdi/Material Design Icons
https://www.color-name.com/hexName a Color
https://icon.kitchen/App Icon Generator
https://romannurik.github.io/AndroidAssetStudio/icons-app-shortcut.htmlApp Shortcut Icon Generator
https://mockuphone.com/Screenshots Device Mockups Generator

Единицы измерения

dpDensity-independent pixels. Независимые от разрешения пиксели. Используются, чтобы элементы сохраняли размер независимо от разрешения экрана. 1 dp = 160 px (базовая плотность).
spScalable pixels. Используется для определения размеров текста. Не следует использовать для размеров макета. По умолчанию sp имеет тот же размер, что и dp, но изменяется в зависимости от настроек текста пользователя.
nodpiРесурсы для всех разрешений экранов. Система не масштабирует ресурсы, помеченные этим квалификатором, независимо от текущей плотности экрана.
anydpiЭти ресурсы имеют приоритет выше, чем у квалификаторов конкретной плотности экрана. Как правило используются для векторных картинок.

Слои

Layer List

LayerDrawable - drawable, который управляет массивом других drawables. Каждый drawable ресуется порядке списка, последнее рисуется сверху.

<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android">
    
		<item
        android:drawable="@drawable/drawable_resource"
				android:id="@id/resource_name"
				android:top="dimension"
				android:right="dimension"
				android:bottom="dimension"
				android:left="dimension" />

    <item
        android:top="20dp"
				android:left="20dp">

        <bitmap
            android:src="@drawable/android_blue"
						android:gravity="center" />

    </item>

</layer-list>

State List

StateListDrawable — drawable, определенный в XML, который использует несколько разных изображений для представления одной и той же графики в зависимости от состояния объекта.

<selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:state_pressed="true"
				android:drawable="@drawable/button_pressed" /> <!-- pressed -->

    <item
        android:state_focused="true"
				android:drawable="@drawable/button_focused" /> <!-- focused -->

    <item
        android:state_hovered="true"
				android:drawable="@drawable/button_focused" /> <!-- hovered -->

    <item
        android:drawable="@drawable/button_normal" /> <!-- default -->

</selector>

Level list

An XML file that defines a drawable that manages a number of alternate Drawables, each assigned a maximum numerical value. Creates a LevelListDrawable.

<level-list
    xmlns:android="http://schemas.android.com/apk/res/android">
    
		<item
        android:drawable="@drawable/status_off"
				android:maxLevel="0" />

    <item
        android:drawable="@drawable/status_on"
				android:maxLevel="1" />

</level-list>

Bitmap

Растровое цифровое изображение, состоящее из матрицы точек. Каждая точка соответствует отдельному пикселю на дисплее. Каждой точке может быть присвоен цвет.

9-Patch

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

Density

Плотность экрана - характеристика устройства, отражающая количество пикселей на физической площади экрана. В Android используется сокращение DPI (dot per inch). Экраны должны быть сверстаны так, чтобы размеры элементов выглядели одинаково на экранах с разной плотностью пикселей.

Server-Driven UI

SDUI. Подход для динамичного и гибкого пользовательского интерфейса, когда сервер посредством API сообщает приложению, какие компоненты и с каким контентом отображать.

Plurals

Для русских строк корректно будет работать только если в системе установлен русский язык.

LayoutInflater

Используется для преобразования XML-файлов разметки в соответствующие объекты View.

// Получаем LayoutInflater из контекста
val inflater = LayoutInflater.from(context)

// Используем inflater для создания View из XML
val view = inflater.inflate(R.layout.custom_view_layout, null)

attachToRoot

Если вы используете LayoutInflater в производительном коде, например, в адаптерах RecyclerView, рекомендуется использовать метод inflate с параметром attachToRoot = false, чтобы избежать лишних операций и улучшить производительность.

val view = LayoutInflater.from(context).inflate(R.layout.my_layout, rootView, attachToRoot = true)

AsyncLayoutInflater

Позволяет асинхронно инфлейтить XML-разметку. Это полезно для улучшения производительности и избегания блокировки основного потока приложения при создании сложных или ресурсозатратных пользовательских интерфейсов. Выполняется в фоновом потоке.

AsyncLayoutInflater(context).inflate(R.layout.my_layout, null) { inflatedView, _, _ ->
    // Этот блок кода выполняется после завершения инфлейтации
    // Вы можете использовать inflatedView для дальнейших операций
}
Choreographer

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

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

Планирование и обработка кадров. Класс управляет планированием и обработкой кадров в цикле отображения. Он гарантирует, что обновления пользовательского интерфейса и отрисовка происходят в нужное время.

Методы для добавления задач. Choreographer предоставляет методы для добавления задач, которые будут выполняться до или после обновления экрана.

postFrameCallback

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

Choreographer.getInstance().postFrameCallback(object: Choreographer.FrameCallback {
    override fun doFrame(frameTimeNanos: Long) {
        // Ваш код для обновления UI
        Choreographer.getInstance().postFrameCallback(this) // Повторное добавление
    }
})

postCallback

Позволяет добавить Runnable (или Callback) для выполнения задачи в заданный момент времени, например, после обновления экрана.

Choreographer.getInstance().postCallback(
    Choreographer.CALLBACK_ANIMATION,
    Runnable {
        // Ваш код для выполнения после обновления экрана
    },
    null
)
RenderThread

Новый системно-управляемый поток обработки обеспечивает плавность анимации даже при наличии задержек в основном потоке пользовательского интерфейса. Работает асинхронно. Выполняет рендеринг onDraw в то время как UI Thread выполняет onMeasure и onLayout. Приводит к плавному FPS.

• появился в Android 5.0.

Animations

ValueAnimator

Представляет механизм для запуска анимаций вычисления анимированных значений и установки их для целевых объектов.

ObjectAnimator

Наследуется от ValueAnimator. Обеспечивает поддержку анимации свойств целевых объектов. Анимации можно создавать из кода и XML.

ViewPropertyAnimator

Вызывается через View.animate. Подходит для выполнения нескольких анимаций одновременно.

С какой частотой должен отрисовываться UI?

Чтобы сделать приложение плавным - нужно отрисовывать кадры менее чем за 16 мс для 60 кадров в секунду (FPS). 11 мс для 90 FPS. 8 мс для 120 FPS. Если приложение медленно отрисовывает UI - система будет пропускать кадры и юзер ощутит заикание интерфейса (jank).

• на любом телефона идет постоянная перерисовка экрана (герцовка).

• если кадр не успевает отрисоваться - он просто пропускается и готовится следующий. Это выглядит как лаг. В консоли пишется DROP_FRAME_BUFFER.

• иногда GPU рисует быстрее, чем может экран. Для этого в телефоне есть V-SYNC, чтобы кадры готовились ровно в тот промежуток, который нужен. Отвечает за это класс Choreographer (дирижер).

• если кадр не изменился - он берется из специального буффера (Frame Buffer).

HEX-Colors Opacity
HEXOpacity
100%FF
99%FC
98%FA
97%F7
96%F5
95%F2
94%F0
93%ED
92%EB
91%E8
90%E6
89%E3
88%E0
87%DE
86%DB
85%D9
84%D6
83%D4
82%D1
81%CF
80%CC
79%C9
78%C7
77%C4
76%C2
75%BF
74%BD
73%BA
72%B8
71%B5
70%B3
69%B0
68%AD
67%AB
66%A8
65%A6
64%A3
63%A1
62%9E
61%9C
60%99
59%96
58%94
57%91
56%8F
55%8C
54%8A
53%87
52%85
51%82
50%80
49%7D
48%7A
47%78
46%75
45%73
44%70
43%6E
42%6B
41%69
40%66
39%63
38%61
37%5E
36%5C
35%59
34%57
33%54
32%52
31%4F
30%4D
29%4A
28%47
27%45
26%42
25%40
24%3D
23%3B
22%38
21%36
20%33
19%30
18%2E
17%2B
16%29
15%26
14%24
13%21
12%1F
11%1C
10%1A
9%17
8%14
7%12
6%0F
5%0D
4%0A
3%08
2%05
1%03
0%00
Android UI. Вопросы на собесе
  1. C какой частотой должен отрисовываться UI?
  1. Что такое RenderThread?
  1. Как оптимизировать UI?

    Не рисовать фон в xml. устанавливать его в windowBackground.

    Задавать размеры View если они известны чтобы не тратить ресурсы на измерение.