Utilisation simple et implémentation de cas d'Android Studio compose

Compose est un framework d'interface utilisateur de nouvelle génération vigoureusement promu par l'équipe Android et JetBrain. Il peut simplifier le développement de l'interface Android et transformer la méthode d'écriture de fichier xml encombrante d'origine en une simple méthode d'écriture de fichier kt.

Son interface utilisateur déclarative, sa personnalisation plus simple, sa fonction de prévisualisation en temps réel et interactive rendent le développement Android encore meilleur

1. Pré-connaissance : Jetpack

1. Qu'est-ce qu'un Jetpack ?

Jetpack n'est pas un framework ou un composant, c'est un ensemble de bibliothèques, d'outils et de directives qui aident les développeurs à écrire plus facilement des applications de haute qualité. Ces composants aident les développeurs à suivre les meilleures pratiques, à se débarrasser de l'écriture de code passe-partout et à simplifier les tâches complexes afin qu'ils puissent se concentrer sur le code dont ils ont besoin.

2. Pourquoi utiliser Jetpack

1. Remplacez la bibliothèque de support précédente et fournissez une meilleure solution de compatibilité, plus indépendante et plus robuste
2. Implémentez officiellement de nombreux composants nécessaires au développement logiciel quotidien, en éliminant le code passe-partout répétitif
3. Améliorez la qualité du logiciel, la bibliothèque principale vous aide à lier les données, à gérer le cycle de vie et le contenu, vous permettant de vous concentrer sur des parties importantes de votre entreprise

3. Bibliothèque Jetpack couramment utilisée

L'image est tirée du document de développement Android

2. Film positif : débuter avec Compose

1. L'idée de programmation de Compose

Compose est un framework d'interface déclarative . Au cours des dernières années, l'industrie dans son ensemble a commencé à passer à un modèle d'interface déclaratif qui simplifie considérablement les tâches d'ingénierie associées à la création et à la mise à jour des interfaces. La technique fonctionne en régénérant conceptuellement l'intégralité de l'écran à partir de zéro, puis en n'effectuant que les modifications nécessaires. Cette approche évite la complexité de la mise à jour manuelle des hiérarchies de vues avec état.

fonctions composables simples

À l'aide de Compose, les interfaces peuvent être construites en définissant un ensemble de fonctions composables qui acceptent des données et émettent des éléments d'interface. Un exemple simple est le widget de salutation, qui prend une chaîne et émet un widget de texte qui affiche un message de salutation.
cas simpleCette fonction est annotée avec @Composable. Toutes les fonctions composables doivent avoir cette annotation ; cette annotation indique au compilateur Compose que cette fonction est destinée à convertir des données en une interface. ( Similaire à @Component du framework Spring )

Cette fonction accepte des données. Les fonctions composables peuvent accepter des paramètres qui permettent à la logique d'application de décrire l'interface. Dans ce cas, notre widget accepte une chaîne afin qu'il puisse saluer l'utilisateur par son nom.

Cette fonction peut afficher du texte dans l'interface. Pour ce faire, il appelle la fonction composable Text(), qui crée en fait l'élément d'interface texte. Les fonctions composables émettent des hiérarchies d'interface en appelant d'autres fonctions composables.

Cette fonction ne retourne rien. Les fonctions de composition qui émettent des écrans n'ont pas besoin de renvoyer quoi que ce soit, car elles décrivent l'état d'écran souhaité, plutôt que de construire les widgets d'écran.

2. Créer un projet Compose

1. Si vous êtes dans la fenêtre Bienvenue dans Android Studio, cliquez sur Démarrer un nouveau projet Android Studio. Si vous avez déjà un projet Android Studio ouvert, choisissez Fichier > Nouveau > Nouveau projet dans la barre de menus.

insérez la description de l'image ici
2. Dans la fenêtre Sélectionner un modèle de projet, sélectionnez Activité de composition vide et cliquez sur Suivant.
insérez la description de l'image ici3. Dans la fenêtre Configurer votre projet, procédez comme suit :

按照常规方法设置 Name、Package name 和 Save location。请注意,在 Language 下拉菜单中,Kotlin 是唯一可用的选项,因为 Jetpack Compose 仅适用于使用 Kotlin 编写的类。
在 Minimum API level dropdown 菜单中,*选择 API 级别 21 或更高级别*。

insérez la description de l'image ici4. Cliquez sur Terminer.

3. Utilisez Compose pour compléter le cas "marquee"

1. Construire le projet

Cette partie fait référence à ce qui précède ;

2. Créez un nouveau fichier kt sous le package principal

Je l'ai nommé "test" ici
insérez la description de l'image ici

3. Construisez la méthode MarqueeText

C'est la partie principale de l'implémentation du chapiteau, dans cette partie pour éditer les paramètres statiques et les effets dynamiques de l'effet chapiteau

Reportez-vous au paramètre ui défini dans Compose

insérez la description de l'image iciillustrer:

Chapiteau de défilement en boucle Contrôle du texte

  • texte contenu du texte
  • modificateur contrôle modificateur
  • textModifier modificateur de texte
  • gradientEdgeColor La couleur transparente du dégradé des bordures gauche et droite, la valeur par défaut est le dégradé blanc.
  • couleur du texte
  • espacement des caractères letterSpacing
  • décoration de texte décoration de texte

créer une méthode de contrôle

Méthode de contrôle Create Text, équivalente à @Composable fun createText(localModifier: Modifier)

insérez la description de l'image ici

Encodage des effets dynamiques

var offset by remember {
    
     mutableStateOf(0) }
        val textLayoutInfoState = remember {
    
     mutableStateOf<TextLayoutInfo?>(null) }
        LaunchedEffect(textLayoutInfoState.value) {
    
    
            val textLayoutInfo = textLayoutInfoState.value ?: return@LaunchedEffect
            if (textLayoutInfo.textWidth <= textLayoutInfo.containerWidth) return@LaunchedEffect
            if(textLayoutInfo.containerWidth == 0) return@LaunchedEffect
            // 计算播放一遍的总时间
            val duration = 7500 * textLayoutInfo.textWidth / textLayoutInfo.containerWidth
            // 父层不要有其他元素,不然这句很容易发生Error java.lang.ArithmeticException: divide by zero(除以零)
            // 动画间隔时间
            val delay = 1000L

            do {
    
    
                // 定义动画,文字偏移量从0到-文本宽度
                val animation = TargetBasedAnimation(
                    animationSpec = infiniteRepeatable(
                        animation = tween(
                            durationMillis = duration,
                            delayMillis = 1000,
                            easing = LinearEasing,
                        ),
                        repeatMode = RepeatMode.Restart
                    ),
                    typeConverter = Int.VectorConverter,
                    initialValue = 0,
                    targetValue = -textLayoutInfo.textWidth
                )
                // 根据动画帧时间,获取偏移量值。
                // 起始帧时间
                val startTime = withFrameNanos {
    
     it }
                do {
    
    
                    val playTime = withFrameNanos {
    
     it } - startTime
                    offset = animation.getValueFromNanos(playTime)
                } while (!animation.isFinishedFromNanos(playTime))
                // 延迟重新播放
                delay(delay)
            } while (true)
        }

        SubcomposeLayout(
            modifier = modifier.clipToBounds()
        ) {
    
     constraints ->
            // 测量文本总宽度
            val infiniteWidthConstraints = constraints.copy(maxWidth = Int.MAX_VALUE)
            var mainText = subcompose(MarqueeLayers.MainText) {
    
    
                createText(textModifier)
            }.first().measure(infiniteWidthConstraints)

            var gradient: Placeable? = null

            var secondPlaceableWithOffset: Pair<Placeable, Int>? = null
            if (mainText.width <= constraints.maxWidth) {
    
    // 文本宽度小于容器最大宽度, 则无需跑马灯动画
                mainText = subcompose(MarqueeLayers.SecondaryText) {
    
    
                    createText(textModifier.fillMaxWidth())
                }.first().measure(constraints)
                textLayoutInfoState.value = null
            } else {
    
    
                // 循环文本增加间隔
                val spacing = constraints.maxWidth * 2 / 3
                textLayoutInfoState.value = TextLayoutInfo(
                    textWidth = mainText.width + spacing,
                    containerWidth = constraints.maxWidth
                )
                // 第二遍文本偏移量
                val secondTextOffset = mainText.width + offset + spacing
                val secondTextSpace = constraints.maxWidth - secondTextOffset
                if (secondTextSpace > 0) {
    
    
                    secondPlaceableWithOffset = subcompose(MarqueeLayers.SecondaryText) {
    
    
                        createText(textModifier)
                    }.first().measure(infiniteWidthConstraints) to secondTextOffset
                }
                // 测量左右两边渐变控件
                gradient = subcompose(MarqueeLayers.EdgesGradient) {
    
    
                    Row {
    
    
                        GradientEdge(gradientEdgeColor, Color.Transparent)
                        Spacer(Modifier.weight(1f))
                        GradientEdge(Color.Transparent, gradientEdgeColor)
                    }
                }.first().measure(constraints.copy(maxHeight = mainText.height))
            }

            // 将文本、渐变控件 进行位置布局
            layout(
                width = constraints.maxWidth,
                height = mainText.height
            ) {
    
    
                mainText.place(offset, 0)
                secondPlaceableWithOffset?.let {
    
    
                    it.first.place(it.second, 0)
                }
                gradient?.place(0, 0)
            }
        }
    }
     /**
     * 渐变侧边
     */
    @Composable
    private fun GradientEdge(
        startColor: Color, endColor: Color,
    ) {
    
    
        Box(
            modifier = Modifier
                .width(10.dp)
                .fillMaxHeight()
                .background(
                    brush = Brush.horizontalGradient(
                        0f to startColor, 1f to endColor,
                    )
                )
        )
    }

    private enum class MarqueeLayers {
    
     MainText, SecondaryText, EdgesGradient }

    /**
     * 文字布局信息
     * @param textWidth 文本宽度
     * @param containerWidth 容器宽度
     */
    private data class TextLayoutInfo(val textWidth: Int, val containerWidth: Int)

appeler la méthode ci-dessus

@Composable
fun TestScreen() {
    
    
    val content = "这是一段很长很长很长很长很长很长很长很长很长很长的跑马灯文字;"
    Column(modifier = Modifier.padding(top = 200.dp)) {
    
    
        MarqueeText(
            text = content,
            color = Color.Black,
            fontSize = 24.sp,
            modifier = Modifier
                .padding(start = 50.dp, end = 50.dp)
                .background(Color.White)
        )
    }
}

Implémenter la classe startup

class test : ComponentActivity() {
    
    
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContent {
    
    
            MyApplicationTheme {
    
    
                // A surface container using the 'background' color from the theme
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
    
    
                     TestScreen()
                }
            }
        }
    }
}

Dans le fichier de démarrage xml, ajoutez ce fichier kt

<activity
            android:name=".test"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.MyApplication">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

obtenir un effet

insérez la description de l'image ici

4. Résumé

Le framework Compose est un framework de développement Android efficace. Il peut éviter le débogage fastidieux, sujet aux erreurs et difficile de l'écriture de mise en page XML, et il fournit une API riche que les développeurs peuvent utiliser, permettant aux développeurs de passer beaucoup de temps sur la programmation orientée processus et la programmation orientée résultats, réduisant ainsi la programmation orientée tranche.

Zeng Jiancheng https://blog.csdn.net/weixin_57235263/article/details/128127787?spm=1001.2014.3001.5501

Je suppose que tu aimes

Origine blog.csdn.net/fjnu_se/article/details/128208046
conseillé
Classement