Anul 3 Semestrul 1

This commit is contained in:
2025-02-06 20:33:26 +02:00
parent 0b130ee18c
commit 184f3bd92e
313 changed files with 348499 additions and 0 deletions
@@ -0,0 +1 @@
/build
@@ -0,0 +1,59 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}
android {
namespace = "com.example.ma_ui_native"
compileSdk = 34
defaultConfig {
applicationId = "com.example.ma_ui_native"
minSdk = 34
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -0,0 +1,24 @@
package com.example.ma_ui_native
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.ma_ui_native", appContext.packageName)
}
}
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MAUINative"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.MAUINative">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:exported="true"
android:theme="@style/Theme.MAUINative">
</activity>
</application>
</manifest>
@@ -0,0 +1,15 @@
package com.example.ma_ui_native
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
data class Drug(
var Id: Int = -1,
var Name: String = "",
var Category: String = "",
var NumberOfUnits: Int = 0,
var RetailPrice: Double = 0.0,
var Manufacturer: String = ""
){
}
@@ -0,0 +1,5 @@
package com.example.ma_ui_native;
public class DrugViewModel {
}
@@ -0,0 +1,300 @@
package com.example.ma_ui_native
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.example.ma_ui_native.ui.theme.MAUINativeTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
MAUINativeTheme {
val openDialog = remember { mutableStateOf(false) }
val dialogId = remember { mutableStateOf(-1) }
if(openDialog.value){
DeleteDialog(
dialogId.value,
onConfirm = {
Service.DeleteDrug(dialogId.value)
openDialog.value = false
},
onDismiss = {
openDialog.value = false
}
)
}
DrugList({
openDialog.value = true
dialogId.value = it
})
Column(
modifier = Modifier
.padding(48.dp)
.fillMaxSize(),
verticalArrangement = Arrangement.Bottom,
horizontalAlignment = Alignment.End,
) {
val context = LocalContext.current
FAB(onClick = {
context.startActivity(Intent(context, SecondActivity::class.java))
})
}
}
}
}
}
@Composable
fun FAB(onClick: () -> Unit) {
FloatingActionButton(
onClick = { onClick() },
shape = CircleShape,
contentColor = MaterialTheme.colorScheme.onPrimary,
containerColor = MaterialTheme.colorScheme.primary,
) {
Icon(Icons.Outlined.Edit, "Floating action button.")
}
}
@Composable
fun DrugList(onDelete: (Int) -> Unit){
LazyColumn(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface)
.padding(top = 75.5.dp, bottom = 23.5.dp, start = 26.dp, end = 26.dp)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy((10.dp))
){
items(
Service.GetDrugs(),
key = { it.value.Id},
){
DrugDisplay(it.value, onDelete)
}
}
}
@Composable
fun DrugDisplay(drug: Drug, onDelete: (Int) -> Unit){
Box {
Box(
modifier = Modifier
.matchParentSize()
.background(MaterialTheme.colorScheme.surface, RoundedCornerShape((12.dp)))
.border(1.dp, MaterialTheme.colorScheme.outlineVariant, RoundedCornerShape(12.dp))
)
Column(
modifier = Modifier
.fillMaxSize()
) {
Row(
modifier = Modifier
.padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 7.dp)
.fillMaxWidth()
.height(44.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(drug.Name, color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.bodyLarge)
Text(drug.Manufacturer, color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyMedium)
}
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
val context = LocalContext.current
Button(
onClick = { GoToUpdate(drug.Id, context) },
colors = ButtonColors(
MaterialTheme.colorScheme.surface,
MaterialTheme.colorScheme.primary,
MaterialTheme.colorScheme.surface,
MaterialTheme.colorScheme.primary
),
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline)
) {
Text("Edit")
}
Button(
onClick = { onDelete(drug.Id) },
colors = ButtonColors(
MaterialTheme.colorScheme.primary,
MaterialTheme.colorScheme.onPrimary,
MaterialTheme.colorScheme.primary,
MaterialTheme.colorScheme.onPrimary
),
) {
Text("Delete")
}
}
}
HorizontalDivider(
modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 7.dp)
)
Row(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 7.dp)
.shadow(2.dp, shape = RoundedCornerShape(12.dp))
.fillMaxWidth()
.height(44.dp)
.background(MaterialTheme.colorScheme.surfaceContainer, shape = RoundedCornerShape(12.dp))
) {
Box(
modifier = Modifier
.fillMaxHeight()
.background(MaterialTheme.colorScheme.primary, shape = RoundedCornerShape(topStart = 12.dp, bottomStart = 12.dp))
.fillMaxWidth(0.38f),
) {
Text("Category:", color = MaterialTheme.colorScheme.onPrimary, modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.titleSmall)
}
Box(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(0.62f),
) {
Text(drug.Category, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.bodyMedium)
}
}
Row(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 7.dp)
.shadow(2.dp, shape = RoundedCornerShape(12.dp))
.fillMaxWidth()
.height(44.dp)
.background(MaterialTheme.colorScheme.surfaceContainer, shape = RoundedCornerShape(12.dp))
) {
Box(
modifier = Modifier
.fillMaxHeight()
.background(MaterialTheme.colorScheme.primary, shape = RoundedCornerShape(topStart = 12.dp, bottomStart = 12.dp))
.fillMaxWidth(0.38f),
) {
Text("# of Units:", color = MaterialTheme.colorScheme.onPrimary, modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.titleSmall)
}
Box(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(0.62f),
) {
Text(drug.NumberOfUnits.toString(), color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.bodyMedium)
}
}
Row(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 40.dp)
.shadow(2.dp, shape = RoundedCornerShape(12.dp))
.fillMaxWidth()
.height(44.dp)
.background(MaterialTheme.colorScheme.surfaceContainer, shape = RoundedCornerShape(12.dp))
) {
Box(
modifier = Modifier
.fillMaxHeight()
.background(MaterialTheme.colorScheme.primary, shape = RoundedCornerShape(topStart = 12.dp, bottomStart = 12.dp))
.fillMaxWidth(0.38f),
) {
Text("Price:", color = MaterialTheme.colorScheme.onPrimary, modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.titleSmall)
}
Box(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(0.62f),
) {
Text("$%.2f".format(drug.RetailPrice), color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.bodyMedium)
}
}
}
}
}
fun GoToUpdate(id: Int, context: Context){
Log.d("Update", "Update for %d was clicked".format(id))
val bundle = Bundle()
bundle.putInt("id", id)
val intend = Intent(context, SecondActivity::class.java)
intend.putExtras(bundle)
context.startActivity(intend)
}
@Composable
fun DeleteDialog(id: Int, onConfirm: () -> Unit, onDismiss: () -> Unit) {
AlertDialog(
onDismissRequest = {
onDismiss()
},
title = {
Text("Delete Drug")
},
text = {
Text("Are you sure you want to delete this drug? This action can not be reversed")
},
confirmButton = {
Button(
onClick = {
onConfirm()
}
) {
Text("Delete")
}
},
dismissButton = {
Button(
onClick = {
onDismiss()
}
) {
Text("Cancel")
}
}
)
}
@@ -0,0 +1,273 @@
package com.example.ma_ui_native
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import com.example.ma_ui_native.ui.theme.MAUINativeTheme
class SecondActivity : ComponentActivity() {
private var drug = Drug()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(intent.hasExtra("id")) {
val id = intent.getIntExtra("id", -1)
if(id != -1) {
drug = Service.GetDrug(id)
}
}
enableEdgeToEdge()
setContent {
MAUINativeTheme {
Column (
modifier = Modifier
.background(MaterialTheme.colorScheme.surface)
.padding(top = 63.dp, start = 62.dp, end = 62.dp, bottom = 73.dp)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
)
{
Row(
modifier = Modifier
.padding(bottom = 25.dp, start = 61.dp, end = 61.dp)
.fillMaxWidth()
.height(49.dp)
.border(
1.dp,
color = MaterialTheme.colorScheme.outlineVariant,
shape = RoundedCornerShape(8.dp)
),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Text(if(drug.Id == -1) "Add Drug" else "Update Drug", color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.labelLarge)
}
Column(
modifier = Modifier
.padding(bottom = 30.dp)
.fillMaxWidth()
) {
val drugName = remember { mutableStateOf(drug.Name) }
TextField(
value = drugName.value,
onValueChange = {
drugName.value = it
drug.Name = it
},
label = {Text("Name")},
singleLine = true,
trailingIcon = {
IconButton(
onClick = {
drugName.value = ""
drug.Name = ""
}
)
{
Icon(
Icons.Filled.Clear,
contentDescription = "Clear",
)
} },
supportingText = { Text(text = "*required", color = MaterialTheme.colorScheme.error) },
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
val drugManufacturer = remember { mutableStateOf(drug.Manufacturer) }
TextField(
value = drugManufacturer.value,
onValueChange = {
drugManufacturer.value = it
drug.Manufacturer = it
},
label = {Text("Manufacturer")},
singleLine = true,
trailingIcon = {
IconButton(
onClick = {
drugManufacturer.value = ""
drug.Manufacturer = ""
}
)
{
Icon(
Icons.Filled.Clear,
contentDescription = "Clear",
)
} },
supportingText = { Text(text = "*required", color = MaterialTheme.colorScheme.error) },
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
val drugCategory = remember { mutableStateOf(drug.Category) }
TextField(
value = drugCategory.value,
onValueChange = {
drugCategory.value = it
drug.Category = it
},
label = {Text("Category")},
singleLine = true,
trailingIcon = {
IconButton(
onClick = {
drugCategory.value = ""
drug.Category = ""
}
)
{
Icon(
Icons.Filled.Clear,
contentDescription = "Clear",
)
} },
supportingText = { Text(text = "*required", color = MaterialTheme.colorScheme.error) },
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
val drugNumberOfUnits = remember { mutableStateOf(drug.NumberOfUnits.toString()) }
if (drugNumberOfUnits.value == "0") {
drugNumberOfUnits.value = ""
}
TextField(
value = drugNumberOfUnits.value,
onValueChange = {
drugNumberOfUnits.value = it
drug.NumberOfUnits = it.toIntOrNull() ?: 0
},
label = {Text("Number of Units")},
singleLine = true,
trailingIcon = {
IconButton(
onClick = {
drugNumberOfUnits.value = ""
drug.NumberOfUnits = 0
}
)
{
Icon(
Icons.Filled.Clear,
contentDescription = "Clear",
)
} },
supportingText = { Text(text = "*required", color = MaterialTheme.colorScheme.error) },
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number),
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
val drugRetailPrice = remember { mutableStateOf(drug.RetailPrice.toString()) }
if (drugRetailPrice.value == "0.0") {
drugRetailPrice.value = ""
}
TextField(
value = drugRetailPrice.value,
onValueChange = {
drugRetailPrice.value = it
drug.RetailPrice = (it.toDoubleOrNull() ?: 0.0)
},
label = {Text("Retail Price")},
singleLine = true,
trailingIcon = {
IconButton(
onClick = {
drugRetailPrice.value = ""
drug.RetailPrice = 0.0
}
)
{
Icon(
Icons.Filled.Clear,
contentDescription = "Clear",
)
} },
supportingText = { Text(text = "*required", color = MaterialTheme.colorScheme.error) },
prefix = { Text("$") },
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number),
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
}
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Button(
onClick = { finish() },
colors = ButtonColors(
MaterialTheme.colorScheme.surface,
MaterialTheme.colorScheme.primary,
MaterialTheme.colorScheme.surface,
MaterialTheme.colorScheme.primary
),
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline)
) {
Text("Cancel")
}
Button(
onClick = {
if(drug.Id == -1) {
Service.AddDrug(drug)
} else {
Service.UpdateDrug(drug)
}
finish()
},
colors = ButtonColors(
MaterialTheme.colorScheme.primary,
MaterialTheme.colorScheme.onPrimary,
MaterialTheme.colorScheme.onSurfaceVariant,
MaterialTheme.colorScheme.onSurface
),
enabled = drug.Name.isNotEmpty() && drug.Manufacturer.isNotEmpty() && drug.Category.isNotEmpty() && drug.NumberOfUnits > 0 && drug.RetailPrice > 0.0
) {
Text(if(drug.Id == -1) "Add" else "Update")
}
}
}
}
}
}
}
@@ -0,0 +1,49 @@
package com.example.ma_ui_native
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.snapshots.SnapshotStateList
object Service {
private var nextId = 11
private val DrugRepo = mutableStateListOf<MutableState<Drug>>(
mutableStateOf( Drug(1, "Paracetamol", "Analgesic", 100, 2.5, "GSK")),
mutableStateOf(Drug(2, "Amoxicillin", "Antibiotic", 50, 3.5, "Pfizer")),
mutableStateOf(Drug(3, "Omeprazole", "Antacid", 75, 1.5, "AstraZeneca")),
mutableStateOf(Drug(4, "Atorvastatin", "Anticholesterol", 25, 4.5, "Pfizer")),
mutableStateOf(Drug(5, "Metformin", "Antidiabetic", 30, 2.0, "Merck")),
mutableStateOf(Drug(6, "Amlodipine", "Antihypertensive", 40, 3.0, "Novartis")),
mutableStateOf(Drug(7, "Losartan", "Antihypertensive", 35, 3.5, "Merck")),
mutableStateOf(Drug(8, "Simvastatin", "Anticholesterol", 20, 4.0, "AstraZeneca")),
mutableStateOf(Drug(9, "Salbutamol", "Bronchodilator", 45, 2.5, "GSK")),
mutableStateOf(Drug(10, "Levothyroxine", "Hormone", 60, 1.5, "Novartis"))
)
public fun GetDrugs() : SnapshotStateList<MutableState<Drug>> {
return DrugRepo;
}
public fun GetDrug(id: Int) : Drug {
return DrugRepo.find { it.value.Id == id }?.value ?: Drug()
}
public fun AddDrug(drug: Drug) {
drug.Id = nextId++
DrugRepo.add(mutableStateOf( drug))
}
public fun UpdateDrug(drug: Drug) {
val index = DrugRepo.indexOfFirst { it.value.Id == drug.Id }
if (index != -1) {
DrugRepo[index] = mutableStateOf( drug)
}
}
public fun DeleteDrug(id: Int) {
val index = DrugRepo.indexOfFirst { it.value.Id == id }
if (index != -1) {
DrugRepo.removeAt(index)
}
}
}
@@ -0,0 +1,14 @@
package com.example.ma_ui_native.ui.theme
import androidx.compose.ui.graphics.Color
var Primary = Color(0xFF675496)
var OnPrimary = Color(0xFFFFFFFF)
val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
@@ -0,0 +1,58 @@
package com.example.ma_ui_native.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun MAUINativeTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
@@ -0,0 +1,34 @@
package com.example.ma_ui_native.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="m336,680 l144,-144 144,144 56,-56 -144,-144 144,-144 -56,-56 -144,144 -144,-144 -56,56 144,144 -144,144 56,56ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880ZM480,800q134,0 227,-93t93,-227q0,-134 -93,-227t-227,-93q-134,0 -227,93t-93,227q0,134 93,227t227,93ZM480,480Z"
android:fillColor="#e8eaed"/>
</vector>
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">MA-UI-Native</string>
</resources>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.MAUINative" parent="android:Theme.Material.Light.NoActionBar" />
</resources>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>
@@ -0,0 +1,17 @@
package com.example.ma_ui_native
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}