Mobile Apps 2023W Tutorial 1

From Soma-notes

Tasks

  1. Put the app title at the top of the screen and the analysis menu at the bottom. Leave the rest centered.
  2. Add in two new analysis modes, one to count numeric characters, one of your choice.
  3. Make the result area bold and with a slightly larger text.
  4. Make the app remember its state when rotated.

Code

MainActivity.kt

package carleton.comp2601.textanalyzer7

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlin.reflect.KFunction1
import carleton.comp2601.textanalyzer7.ui.theme.TextAnalyzer7Theme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TextAnalyzer7Theme {
                // A surface container using the 'background' color from the theme
                MainScreen()
            }
        }
    }
}

@Composable
fun MainScreen() {
    var t by remember {
        mutableStateOf("")
    }

    var analysisMode by remember {
        mutableStateOf("Count")
    }

    var showMenu by remember {
        mutableStateOf(false)
    }

    val analysisFunc: KFunction1<String, String>? = analysis[analysisMode]
    var r = ""
    if (analysisFunc != null) {
        r = analysisFunc(t)
    }

    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colors.background
    ) {
        Column (
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally,
                ){
            Text("Text Analyzer 7",
                fontWeight = FontWeight.Bold,
                textAlign = TextAlign.Center,
                fontSize = 48.sp,
                modifier = Modifier.padding(bottom = 64.dp))
            TextField(value = t,
                onValueChange = { t = it },
                label = { Text("Enter Text") })
            Text(analysisMode + ": " + r,
                modifier = Modifier.padding(32.dp))
            Box {
                Button(
                    modifier = Modifier.padding(top = 32.dp),
                    onClick = {
                        showMenu = true
                    }) {
                    Text(text = "Analysis Menu")
                }
                ModeMenu(showMenu = showMenu,
                    updateMode = { analysisMode = it },
                    hideMenu = { showMenu = false })
            }
        }
    }
}

@Composable
fun ModeMenu(showMenu: Boolean,
             updateMode:(String)->Unit,
             hideMenu:()->Unit) {

    DropdownMenu(
        expanded = showMenu,
        onDismissRequest = { hideMenu() }
    ) {
        analysis.keys.forEach { mode ->
            DropdownMenuItem(onClick = {
                updateMode(mode)
                hideMenu()
            }) {
                Text(text = mode)
            }
        }
    }
}

fun countUpper(s: String): String {
    var count = 0
    val upperCase = setOf("A","B","C","D","E","F","G","H","I","J","K","L","M",
        "N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
    for (c in s) {
        if (upperCase.contains(c.toString())) {
            count += 1
        }
    }
    return count.toString()
}

fun countCharacters(s: String): String {
    val charcount = s.length
    return charcount.toString()
}

val analysis: MutableMap<String, KFunction1<String, String>> = mutableMapOf(
    "Count" to ::countCharacters,
    "Upper Case" to ::countUpper
)

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    TextAnalyzer7Theme {
        MainScreen()
    }
}