/* 2023-07-15 File created by Kari Laitinen (c) naturalprogramming.com 2023-07-20 Modifications for Material 3. This example demonstrates - using a Slider - drawing a Path on Canvas: rotation, scaling, transforming This is an Android app made of this single file. If you want to test this app, create an Android Compose project with project name TurningArrowC and the package name shown below. Then, store this file to the folder where MainActivity.kt is and make the following change to AndroidManifest.xml: android:name=".TurningArrowCActivity" Imports may need to be modified if a new Android/Compose version is used. Some 'warnings': - tab size in this file is 3 spaces - underscores may be used in the names invented by the programmer */ package turning.arrowc import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Path import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.unit.dp import turning.arrowc.ui.theme.TurningArrowCTheme import androidx.compose.ui.graphics.drawscope.* class TurningArrowCActivity : ComponentActivity() { var upwards_arrow = Path() override fun onCreate(savedInstanceState : Bundle?) { super.onCreate( savedInstanceState ) // The arrow coordinates are selected so that Point (0, 0) // is in the middle of the arrow, and the arrow points upwards. upwards_arrow.moveTo( 0F, -192F ) // to the tip of the arrow upwards_arrow.lineTo( 128F, 0F ) upwards_arrow.lineTo( 64F, 0F ) upwards_arrow.lineTo( 64F, 192F ) upwards_arrow.lineTo( -64F, 192F ) // make the bottom line upwards_arrow.lineTo( -64F, 0F ) upwards_arrow.lineTo( -128F, 0F ) upwards_arrow.close() val arrow_height = 2 * 192F setContent { TurningArrowCTheme { // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), color = Color( 0xFFF7F7F7 ) ) { val configuration = LocalConfiguration.current //val context = LocalContext.current //val screen_height = configuration.screenHeightDp.dp val screenWidth = configuration.screenWidthDp.dp var arrow_angle = remember { mutableStateOf(0F ) } var outline_stroke_width = remember { mutableStateOf(4F ) } Column( horizontalAlignment = Alignment.CenterHorizontally ) { // With a Box we can put Text and Canvas to the // same area on the screen. Box( modifier = Modifier .requiredWidth(screenWidth) .weight(8F) ) { // As the area reserved for Canvas is now determined // by the Box, we can just fill all that area. Canvas( modifier = Modifier.fillMaxSize() ) { //val canvasSize = size val canvasWidth = size.width val canvasHeight = size.height // We will scale the arrow so that it fits nicely on the canvas. val scaling = canvasWidth / arrow_height * 0.8F rotate( arrow_angle.value ) { scale( scaling, scaling ) { translate(canvasWidth / 2, canvasHeight / 2) { drawPath( upwards_arrow, Color.Yellow ) drawPath( path = upwards_arrow, color = Color.Red, style = Stroke(width = outline_stroke_width.value) ) } } } } } // end Box Box( modifier = Modifier .requiredWidth(screenWidth) .weight(1F) ) { Slider( value = arrow_angle.value, onValueChange = { arrow_angle.value = it outline_stroke_width.value = 8F }, valueRange = -90F .. 90F, onValueChangeFinished = { outline_stroke_width.value = 4F }, colors = SliderDefaults.colors( thumbColor = Color.Blue, activeTrackColor = Color.Gray ) ) } } // end Column } } } } }