[Modern Android] Jetpack Compose その2


Composeのサンプルコードを見ながら、分析しようと思います。
JetNewというComposeのサンプルを見つけました。

はじめる

Readmeを読む

Jetnews is a sample news reading app, built with Jetpack Compose. The goal of the sample is to showcase the current UI capabilities of Compose.
To try out this sample app, you need to use the Canary version of Android Studio 4.0, and import the project from the Android Samples following the steps here.
Compose is not available in earlier versions of Android Studio and downloading this github repo directly and opening it will most likely result in build errors.

  • Use Rows and Columns to arrange the contents of the UI
  • Add an AppBar
  • Use MaterialTypography and opacity to style the text
  • Use Shape to round the corners of the images
  • Use elevation to make the Cards stand out from the background

これを読んで見るとFlutterを似ていると感じますね。

コードを見る

1

setContentにUIのComposeを使う。


package com.example.jetnews.ui

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.ui.core.setContent
import com.example.jetnews.JetnewsApplication

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val appContainer = (application as JetnewsApplication).container
        setContent {
            JetnewsApp(appContainer = appContainer)
        }
    }
}

2

  • JetnewsThemeとAppContentというCompose関数がある。
  • DataとModelは今回無視します。

@Composable
fun JetnewsApp(appContainer: AppContainer) {
    JetnewsTheme {
        AppContent(
            interestsRepository = appContainer.interestsRepository,
            postsRepository = appContainer.postsRepository
        )
    }
}

3

JetnewsThemeはTheme.ktで宣言されている。
MaterialThemeはなんだろう。

Theme.kt
@Composable
fun JetnewsTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable() () -> Unit
) {
    MaterialTheme(
        colors = if (darkTheme) DarkThemeColors else LightThemeColors,
        typography = themeTypography,
        shapes = shapes,
        content = content
    )
}

4

  • なるほど、Material design specificationの Compose関数である。
  • Color, typography , shapes, contentをパラメータで使ってる。
/**
 * A MaterialTheme defines the styling principles from the Material design specification.
 *
 * Material components such as [Button] and [Checkbox] use values provided here when retrieving
 * default values.
 *
 * It defines colors as specified in the [Material Color theme creation spec](https://material.io/design/color/the-color-system.html#color-theme-creation),
 * typography defined in the [Material Type Scale spec](https://material.io/design/typography/the-type-system.html#type-scale),
 * and shapes defined in the [Shape scheme](https://material.io/design/shape/applying-shape-to-ui.html#shape-scheme).
 *
 * All values may be set by providing this component with the [colors][ColorPalette],
 * [typography][Typography], and [shapes][Shapes] attributes. Use this to configure the overall
 * theme of elements within this MaterialTheme.
 *
 * Any values that are not set will inherit the current value from the theme, falling back to the
 * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top
 * of your application, and then separate MaterialTheme(s) for different screens / parts of your
 * UI, overriding only the parts of the theme definition that need to change.
 *
 * @sample androidx.ui.material.samples.MaterialThemeSample
 *
 * @param colors A complete definition of the Material Color theme for this hierarchy
 * @param typography A set of text styles to be used as this hierarchy's typography system
 * @param shapes A set of shapes to be used by the components in this hierarchy
 */
@Composable
fun MaterialTheme(
    colors: ColorPalette = MaterialTheme.colors,
    typography: Typography = MaterialTheme.typography,
    shapes: Shapes = MaterialTheme.shapes,
    content: @Composable () -> Unit
) {
    ProvideColorPalette(colors) {
        val indicationFactory: @Composable () -> Indication = remember { { RippleIndication() } }
        Providers(
            IndicationAmbient provides indicationFactory,
            TypographyAmbient provides typography,
            ShapesAmbient provides shapes
        ) {
            ProvideTextStyle(value = typography.body1, children = content)
        }
    }
}
  • これはFlutterのMaterialAppのthemeと一緒だと思う。

5

元に戻して、AppContentのCompose関数をみてみよう

  • Crossfade関数はFadeAnimationを使うための関数みたい
  • FlutterのFadeTransition Widgetと似ていると思う。

@Composable
private fun AppContent(
    postsRepository: PostsRepository,
    interestsRepository: InterestsRepository
) {
    Crossfade(JetnewsStatus.currentScreen) { screen ->
        Surface(color = MaterialTheme.colors.background) {
            when (screen) {
                is Screen.Home -> HomeScreen(postsRepository = postsRepository)
                is Screen.Interests -> InterestsScreen(interestsRepository = interestsRepository)
                is Screen.Article -> ArticleScreen(
                    postId = screen.postId,
                    postsRepository = postsRepository
                )
            }
        }
    }
}

終わりに

今回はここまでです。
つづく。。。