To Lecture Notes

IT 372 -- May 27, 2026

Review Exercises

  1. Set up a demonstration JPC app with a Button element and a state variable defined by
    var buttonCaption = remember { mutableStateOf("") }
    
    Show how to change = to by in this statement; in particular, how to set up the getter and setter for textValue. Answer: we used this MainLayout as an example:
    @Composable
    fun MainLayout( ) {
    
        var buttonCaption by remember { mutableStateOf("Click Me") }
    
        Column(modifier = Modifier
            .padding(all = 40.dp)
            .background(color = Color(0xFFFFA0A0))
            .fillMaxSize( ))
         {
            Button(onClick = {
                buttonCaption = "I\'ve been clicked."
            }) {
                Text(text = buttonCaption)
            }
        }
    }
    
    To set up the getter and setter for buttonCaption, hover over the by keyword after changing it from =; in the dialog window that comes up, click on
    Import operator 'State getValue"
    
    Hover over the by keyword agein; this time click on
    Import operator 'MutableState.setValue'
    
  2. Show that using
    modifier = Modifier
        .padding(all=40.dp)
        .background(color = Color(0xFFC0C0C0))
    
    to style a Column element gives a different result than using
    modifier = Modifier
        .background(color = Color(0xFFC0C0C0))
        .padding(all=40.dp)
    
    In the first case, the background color starts inside the padding, but in the second case, the background color starts inside the padding.
  3. How do you write to and read from an internal file on the emulator or device? Consider the two cases of reading the entire file into a string and reading the file line by line. Also consider the two cases of overwriting the file the file or appending to the file. Answer: we came up with this example.
    @Composable
    fun MainLayout( ) {
    
        var display = remember { mutableStateOf("Start value") }
        var context = LocalContext.current
    
        Column(modifier = Modifier
            .padding(all = 40.dp)) {
    
            Button(onClick = {
                val fileName = "testfile.txt"
                val dataToWrite = "Hello, World!"
                val file = File(context.filesDir, fileName)
                FileOutputStream(file).use {
                    it.write(dataToWrite.toByteArray( ))
                }
            }, modifier = Modifier.padding(all = 40.dp)) {
                Text(text = "Write to File", fontSize = 25.sp)
            }
    
            Button(onClick = {
                val fileName = "testfile.txt"
                val file = File(context.filesDir, fileName)
                val inputStream = file.inputStream( )
                inputStream.bufferedReader( ).use {
                    display.value = it.readText( )
                }
            }, modifier = Modifier.padding(all = 40.dp)) {
                Text(text = "Read from File", fontSize = 25.sp)
            }
    
            Text(text = display.value, fontSize = 25.sp,
                modifier = Modifier.background(Color(0xFFB0B0B0)))
        }
    }
    
    We ran into an error when the filename in the first button was defined as "testfile.txt", but defined as "textfile.txt" in the second button. We could have prevented this by defining fileName once above the Column in MainLayout.
  4. Modify the TouchPoint Example to draw multiple circles positioned by touch points on a canvas. Store the locations of the points in a MutableStateList of Offset objects. Answer: here is the MainLayout function.
    @Composable
    fun MainLayout( ) {
        
        // Use a mutableStateList to hold the circle centers:
        var circles = remember { mutableStateOf<Offset>( ) }
    
        Column(modifier = Modifier
            .background(Color(0xFFC0C0C0))
            .padding(all = 30.dp)) {
            Canvas(
                modifier = Modifier
                    .fillMaxSize()
                    .background(Color.White)
                    .pointerInput(Unit) {
                        // Detects individual tap events on the screen
                        detectTapGestures(
                            onTap = {
                                circles.add(it)
                            }
                        )
                    }
            ) {
                // Draw the point only if the user has tapped
                // the screen
                circles.forEach {
                    drawCircle(
                        color = Color.Blue,
                        radius = 30f,
                        center = it
                    )
                }
            }
        }
    }
    
  5. Set up this trianglePath state variable:
    val trianglePath = remember {
        Path().apply {
            moveTo(600f, 400f)
            lineTo(600f, 800f)
            lineTo(200f, 900f)
            close()
        }
    }
    
    Then define this Canvas element that draws a filled triangle:
    Canvas(modifier = Modifier.fillMaxSize()) {
        drawPath(
            path = trianglePath,
            color = Color.Blue
        )
    }
    
    Modify the Exercise 3 to draw a polygon using touch events. Answer: here is the MainLayout function:
    @Composable
    fun MainLayout( ) {
    
        // Keep track of the vertices of the polygon:
        var points = remember { mutableStateListOf<Offset>( ) }
    
        var polygonPath = Path( ).apply {
            if (points.isNotEmpty( )) {
                moveTo(points.first( ).x, points.first( ).y)
                for (i in 1 until points.size) {
                    lineTo(points[i].x, points[i].y)
                }
                close( )
            }
        }
    
        Column(modifier = Modifier
            .background(Color(0xFFC0C0C0))
            .padding(all = 30.dp)) {
    
            Button(onClick = {
                points.clear( )
            }) {
                Text(text = "Clear",
                    fontSize = 25.sp)
            }
    
            Canvas(
                modifier = Modifier
                    .fillMaxSize()
                    .background(Color.White)
                    .pointerInput(Unit) {
                        // Detects individual tap events on the screen
                        detectTapGestures(
                            onTap = {
                                points.add(it)
                            }
                        )
                    }
            ) {
                // Draw the point only if the user has tapped
                // the screen
                drawPath(
                    path = polygonPath,
                    color = Color.Blue,
                    style = Stroke(width = 10f)
                )
            }
        }
    }
    
    

JetPack Compose Examples