This commit is contained in:
coco
2026-07-15 16:57:36 +08:00
parent 723ce1af5c
commit 95aa018b8b
314 changed files with 8910 additions and 0 deletions
@@ -0,0 +1,14 @@
# How to detect dark mode
Inside your Composable you can use **isSystemInDarkTheme** to detect if the device is running in dark mode.
```kotlin
val dark = isSystemInDarkTheme()
```
-------------
## See also:
* [Official Docs](https://developer.android.com/reference/kotlin/androidx/compose/foundation/package-summary#issystemindarktheme)
* [Learn-Jetpack-Compose-By-Example/DarkModeActivity](https://github.com/vinaygaba/Learn-Jetpack-Compose-By-Example/blob/master/app/src/main/java/com/example/jetpackcompose/theme/DarkModeActivity.kt)
@@ -0,0 +1,16 @@
<!---
This is the API of version 1.2.0
-->
You can use LocalContext.current to receive the context of your Android App inside a Compose Function
```kotlin
@Composable
fun AndroidContextComposeDemo() {
val context = LocalContext.current
Text(text = "Read this string from Context: "+context.getString(R.string.app_name))
}
```
## See also:
* [Full Example Code]({{ site.samplefolder }}/other/AndroidContextComposeDemo.kt)
@@ -0,0 +1,84 @@
# How to show hint with underline in a TextField
!!! info
This is the API of version dev08. Newer versions may have a different one
We have all used EditText in classic Android development. It has lots of features like hint showing or default underline background. In Jetpack compose it's name is TextField
and we set up it like that.
## Create TextField
```kotlin
val state = state { "" }
TextField(
value = state.value,
modifier = modifier,
onValueChange = { state.value = it },
textStyle = yourTextStyle
)
```
With textStyle parameter you can change your TextField's font, font size, color and many other things, but there are something that its missing, you cant quite set its PlaceHolder
text(Hint). So how can we do that? If you think about that hint's only purpose is to be shown when TextField is empty and be hidden when we are starting to type something in TextField.
So we need two views one Text for hint showing and one TextField. They must have same location on the screen so it will look like same component. So without further ado let's start
implementing it.
## Create HintTextField
```kotlin
@Composable
fun HintEditText(
hintText: String = "",
modifier: Modifier = Modifier.None,
textStyle: TextStyle = currentTextStyle()
) {
val state = state { "" }
val inputField = @Composable {
TextField(
value = state.value,
modifier = modifier,
onValueChange = { state.value = it },
textStyle = textStyle.merge(TextStyle(textDecoration = TextDecoration.None))
)
}
Layout(
children = @Composable {
inputField()
Text(
text = hintText,
modifier = modifier,
style = textStyle.merge(TextStyle(color = Color.Gray))
)
Divider(color = Color.Black, height = 2.dp)
},
measureBlock = { measurables: List<Measurable>, constraints: Constraints, _ ->
val inputFieldPlace = measurables[0].measure(constraints)
val hintEditPlace = measurables[1].measure(constraints)
val dividerEditPlace = measurables[2].measure(
Constraints(constraints.minWidth, constraints.maxWidth, 2.ipx, 2.ipx)
)
layout(
inputFieldPlace.width,
inputFieldPlace.height + dividerEditPlace.height
) {
inputFieldPlace.place(0.ipx, 0.ipx)
if (state.value.isEmpty())
hintEditPlace.place(0.ipx, 0.ipx)
dividerEditPlace.place(0.ipx, inputFieldPlace.height)
}
})
}
```
Seems like lots of code for simple functional, doesnt it? Lets describe whats happening from the function declaration. It has three function parameters and they are pretty
self-explanatory. As second part we are creating TextField lambda and passing it in Layout Composable function, with our HintText and Divider, which as you might have guessed
will create underline background. Now it's time to decide where we are going to put our HintTextField.
First of all we need to measure our views and **measureBlock** will help us do that.
Measurables list will contain three items(Our TextField, HintText and Divider) as Measurable type, we need to call measure on all of list items and pass constraints in it. Constraints
is a class which only has four properties(minWidth, maxWidth, minHeight, maxHeight). We can pass constraints which is given to us by measuring @Composable children lambda, which works
with our TextField and HintText because we want them to have same size as it's parent, but when it comes to underline background we need it to stay as thin as possible.
Now we are measuring our HintTextField one more time and placing it's children on some (x, y).
One last thing to realize is that if our state value is not empty we dont place
our HintText at all!
@@ -0,0 +1,83 @@
## How to draw a custom shape?
!!! info
This is the API of version 1.2.0. Newer versions may have a different one
<p align="center">
<img src ="../../images/foundation/shape/triangleshape.png" />
</p>
### GenericShape
You can create custom shapes. One way to do it, is to use **GenericShape**. Let's see how the triangle is drawn.
```kotlin
private val TriangleShape = GenericShape { size, _ ->
// 1)
moveTo(size.width / 2f, 0f)
// 2)
lineTo(size.width, size.height)
// 3)
lineTo(0f, size.height)
}
```
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** and the width with **size.width**
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 implicitly execute the **close()**-function. **close()** will draw a line from the last painter coordinates to the first definied.
### Extend the Shape interface
```kotlin
/**
* Defines a generic shape.
*/
interface Shape {
/**
/**
* Creates [Outline] of this shape for the given [size].
*
* @param size the size of the shape boundary.
* @param density the current density of the screen.
*
* @return [Outline] of this shape for the given [size].
*/
fun createOutline(size: Size, density: Density): Outline
}
```
You can extend the Shape interface to create your own implementation of Shape. Inside **createOutline** you get the size of the Composable, which the shape is applied to and the density of the screen.
You have to return an instance of **Outline**. Outline is a sealed class with the following subclasses:
* Rectangle(val rect: Rect)
* Rounded(val rrect: RRect)
* Generic(val path: Path)
Take a look at the GenericShape example when you want to understand, how the drawing of a custom shape works.
```kotlin
class CustomShape : Shape {
override fun createOutline(size: Size, 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,54 @@
# How to create your own Modifier
!!! info
This is the API of version alpha01. Newer versions may have a different one
Compose is using Modifiers to set certain aspects of a Composable like backgrounds, size or click events.
Compose already comes with
In this example i want to explain how you can create your own Modifier.
We will create a Modifier that scales the size of the Composable where it's applied to.
To create a Modifier you need to create a class that implements Modifier.Element.
```kotlin
/**
* A [Modifier.Element] that changes how its wrapped content is measured and laid out.
* It has the same measurement and layout functionality as the [androidx.compose.ui.Layout]
* component, while wrapping exactly one layout due to it being a modifier. In contrast,
* the [androidx.compose.ui.Layout] component is used to define the layout behavior of
* multiple children.
*
* @see androidx.compose.ui.Layout
*/
interface LayoutModifier : Modifier.Element {
```
```kotlin
class ScaleSizeModifier(val scale: Int) : LayoutModifier {
//1
override fun MeasureScope.measure(
measurable: Measurable,
constraints: Constraints
): MeasureScope.MeasureResult {
val pl = measurable.measure(constraints)
measurable.measure(
Constraints(
pl.width * scale,
pl.width * scale,
pl.height * scale,
pl.height * scale
)
)
return layout(pl.width, pl.height) {
pl.place(0, 0)
}
}
}
```
@@ -0,0 +1,3 @@
# How to make a Composable invisible?
When you want to set a Composable to invisible, you can use the **alpha** modifier. **alpha(0f)** will make it invisible.
@@ -0,0 +1,3 @@
# How to use an Android View in Compose
See [AndroidView](../viewinterop/androidview.md)
@@ -0,0 +1,3 @@
# How to use Compose in a ViewGroup
See [ComposeView](../platform/composeview.md)
@@ -0,0 +1,36 @@
<!---
This is the API of version 1.2.0
-->
# How to load an image
## Load Image
You can use **painterResource** to load an image from the resources
```kotlin
@Composable
fun ImageResourceDemo() {
val image: Painter = painterResource(id = R.drawable.composelogo)
Image(painter = image,contentDescription = "")
}
```
Or load an Icon from Material Icons
```kotlin
@Composable
fun ImageResourceDemo() {
Icon(Icons.Rounded.Home,contentDescription = "")
}
```
Remember to add dependencies to build.gradle
```
implementation "androidx.compose.material:material-icons-extended:$compose_version"
```
<hr>
## See also:
* [Full Example Code]({{ site.samplefolder }}/foundation/ImageResourceDemo.kt)
@@ -0,0 +1,10 @@
# Cookbook
* [Handle changes to a text field](./textfield_changes.md)
* [How to use Compose in a ViewGroup](./how_to_use_compose_in_viewgroup.md)
* [How to create HintTextField](./hint_edit_text.md)
* [How to load an Image](./loadimage.md)
* [How to use an Android View in Compose](./how_to_use_an_android_view_in_compose.md)
* [How to get Android Context](./get_android_context.md)
* [How to detect dark mode](./detect_darkmode.md)
* [How to make a Composable invisible?](./how_to_make_composable_invisible.md)
@@ -0,0 +1,35 @@
<!---
This is the API of version 1.2.0
-->
# Handle changes to a TextField
In some cases, its useful to get the value of a textfield every time the text in a text field changes. For example, you might want to build a search screen with autocomplete functionality where you want to update the results as the user types.
Here is an example how you can do it with Compose:
<p align="left">
<img src ="../../images/TextFieldDemo.png" />
</p>
```kotlin
@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)
}
}
```
The simplest approach is to supply an onValueChange() callback to a TextField. Whenever the text changes, the callback is invoked.
In this example, every time the TextField changes, the new text value will be saved in a state and set to the TextField and the Text.
## See also:
* [Full Example Code]({{ site.samplefolder }}/material/textfield/TextFieldDemo.kt)