Jetpack Compose: AndroidView modifier

Introduction

In modern Android app development, Jetpack Compose has gained significant traction as a declarative UI toolkit, enabling developers to create user interfaces more efficiently. One of the standout features of Jetpack Compose is the ability to integrate legacy views, such as those built with View classes from the Android framework, into Compose's declarative system. This is made possible by the AndroidView composable function, which bridges the gap between traditional View components and Jetpack Compose layouts.

In this article, we will explore a practical example that demonstrates the use of the AndroidView modifier in Jetpack Compose. This example integrates a traditional TextView inside a Jetpack Compose UI, wraps it with modern Compose modifiers such as border, background, and clip, and displays it within a Box layout. By the end, you'll understand how to combine classic Android Views with Compose elements seamlessly.

The MainActivity and Scaffold Setup

The application begins with a basic MainActivity class, inheriting from AppCompatActivity, which is the standard setup for most Android apps. The onCreate method calls the setContent function, which sets the entire layout of the activity to be managed by Compose. The layout is composed by the GetScaffold function.

In the GetScaffold function, a Scaffold is used to structure the app. A Scaffold is a common layout component in Jetpack Compose that provides slots for the top bar, bottom bar, floating action buttons, and the main content. In this example, the top bar is defined by the TopAppBar composable, which displays a title with a customized background color. The content section is filled by the MainContent function.

Composing the Main Content with AndroidView

The core of this example lies in the MainContent function. It places an AndroidView inside a Box layout. Box is a composable that stacks its children on top of each other, and in this case, it's set to fill the entire screen using the Modifier.fillMaxSize() modifier. The content is aligned to the center using the contentAlignment parameter set to Alignment.Center.

The AndroidView composable is the key here. It allows the integration of traditional Android Views into a Compose UI. In this example, the AndroidView creates a TextView within its factory parameter. This TextView is then customized with text, text size, and gravity properties, giving it a typical Android look and behavior. The TextView displays the text "TextView AndroidView" with a text size of 24sp and centers the text within the view using Gravity.CENTER.

Applying Modern Compose Modifiers

While the TextView is a traditional view, it is enhanced using Jetpack Compose's powerful Modifier system. These modifiers allow Compose to control how the TextView looks and behaves within the layout.

First, the Modifier.size(250.dp) constrains the view to a specific size, ensuring it remains within a circular area. Then, clip(CircleShape) is used to apply a circular clipping mask to the TextView, transforming it into a circle. After that, a red border with a thickness of 10dp is added using the border modifier, followed by a background color of orange (Color(0xFFED872D)), which fills the circle behind the TextView. The padding(24.dp) modifier adds internal space around the TextView, and wrapContentSize(Alignment.Center) ensures the content inside the TextView stays centered.

Summary

In summary, this example showcases how Jetpack Compose's AndroidView composable can be used to integrate classic Android Views, such as TextView, into a Compose UI, while still applying modern Compose modifiers. The combination of the AndroidView with Compose's modifier system results in a clean and highly customizable UI component that blends the best of both worlds.

This approach is particularly useful when transitioning from traditional Android views to Jetpack Compose or when reusing complex View-based components within new Compose-based applications. With this seamless integration, developers can modernize their UIs without completely rewriting existing components, allowing for a smoother migration to Jetpack Compose.


MainActivity.kt

package com.cfsuman.jetpackcompose

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Gravity
import android.widget.TextView
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            GetScaffold()
        }
    }


    @Composable
    fun GetScaffold(){
        Scaffold(
            topBar = {
                TopAppBar(
                    title = { Text(
                        text = "Compose - AndroidView Modifier"
                    )},
                    backgroundColor = Color(0xFFC0E8D5),
                )
            },
            content = {MainContent()},
            backgroundColor = Color(0xFFEDEAE0),
        )
    }


    @Composable
    fun MainContent(){
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ){
            AndroidView(factory = { context ->
                TextView(context).apply {
                    text = "TextView AndroidView"
                    textSize = 24F
                    gravity = Gravity.CENTER
                }
            },
                modifier = Modifier
                    .size(250.dp)
                    .clip(CircleShape)
                    .border(
                        width = 10.dp,
                        color = Color(0xFFE30022),
                        shape = CircleShape
                    )
                    .background(Color(0xFFED872D))
                    .padding(24.dp)
                    .wrapContentSize(Alignment.Center)
            )
        }
    }
}
More android jetpack compose tutorials