得到
This commit is contained in:
@@ -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, doesn’t it? Let’s 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 don’t 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, it’s 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)
|
||||
Reference in New Issue
Block a user