UI Components
ViewStub
Загружает и отображает представление только при необходимости. Используется для оптимизации производительности, чтобы избежать ненужной загрузки ресурсов до того, как они понадобятся.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub
android:id="@+id/view_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/your_layout_to_inflate" />
</LinearLayout>
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Получаем ViewStub
val viewStub: ViewStub = findViewById(R.id.view_stub)
// Загружаем макет
viewStub.inflate()
}
}
inflate
Загружает макет из ресурса и возвращает его как иерархию View, которую можно добавить в контейнер.
FrameLayout
Контейнер, который размещает элементы один на другом. Используется для простого наложения или отображения одного элемента в конкретном месте.
LinearLayout
Контейнер для расположения элементов в одном ряду или колонке. Все элементы выстраиваются последовательно, либо по горизонтали, либо по вертикали.
ConstraintLayout
Контейнер для гибкого расположения элементов интерфейса с помощью ограничений. Упрощает создание сложных макетов без вложенных контейнеров и улучшает производительность.
MotionLayout
Позволяет создавать сложные анимации и переходы между различными состояниями UI. Он является расширением ConstraintLayout
и упрощает работу с анимациями, особенно для интерфейсов с динамическими переходами.
<MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/motion_scene">
<ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me"
android:layout_centerInParent="true" />
</ConstraintLayout>
</MotionLayout>
MotionScene
Описывает анимации и переходы между различными состояниями интерфейса.
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetStart="@id/startState"
app:constraintSetEnd="@id/endState"
app:motionDuration="1000">
<OnSwipe
app:touchAnchorId="@id/button"
app:dragDirection="dragHorizontal"
app:touchAnchorSide="center" />
</Transition>
<ConstraintSet
android:id="@+id/startState">
<Constraint
android:id="@id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</ConstraintSet>
<ConstraintSet android:id="@+id/endState">
<Constraint
android:id="@id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true" />
</ConstraintSet>
</MotionScene>
Transition
Описание анимации, которая определяет, как элементы будут изменяться между различными состояниями. Transition
связывает два состояния (start и end) и управляет анимацией, которая происходит при переходе между ними.
<MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/motion_scene">
<ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me"
android:layout_centerInParent="true" />
</ConstraintLayout>
<Transition
app:motionDuration="500"
app:motionStagger="0.1"
app:motionInterpolator="easeInOut"
app:constraintSetStart="@id/startState"
app:constraintSetEnd="@id/endState" />
</MotionLayout>
OnSwipe
Cобытие, которое отслеживает свайпы пользователя (горизонтальные или вертикальные движения) и на основе этого изменяет состояние анимации или переходов в MotionLayout
.
<MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/motion_scene">
<ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Swipe Me"
android:layout_centerInParent="true" />
</ConstraintLayout>
<OnSwipe
app:touchAnchorId="@id/button"
app:touchAnchorSide="center"
app:dragDirection="dragHorizontal"
app:motionProgress="0.5" />
</MotionLayout>
RemoteViews
Класс для обновления UI в компонентах, таких как виджеты и уведомления.
val remoteViews = RemoteViews(packageName, R.layout.widget_layout)
remoteViews.setTextViewText(R.id.widget_text_view, "Hello, RemoteViews!")
val appWidgetManager = AppWidgetManager.getInstance(context)
appWidgetManager.updateAppWidget(ComponentName(context, MyWidgetProvider::class.java), remoteViews)
TextView
Отображает текст.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Пример текста"
android:textSize="18sp"
android:textColor="#000000"
android:textStyle="bold" />
PrecomputedText
Используется для предварительного вычисления текста.
fun TextView.setTextAsync(longString: String) {
val params = this.textMetricsParams
val ref = WeakReference(this)
CoroutineScope.launch(Dispatchers.Default) {
val precomputedText = PrecomputedText.create(longString, params)
withContext(Dispatchers.Main) {
ref.get()?.let { textView ->
textView.text = precomputedText
}
}
}
}
Spannable
Позволяет изменять и стилизовать текст на уровне символов или подстрок в тексте.
val spannable = SpannableString("Текст с разными стилями")
spannable.setSpan(StyleSpan(Typeface.BOLD), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
spannable.setSpan(ForegroundColorSpan(Color.RED), 5, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = spannable
Compound Drawable
Способ добавления изображений (drawable) внутри TextView
.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Пример текста"
android:drawableLeft="@drawable/ic_example"
android:drawablePadding="8dp" />
ScrollView
Позволяет отображать контент, выходящий за пределы экрана, с возможностью прокрутки.
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:text="Элемент 1" />
<TextView android:text="Элемент 2" />
</LinearLayout>
</ScrollView>
fillViewport
Атрибут, который позволяет растянуть его дочерний элемент до полного размера экрана, если контента недостаточно для прокрутки.
android:fillViewport="true"
Constraintlayout
Гибкий и мощный контейнер для размещения UI-элементов в Android. Позволяет создавать сложные интерфейсы с минимальным количеством вложенных элементов, упрощая управление расположением.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Flow
Позволяет автоматически располагать дочерние элементы в нескольких строках или столбцах, создавая адаптивные и гибкие макеты. Он особенно полезен, когда нужно выстроить элементы в сетку или в ряд с динамическим распределением.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Flow
android:id="@+id/flow"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:flow_wrapMode="chain"
app:flow_horizontalAlign="start"
app:flow_verticalAlign="top">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 3" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 4" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 5" />
</androidx.constraintlayout.widget.Flow>
</androidx.constraintlayout.widget.ConstraintLayout>
Guideline
Вспомогательная линия в ConstraintLayout
, которая помогает выравнивать элементы по заданным процентам или фиксированным позициям относительно родительского контейнера.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:orientation="vertical"
app:layout_constraintGuide_percent="0.5" /> <!-- 50% ширины экрана -->
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"
app:layout_constraintStart_toStartOf="@id/guideline"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
chain
Группа элементов, связанных между собой, которые могут быть выровнены по одной оси (горизонтальной или вертикальной) с возможностью динамического изменения расстояний между ними.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item 1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item 2"
app:layout_constraintStart_toEndOf="@id/textView1"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item 3"
app:layout_constraintStart_toEndOf="@id/textView2"
app:layout_constraintTop_toTopOf="parent" />
<!-- Chain definition -->
<androidx.constraintlayout.widget.ConstraintLayout
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView3"
app:layout_constraintHorizontal_chainStyle="spread" />
</androidx.constraintlayout.widget.ConstraintLayout>
barrier
Действует как динамическая граница, определяя ограничение для других элементов. Он автоматически подстраивается под размер или позицию дочерних элементов и может быть использован для выравнивания элементов с учетом их размеров.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item 1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item 2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/textView1" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
app:constraint_referenced_ids="textView1,textView2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintTop_toBottomOf="@id/barrier"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
baseline
Используется для выравнивания элементов по базовой линии текста.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="World"
app:layout_constraintBaseline_toBaselineOf="@id/textView1"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
CoordinatorLayout
Контейнер для сложных интерфейсов с прокруткой, который координирует поведение дочерних элементов, таких как DrawerLayout
или FloatingActionButton
.
<androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
app:layout_anchor="@id/textView"
app:layout_anchorGravity="bottom|end" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
ViewPager2
Компонент для прокручиваемых страниц в Android. Он улучшает оригинальный ViewPager
, поддерживая работу с фрагментами, вертикальную прокрутку и лучшее использование RecyclerView
для производительности.
Передать currentItem как аргумент фрагменту
class PagerViewModel @Inject constructor(
savedStateHandle: SavedStateHandle
): ViewModel() {
val tabLiveData: LiveData<Int> = savedStateHandle.getLiveData<Int>("tab")
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.tabLiveData.observe(viewLifecycleOwner) { tab ->
view.post { binding.viewPager.setCurrentItem(tab, false) }
}
}
companion object {
fun create(tab: Int) = PagerFragment().apply {
arguments = bundleOf("tab" to tab)
}
}
WebView
Позволяет отображать веб-страницы внутри вашего приложения.
• Использование WebView
может представлять потенциальные угрозы безопасности, так как оно позволяет выполнять JavaScript и обрабатывать веб-контент.
• Важно правильно управлять жизненным циклом WebView
, например, освобождать ресурсы и сохранять состояние, если это необходимо.
<WebView
android:id="@+id/my_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val webView: WebView = findViewById(R.id.my_webview)
webView.settings.javaScriptEnabled = true // Включение JavaScript
webView.webViewClient = WebViewClient() // Обработка ссылок внутри WebView
webView.loadUrl("https://www.example.com") // Загрузка веб-страницы
}
override fun onPause() {
super.onPause()
webView.onPause()
}
override fun onResume() {
super.onResume()
webView.onResume()
}
override fun onDestroy() {
super.onDestroy()
webView.destroy()
}
}
javaScriptEnabled
Включает или отключает поддержку JavaScript.
webView.settings.javaScriptEnabled = true
setDomStorageEnabled
Включает или отключает поддержку DOM-хранилища.
webView.settings.domStorageEnabled = true
setSupportZoom
Включает или отключает поддержку масштабирования.
webView.settings.setSupportZoom(true)
goBack
Управлять возвратом на предыдущие страницы в WebView
.
if (webView.canGoBack()) {
webView.goBack()
} else {
super.onBackPressed()
}
WebViewClient
По умолчанию, ссылки, которые пользователь нажимает в WebView
, открываются в браузере. Чтобы ссылки открывались внутри WebView
, нужно установить WebViewClient
.
webView.webViewClient = object: WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
view.loadUrl(url)
return true
}
}
RelativeLayout
RelativeLayout устарел. Мигрируй на ConstraintLayout.
Позволяет располагать дочерние элементы относительно друг друга или родительского контейнера.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"
android:layout_centerInParent="true" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me"
android:layout_below="@id/textView"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Вопросы на собесе (13)
- Для чего нужен CoordinatorLayout?
Предназначен для управления поведением дочерних View, таких как
FloatingActionButton
иAppBarLayout
. Он позволяет координировать взаимодействие между этими View, например, автоматическое скрытие или изменение их размера при прокрутке списка.
- Перечисли наследников ViewGroup?
LinearLayout
RelativeLayout
FrameLayout
ConstraintLayout
TableLayout
GridLayout
CoordinatorLayout
DrawerLayout
ViewPager
RecyclerView
- Ранжируй Layouts по производительности?
FrameLayout
→LinearLayout
→ConstraintLayout
→RelativeLayout
- Как FrameLayout располагает дочерние элементы?
FrameLayout
располагает дочерние элементы в левом верхнем углу по умолчанию, накладывая их друг на друга. Каждый новый элемент размещается поверх предыдущих, если не заданы другие параметры размещения.
- Для чего нужен MotionLayout?
Для создания сложных анимаций и переходов между состояниями интерфейса, объединяя возможности
ConstraintLayout
и анимации.
- Что такое WebView?
Компонент, позволяющий приложениям отображать веб-контент внутри UI. Предоставляет возможность загружать и отображать веб-страницы, выполнять JavaScript и обрабатывать навигацию.
WebView
полезен для интеграции веб-контента в приложения, например, для отображения инструкций или материалов, не выходя из приложения.
- Что будет быстрее: 2 LinearLayout вложенные один в другой или ConstraintLayout?
ConstraintLayout
будет быстрее, чем два вложенныхLinearLayout
, так как он оптимизирует размещение элементов и снижает количество проходов по дереву представлений.ConstraintLayout
лучше масштабируется для сложных интерфейсов, поскольку позволяет избежать глубокой вложенности и перегрузки измерений.
- С помощью какого компонента лучше выполнять отложенный (по запросу) inflate дочерней View?
•
LazyView
•
AsnycLayoutinflater
•
ViewStub
- Сколько дочерних элементов может содержать ScrollView?
• 2
• 1
• 3
• Сколько угодно
- Какой метод используется для настройки слушателя нажатий в View?
•
setOnTouchListener
•
setOnClickListener
•
setClickListener
•
setOnClick
- Какой из следующих атрибутов XML используется для установки стиля текста в TextView?
•
textStyle
•
textAppearance
•
textFont
•
textSize
- Сколько проходов по детям с вызовом метода onMeasure() выполняется в LinearLayout (без использования и дополнительных вызовов метода рефреша жизненного цикла View)
• 1
• 1 или 2
• 2 или 3
• До 5 раз
- Что отрисуется на экране при inflate этого XML?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout>
• left-top
• right-top
• left-bottom
• right-bottom