得到
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.jensklingenberg.jetpackcomposeplayground">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.AppCompat.Light">
|
||||
<activity android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="androidx.activity.ComponentActivity" />
|
||||
|
||||
<activity android:name=".mysamples.demo.DemoActivity"/>
|
||||
<activity android:name=".UiTestingDemoActivity" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoActivity
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
startActivity(Intent(this, DemoActivity::class.java))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground
|
||||
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.testing.TestingExample
|
||||
|
||||
|
||||
class UiTestingDemoActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContent {
|
||||
TestingExample()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples
|
||||
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
|
||||
data class User(val name: String, val age: Int)
|
||||
|
||||
val LocalActiveUser = compositionLocalOf<User> { error("No user found!") }
|
||||
|
||||
class MyTestActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContent {
|
||||
MyUserScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
@Composable
|
||||
private fun MyUserScreen() {
|
||||
val user = User("Jens", 31)
|
||||
CompositionLocalProvider(LocalActiveUser provides user) {
|
||||
UserInfo()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun UserInfo() {
|
||||
Column {
|
||||
Text("Name: " + LocalActiveUser.current.name)
|
||||
Text("Age: " + LocalActiveUser.current.age)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.demo
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.runtime.Composable
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Generic demo with a [title] that will be displayed in the list of demos.
|
||||
*/
|
||||
sealed class Demo(val title: String) {
|
||||
override fun toString() = title
|
||||
}
|
||||
|
||||
/**
|
||||
* Demo that launches an [Activity] when selected.
|
||||
*
|
||||
* This should only be used for demos that need to customize the activity, the large majority of
|
||||
* demos should just use [ComposableDemo] instead.
|
||||
*
|
||||
* @property activityClass the KClass (Foo::class) of the activity that will be launched when
|
||||
* this demo is selected.
|
||||
*/
|
||||
class ActivityDemo<T : ComponentActivity>(title: String, val activityClass: KClass<T>) : Demo(title)
|
||||
|
||||
/**
|
||||
* Demo that displays [Composable] [content] when selected.
|
||||
*/
|
||||
class ComposableDemo(title: String, val content: @Composable () -> Unit) : Demo(title)
|
||||
|
||||
/**
|
||||
* A category of [Demo]s, that will display a list of [demos] when selected.
|
||||
*/
|
||||
class DemoCategory(title: String, val demos: List<Demo>) : Demo(title)
|
||||
|
||||
/**
|
||||
* Flattened recursive DFS [List] of every demo in [this].
|
||||
*/
|
||||
fun DemoCategory.allDemos(): List<Demo> {
|
||||
val allDemos = mutableListOf<Demo>()
|
||||
fun DemoCategory.addAllDemos() {
|
||||
demos.forEach { demo ->
|
||||
allDemos += demo
|
||||
if (demo is DemoCategory) {
|
||||
demo.addAllDemos()
|
||||
}
|
||||
}
|
||||
}
|
||||
addAllDemos()
|
||||
return allDemos
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattened recursive DFS [List] of every launchable demo in [this].
|
||||
*/
|
||||
fun DemoCategory.allLaunchableDemos(): List<Demo> {
|
||||
return allDemos().filter { it !is DemoCategory }
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.demo
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.Window
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.OnBackPressedDispatcher
|
||||
import androidx.compose.material.Colors
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.darkColors
|
||||
import androidx.compose.material.lightColors
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.Saver
|
||||
import androidx.compose.runtime.saveable.listSaver
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
|
||||
/**
|
||||
* Main [Activity] containing all Compose related demos.
|
||||
*/
|
||||
class DemoActivity : ComponentActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
ComposeView(this).also {
|
||||
setContentView(it)
|
||||
}.setContent {
|
||||
val activityStarter = fun(demo: ActivityDemo<*>) {
|
||||
startActivity(Intent(this, demo.activityClass.java))
|
||||
}
|
||||
val navigator = rememberSaveable(
|
||||
saver = Navigator.Saver(AllDemosCategory, onBackPressedDispatcher, activityStarter)
|
||||
) {
|
||||
Navigator(AllDemosCategory, onBackPressedDispatcher, activityStarter)
|
||||
}
|
||||
val demoColors = remember {
|
||||
DemoColors().also {
|
||||
lifecycle.addObserver(
|
||||
LifecycleEventObserver { _, event ->
|
||||
if (event == Lifecycle.Event.ON_RESUME) {
|
||||
it.loadColorsFromSharedPreferences(this)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
DemoTheme(demoColors, window) {
|
||||
val filteringMode = rememberSaveable(
|
||||
saver = FilterMode.Saver(onBackPressedDispatcher)
|
||||
) {
|
||||
FilterMode(onBackPressedDispatcher)
|
||||
}
|
||||
val onStartFiltering = { filteringMode.isFiltering = true }
|
||||
val onEndFiltering = { filteringMode.isFiltering = false }
|
||||
DemoApp(
|
||||
currentDemo = navigator.currentDemo,
|
||||
backStackTitle = navigator.backStackTitle,
|
||||
isFiltering = filteringMode.isFiltering,
|
||||
onStartFiltering = onStartFiltering,
|
||||
onEndFiltering = onEndFiltering,
|
||||
onNavigateToDemo = { demo ->
|
||||
if (filteringMode.isFiltering) {
|
||||
onEndFiltering()
|
||||
navigator.popAll()
|
||||
}
|
||||
navigator.navigateTo(demo)
|
||||
},
|
||||
canNavigateUp = !navigator.isRoot,
|
||||
onNavigateUp = {
|
||||
onBackPressed()
|
||||
},
|
||||
launchSettings = {
|
||||
// startActivity(Intent(this, DemoSettingsActivity::class.java))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DemoTheme(
|
||||
demoColors: DemoColors,
|
||||
window: Window,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
MaterialTheme() {
|
||||
val statusBarColor = with(MaterialTheme.colors) {
|
||||
(if (isLight) primaryVariant else Color.Black).toArgb()
|
||||
}
|
||||
SideEffect {
|
||||
window.statusBarColor = statusBarColor
|
||||
}
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
private class Navigator private constructor(
|
||||
private val backDispatcher: OnBackPressedDispatcher,
|
||||
private val launchActivityDemo: (ActivityDemo<*>) -> Unit,
|
||||
private val rootDemo: Demo,
|
||||
initialDemo: Demo,
|
||||
private val backStack: MutableList<Demo>
|
||||
) {
|
||||
constructor(
|
||||
rootDemo: Demo,
|
||||
backDispatcher: OnBackPressedDispatcher,
|
||||
launchActivityDemo: (ActivityDemo<*>) -> Unit
|
||||
) : this(backDispatcher, launchActivityDemo, rootDemo, rootDemo, mutableListOf<Demo>())
|
||||
|
||||
private val onBackPressed = object : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() {
|
||||
popBackStack()
|
||||
}
|
||||
}.apply {
|
||||
isEnabled = !isRoot
|
||||
backDispatcher.addCallback(this)
|
||||
}
|
||||
|
||||
private var _currentDemo by mutableStateOf(initialDemo)
|
||||
var currentDemo: Demo
|
||||
get() = _currentDemo
|
||||
private set(value) {
|
||||
_currentDemo = value
|
||||
onBackPressed.isEnabled = !isRoot
|
||||
}
|
||||
|
||||
val isRoot: Boolean get() = backStack.isEmpty()
|
||||
|
||||
val backStackTitle: String
|
||||
get() =
|
||||
(backStack.drop(1) + currentDemo).joinToString(separator = " > ") { it.title }
|
||||
|
||||
fun navigateTo(demo: Demo) {
|
||||
if (demo is ActivityDemo<*>) {
|
||||
launchActivityDemo(demo)
|
||||
} else {
|
||||
backStack.add(currentDemo)
|
||||
currentDemo = demo
|
||||
}
|
||||
}
|
||||
|
||||
fun popAll() {
|
||||
if (!isRoot) {
|
||||
backStack.clear()
|
||||
currentDemo = rootDemo
|
||||
}
|
||||
}
|
||||
|
||||
private fun popBackStack() {
|
||||
currentDemo = backStack.removeAt(backStack.lastIndex)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun Saver(
|
||||
rootDemo: DemoCategory,
|
||||
backDispatcher: OnBackPressedDispatcher,
|
||||
launchActivityDemo: (ActivityDemo<*>) -> Unit
|
||||
): Saver<Navigator, *> = listSaver<Navigator, String>(
|
||||
save = { navigator ->
|
||||
(navigator.backStack + navigator.currentDemo).map { it.title }
|
||||
},
|
||||
restore = { restored ->
|
||||
require(restored.isNotEmpty())
|
||||
val backStack = restored.mapTo(mutableListOf()) {
|
||||
requireNotNull(findDemo(rootDemo, it))
|
||||
}
|
||||
val initial = backStack.removeAt(backStack.lastIndex)
|
||||
Navigator(backDispatcher, launchActivityDemo, rootDemo, initial, backStack)
|
||||
}
|
||||
)
|
||||
|
||||
private fun findDemo(demo: Demo, title: String): Demo? {
|
||||
if (demo.title == title) {
|
||||
return demo
|
||||
}
|
||||
if (demo is DemoCategory) {
|
||||
demo.demos.forEach { child ->
|
||||
findDemo(child, title)
|
||||
?.let { return it }
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FilterMode(backDispatcher: OnBackPressedDispatcher, initialValue: Boolean = false) {
|
||||
|
||||
private var _isFiltering by mutableStateOf(initialValue)
|
||||
|
||||
private val onBackPressed = object : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() {
|
||||
isFiltering = false
|
||||
}
|
||||
}.apply {
|
||||
isEnabled = initialValue
|
||||
backDispatcher.addCallback(this)
|
||||
}
|
||||
|
||||
var isFiltering
|
||||
get() = _isFiltering
|
||||
set(value) {
|
||||
_isFiltering = value
|
||||
onBackPressed.isEnabled = value
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun Saver(backDispatcher: OnBackPressedDispatcher) = Saver<FilterMode, Boolean>(
|
||||
save = { it.isFiltering },
|
||||
restore = { FilterMode(backDispatcher, it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [DemoColors] from the values saved to [SharedPreferences]. If a given color is
|
||||
* not present in the [SharedPreferences], its default value as defined in [Colors]
|
||||
* will be returned.
|
||||
*/
|
||||
fun DemoColors.loadColorsFromSharedPreferences(context: Context) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: remove after b/154329050 is fixed
|
||||
* Inline classes don't play well with reflection, so we want boxed classes for our
|
||||
* call to [lightColors].
|
||||
*/
|
||||
internal fun reflectLightColors(
|
||||
primary: Long = 0xFF6200EE,
|
||||
primaryVariant: Long = 0xFF3700B3,
|
||||
secondary: Long = 0xFF03DAC6,
|
||||
secondaryVariant: Long = 0xFF018786,
|
||||
background: Long = 0xFFFFFFFF,
|
||||
surface: Long = 0xFFFFFFFF,
|
||||
error: Long = 0xFFB00020,
|
||||
onPrimary: Long = 0xFFFFFFFF,
|
||||
onSecondary: Long = 0xFF000000,
|
||||
onBackground: Long = 0xFF000000,
|
||||
onSurface: Long = 0xFF000000,
|
||||
onError: Long = 0xFFFFFFFF
|
||||
) = lightColors(
|
||||
primary = Color(primary),
|
||||
primaryVariant = Color(primaryVariant),
|
||||
secondary = Color(secondary),
|
||||
secondaryVariant = Color(secondaryVariant),
|
||||
background = Color(background),
|
||||
surface = Color(surface),
|
||||
error = Color(error),
|
||||
onPrimary = Color(onPrimary),
|
||||
onSecondary = Color(onSecondary),
|
||||
onBackground = Color(onBackground),
|
||||
onSurface = Color(onSurface),
|
||||
onError = Color(onError)
|
||||
)
|
||||
|
||||
/**
|
||||
* TODO: remove after b/154329050 is fixed
|
||||
* Inline classes don't play well with reflection, so we want boxed classes for our
|
||||
* call to [darkColors].
|
||||
*/
|
||||
internal fun reflectDarkColors(
|
||||
primary: Long = 0xFFBB86FC,
|
||||
primaryVariant: Long = 0xFF3700B3,
|
||||
secondary: Long = 0xFF03DAC6,
|
||||
background: Long = 0xFF121212,
|
||||
surface: Long = 0xFF121212,
|
||||
error: Long = 0xFFCF6679,
|
||||
onPrimary: Long = 0xFF000000,
|
||||
onSecondary: Long = 0xFF000000,
|
||||
onBackground: Long = 0xFFFFFFFF,
|
||||
onSurface: Long = 0xFFFFFFFF,
|
||||
onError: Long = 0xFF000000
|
||||
) = darkColors(
|
||||
primary = Color(primary),
|
||||
primaryVariant = Color(primaryVariant),
|
||||
secondary = Color(secondary),
|
||||
background = Color(background),
|
||||
surface = Color(surface),
|
||||
error = Color(error),
|
||||
onPrimary = Color(onPrimary),
|
||||
onSecondary = Color(onSecondary),
|
||||
onBackground = Color(onBackground),
|
||||
onSurface = Color(onSurface),
|
||||
onError = Color(onError)
|
||||
)
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.demo
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.integration.demos.DemoFilter
|
||||
import androidx.compose.integration.demos.FilterAppBar
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.ListItem
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TopAppBar
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.ArrowForward
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun DemoApp(
|
||||
currentDemo: Demo,
|
||||
backStackTitle: String,
|
||||
isFiltering: Boolean,
|
||||
onStartFiltering: () -> Unit,
|
||||
onEndFiltering: () -> Unit,
|
||||
onNavigateToDemo: (Demo) -> Unit,
|
||||
canNavigateUp: Boolean,
|
||||
onNavigateUp: () -> Unit,
|
||||
launchSettings: () -> Unit
|
||||
) {
|
||||
val navigationIcon = (@Composable { AppBarIcons.Back(onNavigateUp) }).takeIf { canNavigateUp }
|
||||
|
||||
var filterText by rememberSaveable { mutableStateOf("") }
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
DemoAppBar(
|
||||
title = backStackTitle,
|
||||
navigationIcon = navigationIcon,
|
||||
launchSettings = launchSettings,
|
||||
isFiltering = isFiltering,
|
||||
filterText = filterText,
|
||||
onFilter = { filterText = it },
|
||||
onStartFiltering = onStartFiltering,
|
||||
onEndFiltering = onEndFiltering
|
||||
)
|
||||
}
|
||||
) { innerPadding ->
|
||||
val modifier = Modifier.padding(innerPadding)
|
||||
DemoContent(modifier, currentDemo, isFiltering, filterText, onNavigateToDemo)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DemoContent(
|
||||
modifier: Modifier,
|
||||
currentDemo: Demo,
|
||||
isFiltering: Boolean,
|
||||
filterText: String,
|
||||
onNavigate: (Demo) -> Unit
|
||||
) {
|
||||
Crossfade(isFiltering to currentDemo) { (filtering, demo) ->
|
||||
Surface(modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||
if (filtering) {
|
||||
DemoFilter(
|
||||
launchableDemos = AllDemosCategory.allLaunchableDemos(),
|
||||
filterText = filterText,
|
||||
onNavigate = onNavigate
|
||||
)
|
||||
} else {
|
||||
DisplayDemo(demo, onNavigate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DisplayDemo(demo: Demo, onNavigate: (Demo) -> Unit) {
|
||||
when (demo) {
|
||||
is ActivityDemo<*> -> {
|
||||
/* should never get here as activity demos are not added to the backstack*/
|
||||
}
|
||||
is ComposableDemo -> demo.content()
|
||||
is DemoCategory -> DisplayDemoCategory(demo, onNavigate)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
private fun DisplayDemoCategory(category: DemoCategory, onNavigate: (Demo) -> Unit) {
|
||||
// TODO: migrate to LazyColumn after b/175671850
|
||||
Column(Modifier.verticalScroll(rememberScrollState())) {
|
||||
category.demos.forEach { demo ->
|
||||
ListItem(
|
||||
text = {
|
||||
Text(
|
||||
modifier = Modifier.height(56.dp)
|
||||
.wrapContentSize(Alignment.Center),
|
||||
text = demo.title
|
||||
)
|
||||
},
|
||||
modifier = Modifier.clickable { onNavigate(demo) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ComposableLambdaParameterNaming", "ComposableLambdaParameterPosition")
|
||||
@Composable
|
||||
private fun DemoAppBar(
|
||||
title: String,
|
||||
navigationIcon: @Composable (() -> Unit)?,
|
||||
isFiltering: Boolean,
|
||||
filterText: String,
|
||||
onFilter: (String) -> Unit,
|
||||
onStartFiltering: () -> Unit,
|
||||
onEndFiltering: () -> Unit,
|
||||
launchSettings: () -> Unit
|
||||
) {
|
||||
if (isFiltering) {
|
||||
FilterAppBar(
|
||||
filterText = filterText,
|
||||
onFilter = onFilter,
|
||||
onClose = onEndFiltering
|
||||
)
|
||||
} else {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(title, Modifier.testTag(Tags.AppBarTitle))
|
||||
},
|
||||
navigationIcon = navigationIcon,
|
||||
actions = {
|
||||
AppBarIcons.Filter(onClick = onStartFiltering)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private object AppBarIcons {
|
||||
@Composable
|
||||
fun Back(onClick: () -> Unit) {
|
||||
val icon = when (LocalLayoutDirection.current) {
|
||||
LayoutDirection.Ltr -> Icons.Filled.ArrowBack
|
||||
LayoutDirection.Rtl -> Icons.Filled.ArrowForward
|
||||
}
|
||||
IconButton(onClick = onClick) {
|
||||
Icon(icon, null)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Filter(onClick: () -> Unit) {
|
||||
IconButton(modifier = Modifier.testTag(Tags.FilterButton), onClick = onClick) {
|
||||
Icon(Icons.Filled.Search, null)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Settings(onClick: () -> Unit) {
|
||||
IconButton(onClick = onClick) {
|
||||
Icon(Icons.Filled.Settings, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.demo
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material.Colors
|
||||
import androidx.compose.material.darkColors
|
||||
import androidx.compose.material.lightColors
|
||||
|
||||
/**
|
||||
* Wrapper class that contains a light and dark [Colors], to allow saving and
|
||||
* restoring the entire light / dark theme to and from [SharedPreferences].
|
||||
*/
|
||||
@Stable
|
||||
class DemoColors {
|
||||
var light: Colors by mutableStateOf(lightColors())
|
||||
var dark: Colors by mutableStateOf(darkColors())
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package androidx.compose.integration.demos
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.ListItem
|
||||
import androidx.compose.material.LocalContentColor
|
||||
import androidx.compose.material.LocalTextStyle
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TopAppBar
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.graphics.compositeOver
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.Demo
|
||||
|
||||
/**
|
||||
* A scrollable list of [launchableDemos], filtered by [filterText].
|
||||
*/
|
||||
@Composable
|
||||
fun DemoFilter(launchableDemos: List<Demo>, filterText: String, onNavigate: (Demo) -> Unit) {
|
||||
val filteredDemos = launchableDemos
|
||||
.filter { it.title.contains(filterText, ignoreCase = true) }
|
||||
.sortedBy { it.title }
|
||||
// TODO: migrate to LazyColumn after b/175671850
|
||||
Column(Modifier.verticalScroll(rememberScrollState())) {
|
||||
filteredDemos.forEach { demo ->
|
||||
FilteredDemoListItem(
|
||||
demo,
|
||||
filterText = filterText,
|
||||
onNavigate = onNavigate
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [TopAppBar] with a text field allowing filtering all the demos.
|
||||
*/
|
||||
@Composable
|
||||
fun FilterAppBar(
|
||||
filterText: String,
|
||||
onFilter: (String) -> Unit,
|
||||
onClose: () -> Unit
|
||||
) {
|
||||
with(MaterialTheme.colors) {
|
||||
val appBarColor = if (isLight) {
|
||||
surface
|
||||
} else {
|
||||
// Blending primary over surface according to Material design guidance for brand
|
||||
// surfaces in dark theme
|
||||
primary.copy(alpha = 0.08f).compositeOver(surface)
|
||||
}
|
||||
TopAppBar(backgroundColor = appBarColor, contentColor = onSurface) {
|
||||
IconButton(modifier = Modifier.align(Alignment.CenterVertically), onClick = onClose) {
|
||||
Icon(Icons.Filled.Close, null)
|
||||
}
|
||||
FilterField(
|
||||
filterText,
|
||||
onFilter,
|
||||
Modifier.fillMaxWidth().align(Alignment.CenterVertically)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [BasicTextField] that edits the current [filterText], providing [onFilter] when edited.
|
||||
*/
|
||||
@Composable
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
private fun FilterField(
|
||||
filterText: String,
|
||||
onFilter: (String) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* [ListItem] that displays a [demo] and highlights any matches for [filterText] inside [Demo.title]
|
||||
*/
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
private fun FilteredDemoListItem(
|
||||
demo: Demo,
|
||||
filterText: String,
|
||||
onNavigate: (Demo) -> Unit
|
||||
) {
|
||||
val primary = MaterialTheme.colors.primary
|
||||
val annotatedString = buildAnnotatedString {
|
||||
val title = demo.title
|
||||
var currentIndex = 0
|
||||
val pattern = filterText.toRegex(option = RegexOption.IGNORE_CASE)
|
||||
pattern.findAll(title).forEach { result ->
|
||||
val index = result.range.first
|
||||
if (index > currentIndex) {
|
||||
append(title.substring(currentIndex, index))
|
||||
currentIndex = index
|
||||
}
|
||||
withStyle(SpanStyle(color = primary)) {
|
||||
append(result.value)
|
||||
}
|
||||
currentIndex = result.range.last + 1
|
||||
}
|
||||
if (currentIndex <= title.lastIndex) {
|
||||
append(title.substring(currentIndex, title.length))
|
||||
}
|
||||
}
|
||||
key(demo.title) {
|
||||
ListItem(
|
||||
text = {
|
||||
Text(
|
||||
modifier = Modifier.height(56.dp).wrapContentSize(Alignment.Center),
|
||||
text = annotatedString
|
||||
)
|
||||
},
|
||||
modifier = Modifier.clickable { onNavigate(demo) }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.demo
|
||||
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.activity.ActivityDemos
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.animation.AnimationDemos
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation.FoundationDemos
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.general.GeneralDemos
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.layout.LayoutDemos
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.MaterialDemos
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.other.OtherDemos
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.ui.UIDemos
|
||||
|
||||
|
||||
/**
|
||||
* [DemoCategory] containing all the top level demo categories.
|
||||
*/
|
||||
val AllDemosCategory = DemoCategory(
|
||||
"Jetpack Compose Playground Demos",
|
||||
listOf(
|
||||
AnimationDemos,
|
||||
FoundationDemos,
|
||||
LayoutDemos,
|
||||
MaterialDemos,
|
||||
GeneralDemos,
|
||||
OtherDemos,
|
||||
ActivityDemos,
|
||||
UIDemos
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.demo
|
||||
|
||||
/**
|
||||
* Tags used for testing
|
||||
*/
|
||||
object Tags {
|
||||
const val AppBarTitle = "AppBarTitle"
|
||||
const val FilterButton = "FilterButton"
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.activity
|
||||
|
||||
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.ComposableDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoCategory
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.activity.backhandler.BackHandlerExample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.animation.crossfade.CrossfadeDemo
|
||||
|
||||
|
||||
val ActivityDemos = DemoCategory(
|
||||
"Activity",
|
||||
listOf(
|
||||
ComposableDemo("BackHandler") { BackHandlerExample() }
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.activity.backhandler
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
|
||||
//# --8<-- [start:func]
|
||||
@Composable
|
||||
fun BackHandlerExample() {
|
||||
var backPressedCount by remember { mutableStateOf(0) }
|
||||
BackHandler(enabled = true, onBack = {
|
||||
backPressedCount += 1
|
||||
})
|
||||
Text(text="Backbutton was pressed : $backPressedCount times")
|
||||
}
|
||||
//# --8<-- [end:func]
|
||||
@@ -0,0 +1,63 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.androidview
|
||||
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.content.ContextCompat
|
||||
import de.jensklingenberg.jetpackcomposeplayground.R
|
||||
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun EmbeddedAndroidViewDemo() {
|
||||
Column {
|
||||
val state = remember { mutableStateOf(0) }
|
||||
|
||||
//widget.ImageView
|
||||
AndroidView(factory = { ctx ->
|
||||
ImageView(ctx).apply {
|
||||
val drawable = ContextCompat.getDrawable(ctx, R.drawable.composelogo)
|
||||
setImageDrawable(drawable)
|
||||
}
|
||||
})
|
||||
|
||||
//Compose Button
|
||||
androidx.compose.material.Button(onClick = { state.value++ }) {
|
||||
Text("MyComposeButton")
|
||||
}
|
||||
|
||||
//widget.Button
|
||||
AndroidView(factory = { ctx ->
|
||||
//Here you can construct your View
|
||||
android.widget.Button(ctx).apply {
|
||||
text = "MyAndroidButton"
|
||||
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||
setOnClickListener {
|
||||
state.value++
|
||||
}
|
||||
}
|
||||
}, modifier = Modifier.padding(8.dp))
|
||||
|
||||
//widget.TextView
|
||||
AndroidView(factory = { ctx ->
|
||||
//Here you can construct your View
|
||||
TextView(ctx).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||
}
|
||||
}, update = {
|
||||
it.text = "You have clicked the buttons: " + state.value.toString() + " times"
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.animation
|
||||
|
||||
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.ComposableDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoCategory
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.animation.crossfade.CrossfadeDemo
|
||||
|
||||
|
||||
val AnimationDemos = DemoCategory(
|
||||
"Animation",
|
||||
listOf(
|
||||
ComposableDemo("CrossfadeDemo") { CrossfadeDemo() }
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.animation.crossfade
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
|
||||
enum class MyColors(val color: Color) {
|
||||
Red(Color.Red), Green(Color.Green), Blue(Color.Blue)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun CrossfadeDemo() {
|
||||
var currentColor by remember { mutableStateOf(MyColors.Red) }
|
||||
Column {
|
||||
Row {
|
||||
MyColors.values().forEach { myColors ->
|
||||
Button(
|
||||
onClick = { currentColor = myColors },
|
||||
Modifier.weight(1f, true)
|
||||
.height(48.dp).background(myColors.color),colors = ButtonDefaults.buttonColors(backgroundColor = myColors.color)
|
||||
) {
|
||||
Text(myColors.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
Crossfade(targetState = currentColor, animationSpec = tween(3000)) { selectedColor ->
|
||||
Box(modifier = Modifier.fillMaxSize().background(selectedColor.color))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.cookbook.textfieldchange
|
||||
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.material.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.runtime.*
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun HandleTextFieldChanges() {
|
||||
var textState by remember { mutableStateOf(TextFieldValue()) }
|
||||
|
||||
TextField(value = textState, onValueChange = {
|
||||
textState = it
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation
|
||||
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun CanvasDrawExample() {
|
||||
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||
drawRect(Color.Blue, topLeft = Offset(0f, 0f), size = Size(this.size.width, 55f))
|
||||
drawCircle(Color.Red, center = Offset(50f, 200f), radius = 40f)
|
||||
drawLine(
|
||||
Color.Green, Offset(20f, 0f),
|
||||
Offset(200f, 200f), strokeWidth = 5f
|
||||
)
|
||||
|
||||
drawArc(
|
||||
Color.Black,
|
||||
0f,
|
||||
60f,
|
||||
useCenter = true,
|
||||
size = Size(300f, 300f),
|
||||
topLeft = Offset(60f, 60f)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation
|
||||
|
||||
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.ComposableDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoCategory
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation.basictextfield.BasicTextFieldDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation.layout.BoxWithConstraintsDemo
|
||||
|
||||
|
||||
val FoundationDemos = DemoCategory(
|
||||
"Foundation",
|
||||
listOf(
|
||||
ComposableDemo("BaseTextFieldDemo") { BasicTextFieldDemo() },
|
||||
ComposableDemo("BoxWithConstraints") { BoxWithConstraintsDemo() },
|
||||
ComposableDemo("Canvas") { CanvasDrawExample() },
|
||||
ComposableDemo("LazyRowDemo") { LazyRowDemo() },
|
||||
ComposableDemo("LazyColumnDemo") { LazyColumnDemo() },
|
||||
ComposableDemo("LazyVerticalGridDemo") { LazyVerticalGridDemo() },
|
||||
ComposableDemo("TextDemo") { TextExample() },
|
||||
ComposableDemo("CircleShapeDemo") { ShapeDemo() },
|
||||
ComposableDemo("ImageResourceDemo") { ImageResourceDemo() },
|
||||
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import de.jensklingenberg.jetpackcomposeplayground.R
|
||||
|
||||
|
||||
@Composable
|
||||
fun ImageResourceDemo() {
|
||||
val image: Painter = painterResource(id = R.drawable.composelogo)
|
||||
Image(painter = image,contentDescription = "")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.lazy.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
@Composable
|
||||
fun LazyColumnDemo() {
|
||||
val list = listOf(
|
||||
"A", "B", "C", "D"
|
||||
) + ((0..100).map { it.toString() })
|
||||
LazyColumn(modifier = Modifier.fillMaxHeight()) {
|
||||
items(items = list, itemContent = { item ->
|
||||
Log.d("COMPOSE", "This get rendered $item")
|
||||
when (item) {
|
||||
"A" -> {
|
||||
Text(text = item, style = TextStyle(fontSize = 80.sp))
|
||||
}
|
||||
"B" -> {
|
||||
Button(onClick = {}) {
|
||||
Text(text = item, style = TextStyle(fontSize = 80.sp))
|
||||
}
|
||||
}
|
||||
"C" -> {
|
||||
//Do Nothing
|
||||
}
|
||||
"D" -> {
|
||||
Text(text = item)
|
||||
}
|
||||
else -> {
|
||||
Text(text = item, style = TextStyle(fontSize = 80.sp))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.lazy.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
@Composable
|
||||
fun LazyRowDemo() {
|
||||
val list = listOf(
|
||||
"A", "B", "C", "D"
|
||||
) + ((0..100).map { it.toString() })
|
||||
LazyRow(modifier = Modifier.fillMaxHeight()) {
|
||||
items(items = list, itemContent = { item ->
|
||||
Log.d("COMPOSE", "This get rendered $item")
|
||||
when (item) {
|
||||
"A" -> {
|
||||
Text(text = item, style = TextStyle(fontSize = 80.sp))
|
||||
}
|
||||
"B" -> {
|
||||
Button(onClick = {}) {
|
||||
Text(text = item, style = TextStyle(fontSize = 80.sp))
|
||||
}
|
||||
}
|
||||
"C" -> {
|
||||
//Do Nothing
|
||||
}
|
||||
"D" -> {
|
||||
Text(text = item)
|
||||
}
|
||||
else -> {
|
||||
Text(text = item, style = TextStyle(fontSize = 80.sp))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
@Composable
|
||||
fun LazyVerticalGridDemo(){
|
||||
val list = (1..10).map { it.toString() }
|
||||
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(128.dp),
|
||||
|
||||
// content padding
|
||||
contentPadding = PaddingValues(
|
||||
start = 12.dp,
|
||||
top = 16.dp,
|
||||
end = 12.dp,
|
||||
bottom = 16.dp
|
||||
),
|
||||
content = {
|
||||
items(list.size) { index ->
|
||||
Card(
|
||||
backgroundColor = Color.Red,
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
.fillMaxWidth(),
|
||||
elevation = 8.dp,
|
||||
) {
|
||||
Text(
|
||||
text = list[index],
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 30.sp,
|
||||
color = Color(0xFFFFFFFF),
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.CutCornerShape
|
||||
import androidx.compose.foundation.shape.GenericShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.*
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
|
||||
@Composable
|
||||
fun CircleShapeDemo() {
|
||||
BoxDemo(CircleShape)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ShapeDemo() {
|
||||
Column {
|
||||
Text("CircleShapeDemo:")
|
||||
CircleShapeDemo()
|
||||
Text("RoundedCornerShapeDemo:")
|
||||
RoundedCornerShapeDemo()
|
||||
Text("CutCornerShapeDemo:")
|
||||
CutCornerShapeDemo()
|
||||
Text("RectangleShapeDemo:")
|
||||
RectangleShapeDemo()
|
||||
Text("TriangleShapeDemo:")
|
||||
TriangleShapeDemo()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BoxDemo(shape: Shape) {
|
||||
Column(modifier = Modifier.fillMaxWidth().wrapContentSize(Alignment.Center).clip(shape)) {
|
||||
Box(
|
||||
modifier = Modifier.size(100.dp).background(Color.Red)
|
||||
) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RoundedCornerShapeDemo() {
|
||||
BoxDemo(shape = RoundedCornerShape(10.dp))
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CutCornerShapeDemo() {
|
||||
BoxDemo(shape = CutCornerShape(10.dp))
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun RectangleShapeDemo() {
|
||||
BoxDemo(shape = RectangleShape)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TriangleShapeDemo() {
|
||||
BoxDemo(shape = CustomShape())
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* You can draw custom shapes.
|
||||
* Use a GenericShape.
|
||||
*/
|
||||
|
||||
|
||||
private val TriangleShape = GenericShape { size, direction ->
|
||||
/**
|
||||
*
|
||||
Inside the GenericShape you can draw your custom shape.
|
||||
You have access to the **size**-object. This is size of the composable that the shape is applied to.
|
||||
You can get the height with **size.height.value** and the width with **size.width.value**
|
||||
|
||||
|
||||
1) Initially the painter will start at the top left of the parent composable(0x,0y).
|
||||
With **moveTo()** you can set the coordinates of the painter. Here the coordinates will be set to the half width of the parent layout
|
||||
and a 0y coordinate.
|
||||
|
||||
2) This will draw a line from the painter coordinates, which were set in **1)**, to the bottom right corner of the parent layout.
|
||||
The painter coordinates are then automatically set to this corner.
|
||||
|
||||
3) This will draw a line to the bottom left corner. GenericShape will implicit execute the **close()**-function. **close()** will draw a line from the last painter coordinates to the first definied.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1)
|
||||
*/
|
||||
/**
|
||||
*
|
||||
Inside the GenericShape you can draw your custom shape.
|
||||
You have access to the **size**-object. This is size of the composable that the shape is applied to.
|
||||
You can get the height with **size.height.value** and the width with **size.width.value**
|
||||
|
||||
|
||||
1) Initially the painter will start at the top left of the parent composable(0x,0y).
|
||||
With **moveTo()** you can set the coordinates of the painter. Here the coordinates will be set to the half width of the parent layout
|
||||
and a 0y coordinate.
|
||||
|
||||
2) This will draw a line from the painter coordinates, which were set in **1)**, to the bottom right corner of the parent layout.
|
||||
The painter coordinates are then automatically set to this corner.
|
||||
|
||||
3) This will draw a line to the bottom left corner. GenericShape will implicit execute the **close()**-function. **close()** will draw a line from the last painter coordinates to the first definied.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 1)
|
||||
*/
|
||||
moveTo(size.width / 2f, 0f)
|
||||
//This will draw a line from the cursor to the x/y coordinates
|
||||
|
||||
/**
|
||||
* 2)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 2)
|
||||
*/
|
||||
lineTo(size.width, size.height)
|
||||
|
||||
/**
|
||||
* 3)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 3)
|
||||
*/
|
||||
lineTo(0f, size.height)
|
||||
}
|
||||
|
||||
|
||||
class CustomShape : Shape {
|
||||
|
||||
|
||||
override fun createOutline(
|
||||
size: Size,
|
||||
layoutDirection: LayoutDirection,
|
||||
density: Density
|
||||
): Outline {
|
||||
val path = Path().apply {
|
||||
moveTo(size.width / 2f, 0f)
|
||||
lineTo(size.width, size.height)
|
||||
lineTo(0f, size.height)
|
||||
close()
|
||||
}
|
||||
return Outline.Generic(path)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation
|
||||
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
|
||||
@Composable
|
||||
fun TextExample(){
|
||||
Column {
|
||||
Text("Just Text")
|
||||
Text("Text with cursive font", style = TextStyle(fontFamily = FontFamily.Cursive))
|
||||
Text(
|
||||
text = "Text with LineThrough",
|
||||
style = TextStyle(textDecoration = TextDecoration.LineThrough)
|
||||
)
|
||||
Text(
|
||||
text = "Text with underline",
|
||||
style = TextStyle(textDecoration = TextDecoration.Underline)
|
||||
)
|
||||
Text(
|
||||
text = "Text with underline, linethrough and bold",
|
||||
style = TextStyle(
|
||||
textDecoration = TextDecoration.combine(
|
||||
listOf(
|
||||
TextDecoration.Underline,
|
||||
TextDecoration.LineThrough
|
||||
)
|
||||
), fontWeight = FontWeight.Bold
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun NormalTextExample(){
|
||||
Text("Just Text")
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CursiveTextExample(){
|
||||
Text("Text with cursive font", style = TextStyle(fontFamily = FontFamily.Cursive))
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TextWithLineThroughExample(){
|
||||
Text(
|
||||
text = "Text with LineThrough",
|
||||
style = TextStyle(textDecoration = TextDecoration.LineThrough)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TextWithUnderline(){
|
||||
Text(
|
||||
text = "Text with underline",
|
||||
style = TextStyle(textDecoration = TextDecoration.Underline)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun TextWithUnderlineStrikeThroughAndBold(){
|
||||
Text(
|
||||
text = "Text with underline, linethrough and bold",
|
||||
style = TextStyle(
|
||||
textDecoration = TextDecoration.combine(
|
||||
listOf(
|
||||
TextDecoration.Underline,
|
||||
TextDecoration.LineThrough
|
||||
)
|
||||
), fontWeight = FontWeight.Bold
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation.basictextfield
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
|
||||
//# --8<-- [start:func]
|
||||
@Composable
|
||||
fun BasicTextFieldDemo() {
|
||||
var textState by remember { mutableStateOf(TextFieldValue("Hello World")) }
|
||||
Column {
|
||||
BasicTextField(value = textState, onValueChange = {
|
||||
textState = it
|
||||
})
|
||||
Text("The textfield has this text: " + textState.text)
|
||||
}
|
||||
}
|
||||
//# --8<-- [end:func]
|
||||
@@ -0,0 +1,41 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation.layout
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
@Composable
|
||||
fun BoxWithConstraintsDemo() {
|
||||
Column {
|
||||
Column {
|
||||
MyBoxWithConstraintsDemo()
|
||||
}
|
||||
|
||||
Text("Here we set the size to 150.dp", modifier = Modifier.padding(top = 20.dp))
|
||||
Column(modifier = Modifier.size(150.dp)) {
|
||||
MyBoxWithConstraintsDemo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MyBoxWithConstraintsDemo() {
|
||||
BoxWithConstraints {
|
||||
val boxWithConstraintsScope = this
|
||||
//You can use this scope to get the minWidth, maxWidth, minHeight, maxHeight in dp and constraints
|
||||
|
||||
Column {
|
||||
if (boxWithConstraintsScope.maxHeight >= 200.dp) {
|
||||
Text(
|
||||
"This is only visible when the maxHeight is >= 200.dp",
|
||||
style = TextStyle(fontSize = 20.sp)
|
||||
)
|
||||
}
|
||||
Text("minHeight: ${boxWithConstraintsScope.minHeight}, maxHeight: ${boxWithConstraintsScope.maxHeight}, minWidth: ${boxWithConstraintsScope.minWidth} maxWidth: ${boxWithConstraintsScope.maxWidth}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.foundation.layout
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun SpacerDemo() {
|
||||
Column {
|
||||
Text("Hello")
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.size(30.dp)
|
||||
)
|
||||
Text("World")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.general
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
|
||||
|
||||
data class User(val name: String, val age: Int)
|
||||
|
||||
val LocalActiveUser = compositionLocalOf<User> { error("No user found!") }
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContent {
|
||||
MyUserScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MyUserScreen() {
|
||||
val user = User("Jens", 31)
|
||||
CompositionLocalProvider(LocalActiveUser provides user) {
|
||||
UserInfo()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun UserInfo() {
|
||||
Column {
|
||||
Text("Name: " + LocalActiveUser.current.name)
|
||||
Text("Age: " + LocalActiveUser.current.age)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.general
|
||||
|
||||
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.ComposableDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoCategory
|
||||
|
||||
|
||||
val GeneralDemos = DemoCategory(
|
||||
"General",
|
||||
listOf(
|
||||
ComposableDemo("LifecycleDemo") { LifecycleDemo() },
|
||||
ComposableDemo("PaddingDemo") { PaddingDemo() },
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.general
|
||||
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
|
||||
|
||||
@Composable
|
||||
fun LifecycleDemo() {
|
||||
|
||||
val count = remember { mutableStateOf(0) }
|
||||
|
||||
Column {
|
||||
Button(onClick = {
|
||||
count.value++
|
||||
}) {
|
||||
Text("Click me")
|
||||
}
|
||||
|
||||
if (count.value < 3) {
|
||||
SideEffect {
|
||||
Log.d("Compose", "onactive with value: " + count.value)
|
||||
}
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
Log.d("Compose", "onDispose because value=" + count.value)
|
||||
}
|
||||
}
|
||||
|
||||
Text(text = "You have clicked the button: " + count.value.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.general
|
||||
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
|
||||
@Composable
|
||||
fun PaddingDemo() {
|
||||
|
||||
Column {
|
||||
Text("TextWithoutPadding")
|
||||
Column(modifier = Modifier.padding(start = 80.dp)){
|
||||
Text("TextWith80dpOnlyLeftPadding")
|
||||
|
||||
}
|
||||
|
||||
|
||||
Column(Modifier.padding(all = 80.dp)){
|
||||
Text("TextWith80dpPadding")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.layout
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.FloatingActionButton
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
|
||||
@Preview(showBackground = true)
|
||||
//# --8<-- [start:func]
|
||||
@Composable
|
||||
fun BoxExample() {
|
||||
Box(Modifier.fillMaxSize()) {
|
||||
Text("This text is drawn first", modifier = Modifier.align(Alignment.TopCenter))
|
||||
Box(
|
||||
Modifier.align(Alignment.TopCenter).fillMaxHeight().width(
|
||||
50.dp
|
||||
).background( Color.Blue)
|
||||
)
|
||||
Text("This text is drawn last", modifier = Modifier.align(Alignment.Center))
|
||||
FloatingActionButton(
|
||||
modifier = Modifier.align(Alignment.BottomEnd).padding(12.dp),
|
||||
onClick = {}
|
||||
) {
|
||||
Text("+")
|
||||
}
|
||||
}
|
||||
}
|
||||
//# --8<-- [end:func]
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.layout
|
||||
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
|
||||
|
||||
|
||||
@Composable
|
||||
fun ColumnDemo() {
|
||||
|
||||
MaterialTheme {
|
||||
ColumnExample()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ColumnExample() {
|
||||
|
||||
Column {
|
||||
Text(text = " Hello World!")
|
||||
Text(text = " Hello World!2")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.layout
|
||||
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
|
||||
|
||||
@Composable
|
||||
fun ConstraintLayoutDemo() {
|
||||
ConstraintLayout(modifier = Modifier.size(200.dp)) {
|
||||
val (redBox, blueBox, yellowBox, text) = createRefs()
|
||||
|
||||
Box(modifier = Modifier
|
||||
.size(50.dp)
|
||||
.background(Color.Red)
|
||||
.constrainAs(redBox) {})
|
||||
|
||||
Box(modifier = Modifier
|
||||
.size(50.dp)
|
||||
.background(Color.Blue)
|
||||
.constrainAs(blueBox) {
|
||||
top.linkTo(redBox.bottom)
|
||||
start.linkTo(redBox.end)
|
||||
})
|
||||
|
||||
Box(modifier = Modifier
|
||||
.size(50.dp)
|
||||
.background(Color.Yellow)
|
||||
.constrainAs(yellowBox) {
|
||||
bottom.linkTo(blueBox.bottom)
|
||||
start.linkTo(blueBox.end, 20.dp)
|
||||
})
|
||||
|
||||
Text("Hello World", modifier = Modifier.constrainAs(text) {
|
||||
top.linkTo(parent.top)
|
||||
start.linkTo(yellowBox.start)
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.layout
|
||||
|
||||
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.ComposableDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoCategory
|
||||
|
||||
|
||||
val LayoutDemos = DemoCategory(
|
||||
"LayoutDemos",
|
||||
listOf(
|
||||
ComposableDemo("BoxExample") { BoxExample() },
|
||||
ComposableDemo("ConstraintLayoutDemo") { ConstraintLayoutDemo() },
|
||||
|
||||
ComposableDemo("ColumnExample") { ColumnExample() },
|
||||
ComposableDemo("RowExample") { RowExample() },
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.layout
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
|
||||
@Composable
|
||||
fun RowDemo() {
|
||||
MaterialTheme {
|
||||
RowExample()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RowExample() {
|
||||
Row {
|
||||
Text(text = " Hello World!", style = (MaterialTheme.typography).body1)
|
||||
Text(text = " Hello World!2", style = (MaterialTheme.typography).body1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material
|
||||
|
||||
|
||||
import SnackbarDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.ComposableDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoCategory
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.button.ButtonExample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.card.CardDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.checkbox.CheckBoxDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.circularprogress.CircularProgressIndicatorSample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.dropdown.DropdownDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.floatingactionbutton.FloatingActionButtonDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.linearprogress.LinearProgressIndicatorSample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.modaldrawer.ModalDrawerSample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.radiobutton.RadioButtonSample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.alertdialog.AlertDialogSample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.appbar.topappbar.TopAppBarSample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.button.ProgressButtonExample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.divider.DividerExample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.modalbottomsheetlayout.ModalBottomSheetSample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.navigationrail.NavigationRailSample
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.scaffold.ScaffoldDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.surface.SurfaceDemo
|
||||
|
||||
|
||||
val MaterialDemos = DemoCategory(
|
||||
"MaterialDemos",
|
||||
listOf(
|
||||
ComposableDemo("AlertDialogSample") { AlertDialogSample() },
|
||||
ComposableDemo("ButtonExample") { ButtonExample() },
|
||||
ComposableDemo("ProgressButtonExample") { ProgressButtonExample() },
|
||||
ComposableDemo("CardDemo") { CardDemo() },
|
||||
ComposableDemo("CheckBoxDemo") { CheckBoxDemo() },
|
||||
ComposableDemo("CircularProgressIndicatorSample") { CircularProgressIndicatorSample() },
|
||||
ComposableDemo("Divider") { DividerExample() },
|
||||
ComposableDemo("DropdownDemo") { DropdownDemo() },
|
||||
ComposableDemo("FloatingActionButtonDemo") { FloatingActionButtonDemo() },
|
||||
ComposableDemo("LinearProgressIndicatorSample") { LinearProgressIndicatorSample() },
|
||||
ComposableDemo("ModalBottomSheetSample") { ModalBottomSheetSample() },
|
||||
ComposableDemo("ModalDrawerLayoutSample") { ModalDrawerSample() },
|
||||
ComposableDemo("NavigationRailSample") { NavigationRailSample() },
|
||||
ComposableDemo("RadioButtonSample") { RadioButtonSample() },
|
||||
ComposableDemo("ScaffoldDemo") { ScaffoldDemo() },
|
||||
ComposableDemo("SnackbarDemo") { SnackbarDemo() },
|
||||
ComposableDemo("SurfaceDemo") { SurfaceDemo() },
|
||||
ComposableDemo("TopAppBarSample") { TopAppBarSample() },
|
||||
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,61 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.alertdialog
|
||||
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
||||
|
||||
@Composable
|
||||
fun AlertDialogSample() {
|
||||
MaterialTheme {
|
||||
Column {
|
||||
val openDialog = remember { mutableStateOf(false) }
|
||||
|
||||
Button(onClick = {
|
||||
openDialog.value = true
|
||||
}) {
|
||||
Text("Click me")
|
||||
}
|
||||
|
||||
if (openDialog.value) {
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
// Dismiss the dialog when the user clicks outside the dialog or on the back
|
||||
// button. If you want to disable that functionality, simply use an empty
|
||||
// onCloseRequest.
|
||||
openDialog.value = false
|
||||
},
|
||||
title = {
|
||||
Text(text = "Dialog Title")
|
||||
},
|
||||
text = {
|
||||
Text("Here is a text ")
|
||||
},
|
||||
confirmButton = {
|
||||
Button(
|
||||
|
||||
onClick = {
|
||||
openDialog.value = false
|
||||
}) {
|
||||
Text("This is the Confirm Button")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
Button(
|
||||
|
||||
onClick = {
|
||||
openDialog.value = false
|
||||
}) {
|
||||
Text("This is the dismiss Button")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.appbar.topappbar
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun TopAppBarSample(){
|
||||
Column {
|
||||
TopAppBar(
|
||||
elevation = 4.dp,
|
||||
title = {
|
||||
Text("I'm a TopAppBar")
|
||||
},
|
||||
backgroundColor = MaterialTheme.colors.primarySurface,
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {/* Do Something*/ }) {
|
||||
Icon(Icons.Filled.ArrowBack, null)
|
||||
}
|
||||
}, actions = {
|
||||
IconButton(onClick = {/* Do Something*/ }) {
|
||||
Icon(Icons.Filled.Share, null)
|
||||
}
|
||||
IconButton(onClick = {/* Do Something*/ }) {
|
||||
Icon(Icons.Filled.Settings, null)
|
||||
}
|
||||
})
|
||||
|
||||
Text("Hello World")
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.badgebox
|
||||
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
fun BadgeBoxDemo() {
|
||||
BottomNavigation {
|
||||
BottomNavigationItem(
|
||||
icon = {
|
||||
BadgedBox(badge = { Badge { Text("8") } }) {
|
||||
Icon(
|
||||
Icons.Filled.Favorite,
|
||||
contentDescription = "Favorite"
|
||||
)
|
||||
}
|
||||
|
||||
},
|
||||
selected = false,
|
||||
onClick = {})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.button
|
||||
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.OutlinedButton
|
||||
import androidx.compose.material.R
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun ButtonExample() {
|
||||
Button(
|
||||
onClick = { /* Do something! */ }, colors = ButtonDefaults.textButtonColors(
|
||||
backgroundColor = Color.Red
|
||||
)
|
||||
) {
|
||||
Text("Button")
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun OutlinedButtonExample() {
|
||||
OutlinedButton(onClick = { /* Do something! */ }) {
|
||||
Text("I'm an Outlined Button")
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TextButtonExample() {
|
||||
TextButton(onClick = { /* Do something! */ }) {
|
||||
Text("I'm a Text Button")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun ProgressButtonExample() {
|
||||
var loading by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
Box() {
|
||||
ProgressButton(
|
||||
onClick = { loading = !loading },
|
||||
modifier = Modifier
|
||||
.padding(16.dp)
|
||||
.height(46.dp)
|
||||
.align(Alignment.Center),
|
||||
loading = loading,
|
||||
color = Color.Black,
|
||||
progressColor = Color.White
|
||||
) {
|
||||
Text(
|
||||
color = Color.White,
|
||||
text = "Refresh"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ProgressButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
loading: Boolean = false,
|
||||
color: Color,
|
||||
progressColor: Color,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val contentAlpha by animateFloatAsState(targetValue = if (loading) 0f else 1f)
|
||||
val loadingAlpha by animateFloatAsState(targetValue = if (loading) 1f else 0f)
|
||||
Button(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
colors = ButtonDefaults.buttonColors(backgroundColor = color),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.size(size = 16.dp)
|
||||
.graphicsLayer { alpha = loadingAlpha },
|
||||
color = progressColor,
|
||||
strokeWidth = 2.dp,
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier.graphicsLayer { alpha = contentAlpha }
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.card
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun CardDemo() {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(15.dp)
|
||||
.clickable{ },
|
||||
elevation = 10.dp
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(15.dp)
|
||||
) {
|
||||
Text(
|
||||
buildAnnotatedString {
|
||||
append("welcome to ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.W900, color = Color(0xFF4552B8))
|
||||
) {
|
||||
append("Jetpack Compose Playground")
|
||||
}
|
||||
}
|
||||
)
|
||||
Text(
|
||||
buildAnnotatedString {
|
||||
append("Now you are in the ")
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.W900)) {
|
||||
append("Card")
|
||||
}
|
||||
append(" section")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.checkbox
|
||||
|
||||
import androidx.compose.material.Checkbox
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
||||
@Composable
|
||||
fun CheckBoxDemo() {
|
||||
val checkedState = remember { mutableStateOf(true) }
|
||||
Checkbox(
|
||||
checked = checkedState.value,
|
||||
onCheckedChange = { checkedState.value = it }
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.circularprogress
|
||||
|
||||
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.OutlinedButton
|
||||
import androidx.compose.material.ProgressIndicatorDefaults
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun CircularProgressIndicatorSample() {
|
||||
var progress by remember { mutableStateOf(0.1f) }
|
||||
val animatedProgress = animateFloatAsState(
|
||||
targetValue = progress,
|
||||
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
|
||||
).value
|
||||
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Spacer(Modifier.height(30.dp))
|
||||
Text("CircularProgressIndicator with undefined progress")
|
||||
CircularProgressIndicator()
|
||||
Spacer(Modifier.height(30.dp))
|
||||
Text("CircularProgressIndicator with progress set by buttons")
|
||||
CircularProgressIndicator(progress = animatedProgress)
|
||||
Spacer(Modifier.height(30.dp))
|
||||
OutlinedButton(
|
||||
onClick = {
|
||||
if (progress < 1f) progress += 0.1f
|
||||
}
|
||||
) {
|
||||
Text("Increase")
|
||||
}
|
||||
|
||||
OutlinedButton(
|
||||
onClick = {
|
||||
if (progress > 0f) progress -= 0.1f
|
||||
}
|
||||
) {
|
||||
Text("Decrease")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.divider
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun DividerExample(){
|
||||
Column {
|
||||
Text("Foo")
|
||||
Divider(startIndent = 8.dp, thickness = 1.dp, color = Color.Black)
|
||||
Text("Bar")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.dropdown
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun DropdownDemo() {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val items = listOf("A", "B", "C", "D", "E", "F")
|
||||
val disabledValue = "B"
|
||||
var selectedIndex by remember { mutableStateOf(0) }
|
||||
Box(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)) {
|
||||
Text(items[selectedIndex],modifier = Modifier.fillMaxWidth().clickable(onClick = { expanded = true }).background(
|
||||
Color.Gray))
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
modifier = Modifier.fillMaxWidth().background(
|
||||
Color.Red)
|
||||
) {
|
||||
items.forEachIndexed { index, s ->
|
||||
DropdownMenuItem(onClick = {
|
||||
selectedIndex = index
|
||||
expanded = false
|
||||
}) {
|
||||
val disabledText = if (s == disabledValue) {
|
||||
" (Disabled)"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
Text(text = s + disabledText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.floatingactionbutton
|
||||
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun FloatingActionButtonDemo() {
|
||||
FloatingActionButton(onClick = { /*do something*/}) {
|
||||
Text("FloatingActionButton")
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ExtendedFloatingActionButtonDemo() {
|
||||
ExtendedFloatingActionButton(
|
||||
icon = { Icon(Icons.Filled.Favorite,"") },
|
||||
text = { Text("FloatingActionButton") },
|
||||
onClick = { /*do something*/ },
|
||||
elevation = FloatingActionButtonDefaults.elevation(8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.linearprogress
|
||||
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun LinearProgressIndicatorSample() {
|
||||
var progress by remember { mutableStateOf(0.1f) }
|
||||
val animatedProgress = animateFloatAsState(
|
||||
targetValue = progress,
|
||||
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
|
||||
).value
|
||||
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
|
||||
Spacer(Modifier.height(30.dp))
|
||||
Text("LinearProgressIndicator with undefined progress")
|
||||
LinearProgressIndicator()
|
||||
Spacer(Modifier.height(30.dp))
|
||||
Text("LinearProgressIndicator with progress set by buttons")
|
||||
LinearProgressIndicator(progress = animatedProgress)
|
||||
Spacer(Modifier.height(30.dp))
|
||||
OutlinedButton(
|
||||
onClick = {
|
||||
if (progress < 1f) progress += 0.1f
|
||||
}
|
||||
) {
|
||||
Text("Increase")
|
||||
}
|
||||
|
||||
OutlinedButton(
|
||||
onClick = {
|
||||
if (progress > 0f) progress -= 0.1f
|
||||
}
|
||||
) {
|
||||
Text("Decrease")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.modalbottomsheetlayout
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
fun ModalBottomSheetSample() {
|
||||
val state = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
|
||||
val scope = rememberCoroutineScope()
|
||||
ModalBottomSheetLayout(
|
||||
sheetState = state,
|
||||
sheetContent = {
|
||||
LazyColumn {
|
||||
items(50) {
|
||||
ListItem(
|
||||
text = { Text("Item $it") },
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.Favorite,
|
||||
contentDescription = "Localized description"
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize().padding(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text("Rest of the UI")
|
||||
Spacer(Modifier.height(20.dp))
|
||||
Button(onClick = { scope.launch { state.show() } }) {
|
||||
Text("Click to show sheet")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.modaldrawer
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun ModalDrawerSample() {
|
||||
val drawerState = rememberDrawerState(DrawerValue.Closed)
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
ModalDrawer(
|
||||
drawerState = drawerState,
|
||||
drawerContent = {
|
||||
Column {
|
||||
Text("Text in Drawer")
|
||||
Button(onClick = {
|
||||
scope.launch {
|
||||
drawerState.close()
|
||||
}
|
||||
}) {
|
||||
Text("Close Drawer")
|
||||
}
|
||||
}
|
||||
},
|
||||
content = {
|
||||
Column {
|
||||
Text("Text in Bodycontext")
|
||||
Button(onClick = {
|
||||
|
||||
scope.launch {
|
||||
drawerState.open()
|
||||
}
|
||||
|
||||
}) {
|
||||
Text("Click to open")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.navigationrail
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.NavigationRail
|
||||
import androidx.compose.material.NavigationRailItem
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
enum class Page(val title:String, val content: String){
|
||||
HOME("home","Show only icon"),
|
||||
SEARCH("Search","Show icon with label"),
|
||||
SETTINGS("Settings","Show icon /Show the label only when selected")
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NavigationRailSample() {
|
||||
var selectedItem by remember { mutableStateOf(0) }
|
||||
val pages = Page.values()
|
||||
val icons = listOf(Icons.Filled.Home, Icons.Filled.Search, Icons.Filled.Settings)
|
||||
Row {
|
||||
NavigationRail {
|
||||
pages.forEachIndexed { index, item ->
|
||||
when(item){
|
||||
Page.HOME -> {
|
||||
NavigationRailItem(
|
||||
icon = { Icon(icons[index], contentDescription = "") },
|
||||
selected = selectedItem == index,
|
||||
onClick = { selectedItem = index }
|
||||
)
|
||||
}
|
||||
Page.SEARCH -> {
|
||||
NavigationRailItem(
|
||||
label = { Text(item.title) },
|
||||
icon = { Icon(icons[index], contentDescription = "") },
|
||||
selected = selectedItem == index,
|
||||
onClick = { selectedItem = index }
|
||||
)
|
||||
}
|
||||
Page.SETTINGS -> {
|
||||
NavigationRailItem(
|
||||
label = { Text(item.title) },
|
||||
icon = { Icon(icons[index], contentDescription = "") },
|
||||
selected = selectedItem == index,
|
||||
onClick = { selectedItem = index },
|
||||
alwaysShowLabel = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text(pages[selectedItem].content, Modifier.padding(start = 8.dp))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.radiobutton
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.RadioButton
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
|
||||
@Composable
|
||||
fun RadioButtonSample() {
|
||||
val radioOptions = listOf("A", "B", "C")
|
||||
val (selectedOption, onOptionSelected) = remember { mutableStateOf(radioOptions[1] ) }
|
||||
Column {
|
||||
radioOptions.forEach { text ->
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = (text == selectedOption),
|
||||
onClick = {
|
||||
onOptionSelected
|
||||
(text)
|
||||
}
|
||||
)
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
RadioButton(
|
||||
selected = (text == selectedOption),
|
||||
onClick = { onOptionSelected(text) }
|
||||
)
|
||||
Text(
|
||||
text = text,
|
||||
style = MaterialTheme.typography.body1.merge(),
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.scaffold
|
||||
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
|
||||
@Composable
|
||||
fun ScaffoldDemo() {
|
||||
val materialBlue700= Color(0xFF1976D2)
|
||||
val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Open))
|
||||
Scaffold(
|
||||
scaffoldState = scaffoldState,
|
||||
topBar = { TopAppBar(title = {Text("TopAppBar")},backgroundColor = materialBlue700) },
|
||||
floatingActionButtonPosition = FabPosition.End,
|
||||
floatingActionButton = { FloatingActionButton(onClick = {}){
|
||||
Text("X")
|
||||
} },
|
||||
drawerContent = { Text(text = "drawerContent") },
|
||||
content = {
|
||||
|
||||
Text("BodyContent") },
|
||||
bottomBar = { BottomAppBar(backgroundColor = materialBlue700) { Text("BottomAppBar") } }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
import androidx.compose.material.Slider
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
|
||||
@Composable
|
||||
fun MySliderDemo() {
|
||||
var sliderPosition by remember { mutableStateOf(0f) }
|
||||
Text(text = sliderPosition.toString())
|
||||
Slider(value = sliderPosition, onValueChange = { sliderPosition = it })
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.Snackbar
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun SnackbarDemo() {
|
||||
Column {
|
||||
val (snackbarVisibleState, setSnackBarState) = remember { mutableStateOf(false) }
|
||||
|
||||
Button(onClick = { setSnackBarState(!snackbarVisibleState) }) {
|
||||
if (snackbarVisibleState) {
|
||||
Text("Hide Snackbar")
|
||||
} else {
|
||||
Text("Show Snackbar")
|
||||
}
|
||||
}
|
||||
if (snackbarVisibleState) {
|
||||
Snackbar(
|
||||
|
||||
action = {
|
||||
Button(onClick = {}) {
|
||||
Text("MyAction")
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) { Text(text = "This is a snackbar!") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.surface
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun SurfaceDemo() {
|
||||
Surface(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
border = BorderStroke(2.dp, Color.Red),
|
||||
contentColor = Color.Blue,
|
||||
elevation = 8.dp,
|
||||
shape = CircleShape
|
||||
) {
|
||||
Text("Hello World", modifier = Modifier.padding(8.dp))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.switch
|
||||
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Switch
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
||||
|
||||
|
||||
@Composable
|
||||
fun SwitchDemo() {
|
||||
MaterialTheme {
|
||||
val checkedState = remember { mutableStateOf(true) }
|
||||
Switch(
|
||||
checked = checkedState.value,
|
||||
onCheckedChange = { checkedState.value = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.material.textfield
|
||||
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextField
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
|
||||
@Composable
|
||||
fun TextFieldDemo() {
|
||||
Column(Modifier.padding(16.dp)) {
|
||||
val textState = remember { mutableStateOf(TextFieldValue()) }
|
||||
TextField(
|
||||
value = textState.value,
|
||||
onValueChange = { textState.value = it }
|
||||
)
|
||||
Text("The textfield has this text: " + textState.value.text)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.other
|
||||
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import de.jensklingenberg.jetpackcomposeplayground.R
|
||||
|
||||
|
||||
@Composable
|
||||
fun AndroidContextComposeDemo() {
|
||||
MaterialTheme {
|
||||
val context = LocalContext.current
|
||||
Text(text = "Read this string from Context: "+context.getString(R.string.app_name))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.other
|
||||
|
||||
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.ComposableDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoCategory
|
||||
|
||||
|
||||
val OtherDemos = DemoCategory(
|
||||
"Other",
|
||||
listOf(
|
||||
ComposableDemo("TextFieldDemo") { TextFieldDemo() },
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.other
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
|
||||
|
||||
@Composable
|
||||
fun TextFieldDemo() {
|
||||
Column {
|
||||
var state = TextFieldValue("")
|
||||
BasicTextField(
|
||||
value = state,
|
||||
onValueChange = {value-> state= value }
|
||||
)
|
||||
Text("The textfield has this text: "+state)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.testing
|
||||
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
|
||||
@Composable
|
||||
fun TestingExample() {
|
||||
val state = remember { mutableStateOf("Hello") }
|
||||
Button(onClick = { state.value = "Bye" }, modifier = Modifier.testTag("MyTestTag")) {
|
||||
Text(state.value)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.ui
|
||||
|
||||
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.ComposableDemo
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.demo.DemoCategory
|
||||
import de.jensklingenberg.jetpackcomposeplayground.mysamples.github.ui.layout.SubComposeLayoutDemo
|
||||
|
||||
|
||||
val UIDemos = DemoCategory(
|
||||
"UIDemos",
|
||||
listOf(
|
||||
ComposableDemo("SubComposeLayoutDemo") { SubComposeLayoutDemo() },
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,91 @@
|
||||
package de.jensklingenberg.jetpackcomposeplayground.mysamples.github.ui.layout
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.Placeable
|
||||
import androidx.compose.ui.layout.SubcomposeLayout
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
|
||||
@Composable
|
||||
fun SubComposeLayoutDemo() {
|
||||
ResizeWidthColumn(Modifier.fillMaxWidth(), true) {
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Red)
|
||||
) {
|
||||
Text("Hello")
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.background(Color.Red)
|
||||
) {
|
||||
Text("This is a long messsage \n and its longer")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ResizeWidthColumn(modifier: Modifier, resize: Boolean, mainContent: @Composable () -> Unit) {
|
||||
SubcomposeLayout(modifier) { constraints ->
|
||||
val mainPlaceables = subcompose(SlotsEnum.Main, mainContent).map {
|
||||
// Here we measure the width/height of the child Composables
|
||||
it.measure(Constraints())
|
||||
}
|
||||
|
||||
//Here we find the max width/height of the child Composables
|
||||
val maxSize = mainPlaceables.fold(IntSize.Zero) { currentMax, placeable ->
|
||||
IntSize(
|
||||
width = maxOf(currentMax.width, placeable.width),
|
||||
height = maxOf(currentMax.height, placeable.height)
|
||||
)
|
||||
}
|
||||
|
||||
val resizedPlaceables: List<Placeable> =
|
||||
subcompose(SlotsEnum.Dependent, mainContent).map {
|
||||
if (resize) {
|
||||
/** Here we rewrite the child Composables to have the width of
|
||||
* widest Composable
|
||||
*/
|
||||
it.measure(
|
||||
Constraints(
|
||||
minWidth = maxSize.width
|
||||
)
|
||||
)
|
||||
} else {
|
||||
// Ask the child for its preferred size.
|
||||
it.measure(Constraints())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We can place the Composables on the screen
|
||||
* with layout() and the place() functions
|
||||
*/
|
||||
|
||||
layout(constraints.maxWidth, constraints.maxHeight) {
|
||||
resizedPlaceables.forEachIndexed { index, placeable ->
|
||||
val widthStart = resizedPlaceables.take(index).sumOf { it.measuredHeight }
|
||||
placeable.place(0, widthStart)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum class SlotsEnum {
|
||||
Main,
|
||||
Dependent
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp">
|
||||
<path android:fillColor="#000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
|
||||
</vector>
|
||||
|
After Width: | Height: | Size: 325 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp">
|
||||
<path android:fillColor="#000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
|
||||
</vector>
|
||||
|
After Width: | Height: | Size: 488 B |
|
After Width: | Height: | Size: 272 B |
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
~ Copyright 2019 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<vector android:height="480dp" android:viewportHeight="144"
|
||||
android:viewportWidth="144" android:width="480dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#F79D80" android:pathData="M69.26,55.73m-53.39,0a53.39,53.39 0,1 1,106.78 0a53.39,53.39 0,1 1,-106.78 0"/>
|
||||
<path android:fillColor="#37474F" android:pathData="M47.66,76.35h2.26v65.31h-2.26z"/>
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M61.47,22.88l7.59,0.63C69.06,23.51 65.07,22.59 61.47,22.88z"/>
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M78.86,44.71c-6.8,-5.5 -22.66,-7.48 -22.99,-17.32c-0.11,-3.17 2.61,-4.26 5.6,-4.5l-11.02,-0.92c-3.05,9.16 1.58,18.08 14.69,24.18c10.96,5.1 6.86,12.67 3.64,16.47c-3.13,-3.32 -7.57,-5.4 -12.49,-5.4c-0.78,0 -1.54,0.06 -2.29,0.16c-6.08,0.37 -39.94,5.23 -35.41,67.19c0,0 56.87,-40.62 56.95,-40.68c4.87,-3.48 9.11,-8.88 11.13,-14.5C89.88,60.43 86.05,50.53 78.86,44.71z"/>
|
||||
<path android:fillColor="#434343" android:pathData="M68.8,62.41c-3.13,-3.32 -7.57,-5.4 -12.49,-5.4c-0.78,0 -1.54,0.06 -2.29,0.16c-6.08,0.37 -39.94,5.23 -35.41,67.19c0,0 1.34,-0.96 3.61,-2.58c-2.04,-56.41 29.85,-60.98 35.73,-61.34c0.75,-0.1 1.51,-0.16 2.29,-0.16C65.16,60.29 66.58,61.23 68.8,62.41"/>
|
||||
<path android:fillColor="#FFD54F" android:pathData="M83.23,22.46l20.76,1.43c0.4,0.03 0.52,-0.52 0.16,-0.67l-19.1,-7.78c-0.2,-0.08 -0.42,0.03 -0.47,0.24l-1.66,6.35C82.86,22.23 83.01,22.44 83.23,22.46z"/>
|
||||
<path android:fillColor="#F9BF2C" android:pathData="M86.66,16.09l-1.62,-0.66c-0.2,-0.08 -0.42,0.03 -0.47,0.24l-1.66,6.36c-0.06,0.21 0.1,0.42 0.31,0.44l10.52,0.72L86.66,16.09z"/>
|
||||
<path android:fillColor="#1B2428" android:pathData="M47.66,103.79l0,3.86l2.24,2.24l0,-7.7z"/>
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M71.76,7.67c-5.16,-0.35 -9.83,0.75 -12.82,2.74l0,0c-7.5,4.2 -9.01,13.44 -9.18,14.36c-0.18,0.93 3.05,2.01 3.05,2.01l4.12,-4.16l4.52,-0.06c2.52,1.27 5.61,2.55 9.09,2.79c8.62,0.59 15.88,-2.89 16.22,-7.77C87.1,12.7 80.38,8.26 71.76,7.67z"/>
|
||||
<path android:fillColor="#881A51" android:pathData="M71.76,7.67c-5.16,-0.35 -9.83,0.75 -12.82,2.74l0,0c-7.5,4.2 -9.01,13.44 -9.18,14.36c-0.18,0.93 3.05,2.01 3.05,2.01l4.12,-4.16l4.67,-0.38c2.52,1.27 7.02,1.03 10.5,1.27c8.62,0.59 14.33,-1.05 14.66,-5.93C87.1,12.7 80.38,8.26 71.76,7.67z"/>
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M71.83,11.32c-5.16,-0.29 -9.83,0.61 -12.82,2.21l0,0c-7.5,3.39 -9.16,10.46 -9.25,11.23c-0.15,1.18 3.05,3.13 3.05,3.13l4.2,-4.48l4.47,-0.54c2.52,1.03 5.59,2.28 9.07,2.47c8.62,0.48 15.08,-2.54 15.41,-6.49C86.29,14.92 80.45,11.8 71.83,11.32z"/>
|
||||
<path android:fillColor="#BDBDBD" android:pathData="M73.53,24.78c-3.48,-0.19 -6.55,-1.44 -9.07,-2.47c0,0 0,0 0,0l-1.08,0.13c-0.68,0.11 -1.33,0.28 -1.91,0.52l0.11,-0.01c0,0 0,0 0,0c2.52,1.03 5.59,2.28 9.07,2.47c3.37,0.19 6.4,-0.16 8.87,-0.89C77.7,24.8 75.68,24.9 73.53,24.78z"/>
|
||||
<path android:fillColor="#EEEEEE" android:pathData="M82.13,48.13c1.75,4.57 2.05,9.63 0.33,14.43c-2.02,5.62 -6.26,11.01 -11.13,14.5c-0.33,0.24 -41.01,29.29 -53.34,38.1c0.03,2.98 0.16,6.12 0.41,9.41c0,0 56.87,-40.62 56.95,-40.68c4.87,-3.48 9.11,-8.88 11.13,-14.5C89.13,62.01 86.99,53.98 82.13,48.13z"/>
|
||||
<path android:fillColor="#BDBDBD" android:pathData="M78.86,44.91c-0.16,-0.13 -0.33,-0.26 -0.5,-0.39c5.68,5.93 8.39,14.63 5.53,22.58c-2.02,5.62 -6.26,11.01 -11.13,14.5c-0.07,0.05 -43.58,31.16 -54.59,39.02c0.06,1.4 0.15,2.8 0.26,4.26c0,0 57.03,-40.74 57.11,-40.79c4.87,-3.48 9.11,-8.88 11.13,-14.5C89.88,60.64 86.05,50.73 78.86,44.91z"/>
|
||||
<path android:fillColor="#BDBDBD" android:pathData="M78.94,44.76c-6.8,-5.5 -22.66,-7.48 -22.99,-17.32c-0.04,-1.21 0.33,-2.11 0.97,-2.78c-1.81,0.6 -3.12,1.8 -3.04,4.02C54.2,38.52 70.07,40.5 76.86,46c7.19,5.82 11.02,15.73 7.81,24.68c-2.02,5.62 -6.26,11.01 -11.13,14.5c-0.07,0.05 -44.69,31.92 -54.89,39.21c0.01,0.08 0.01,0.16 0.02,0.24c0,0 56.87,-40.62 56.95,-40.68c4.87,-3.48 9.11,-8.88 11.13,-14.5C89.96,60.49 86.13,50.59 78.94,44.76z"/>
|
||||
<path android:fillColor="#BDBDBD" android:pathData="M54.5,28.8c0,0 -0.52,0.61 -0.52,0.61c0.01,-0.01 -0.02,-0.11 -0.02,-0.12c-0.02,-0.11 -0.03,-0.23 -0.05,-0.34c-0.04,-0.4 -0.06,-0.79 -0.04,-1.19c0.02,-0.55 0.1,-1.1 0.24,-1.64c0.17,-0.63 0.43,-1.24 0.78,-1.79c0.42,-0.65 0.96,-1.21 1.58,-1.66c0.32,-0.23 0.66,-0.43 1.01,-0.61c0.47,-0.24 0.93,-0.43 1.46,-0.49c0.27,-0.03 0.55,-0.05 0.82,-0.05c0.89,-0.02 1.78,0.07 2.65,0.24c0.37,0.07 0.73,0.16 1.09,0.26c0.19,0.05 0.39,0.11 0.58,0.17c0.1,0.03 0.2,0.07 0.3,0.1c0.04,0.01 0.27,0.13 0.3,0.11c0,0 -1.79,1.07 -1.79,1.07s-5.78,-1.34 -6.91,3.25L54.5,28.8z"/>
|
||||
</vector>
|
||||
|
After Width: | Height: | Size: 385 B |
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright 2019 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24" >
|
||||
<group
|
||||
android:name="hourglass_frame"
|
||||
android:translateX="12"
|
||||
android:translateY="12"
|
||||
android:scaleX="0.75"
|
||||
android:scaleY="0.75" >
|
||||
<group
|
||||
android:name="hourglass_frame_pivot"
|
||||
android:translateX="-12"
|
||||
android:translateY="-12" >
|
||||
<group
|
||||
android:name="group_2_2"
|
||||
android:translateX="12"
|
||||
android:translateY="6.5" >
|
||||
<path
|
||||
android:name="path_2_2"
|
||||
android:pathData="M 6.52099609375 -3.89300537109 c 0.0 0.0 -6.52099609375 6.87901306152 -6.52099609375 6.87901306152 c 0 0.0 -6.52099609375 -6.87901306152 -6.52099609375 -6.87901306152 c 0.0 0.0 13.0419921875 0.0 13.0419921875 0.0 Z M 9.99800109863 -6.5 c 0.0 0.0 -19.9960021973 0.0 -19.9960021973 0.0 c -0.890991210938 0.0 -1.33700561523 1.07699584961 -0.707000732422 1.70700073242 c 0.0 0.0 10.7050018311 11.2929992676 10.7050018311 11.2929992676 c 0 0.0 10.7050018311 -11.2929992676 10.7050018311 -11.2929992676 c 0.630004882812 -0.630004882812 0.183990478516 -1.70700073242 -0.707000732422 -1.70700073242 Z"
|
||||
android:fillColor="#FF777777" />
|
||||
</group>
|
||||
<group
|
||||
android:name="group_1_2"
|
||||
android:translateX="12"
|
||||
android:translateY="17.5" >
|
||||
<path
|
||||
android:name="path_2_1"
|
||||
android:pathData="M 0 -2.98600769043 c 0 0.0 6.52099609375 6.87901306152 6.52099609375 6.87901306152 c 0.0 0.0 -13.0419921875 0.0 -13.0419921875 0.0 c 0.0 0.0 6.52099609375 -6.87901306152 6.52099609375 -6.87901306152 Z M 0 -6.5 c 0 0.0 -10.7050018311 11.2929992676 -10.7050018311 11.2929992676 c -0.630004882812 0.630004882812 -0.184005737305 1.70700073242 0.707000732422 1.70700073242 c 0.0 0.0 19.9960021973 0.0 19.9960021973 0.0 c 0.890991210938 0.0 1.33699035645 -1.07699584961 0.707000732422 -1.70700073242 c 0.0 0.0 -10.7050018311 -11.2929992676 -10.7050018311 -11.2929992676 Z"
|
||||
android:fillColor="#FF777777" />
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
<group
|
||||
android:name="fill_outlines"
|
||||
android:translateX="12"
|
||||
android:translateY="12"
|
||||
android:scaleX="0.75"
|
||||
android:scaleY="0.75" >
|
||||
<group
|
||||
android:name="fill_outlines_pivot"
|
||||
android:translateX="-12"
|
||||
android:translateY="-12" >
|
||||
<clip-path
|
||||
android:name="mask_1"
|
||||
android:pathData="M 24 13.3999938965 c 0 0.0 -24 0.0 -24 0.0 c 0 0.0 0 10.6000061035 0 10.6000061035 c 0 0 24 0 24 0 c 0 0 0 -10.6000061035 0 -10.6000061035 Z" />
|
||||
<group
|
||||
android:name="group_1_3"
|
||||
android:translateX="12"
|
||||
android:translateY="12" >
|
||||
<path
|
||||
android:name="path_1_6"
|
||||
android:pathData="M 10.7100067139 10.2900085449 c 0.629989624023 0.629989624023 0.179992675781 1.70999145508 -0.710006713867 1.70999145508 c 0 0 -20 0 -20 0 c -0.889999389648 0 -1.33999633789 -1.08000183105 -0.710006713867 -1.70999145508 c 0.0 0.0 9.76000976562 -10.2900085449 9.76000976563 -10.2900085449 c 0.0 0 -9.76000976562 -10.2899932861 -9.76000976563 -10.2899932861 c -0.629989624023 -0.630004882812 -0.179992675781 -1.71000671387 0.710006713867 -1.71000671387 c 0 0 20 0 20 0 c 0.889999389648 0 1.33999633789 1.08000183105 0.710006713867 1.71000671387 c 0.0 0.0 -9.76000976562 10.2899932861 -9.76000976563 10.2899932861 c 0.0 0 9.76000976562 10.2900085449 9.76000976563 10.2900085449 Z"
|
||||
android:fillColor="#FF777777" />
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="108dp"
|
||||
android:width="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
</vector>
|
||||
|
After Width: | Height: | Size: 894 B |
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="#20000000">
|
||||
<item android:drawable="@drawable/ripple_shape" />
|
||||
<item android:id="@android:id/mask"
|
||||
android:drawable="@drawable/ripple_shape" />
|
||||
</ripple>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="100px"/>
|
||||
<solid android:color="@android:color/white"/>
|
||||
<stroke android:color="#80000000" android:width="1dp"/>
|
||||
</shape>
|
||||
@@ -0,0 +1 @@
|
||||
This is a dummy font file used for sample code.
|
||||
@@ -0,0 +1 @@
|
||||
This is a dummy font file used for sample code.
|
||||
@@ -0,0 +1 @@
|
||||
This is a dummy font file used for sample code.
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/container"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/button1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="AndroidX Samples" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="My Samples" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 10 KiB |