Rename project

from 'Android Owner' to 'OwnDroid'
resolve #2
This commit is contained in:
BinTianqi
2024-04-21 09:11:16 +08:00
parent c0df796610
commit 26793f510b
38 changed files with 265 additions and 224 deletions

View File

@@ -0,0 +1,59 @@
package com.bintianqi.owndroid.ui
import androidx.compose.animation.*
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.VisibilityThreshold
import androidx.compose.animation.core.spring
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.navigation.NavBackStackEntry
import com.bintianqi.owndroid.displayMetrics
class Animations{
private val fade: FiniteAnimationSpec<Float> = spring(stiffness = Spring.StiffnessMediumLow)
private val spring:FiniteAnimationSpec<IntOffset> = spring(stiffness = Spring.StiffnessMediumLow, visibilityThreshold = IntOffset.VisibilityThreshold)
val animateListSize:FiniteAnimationSpec<IntSize> = spring(stiffness = Spring.StiffnessMediumLow, visibilityThreshold = IntSize.VisibilityThreshold)
private val screenWidth = displayMetrics.widthPixels
private val initialOffsetValue = screenWidth/10
private val targetOffsetValue = screenWidth/10
val navHostEnterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition = {
fadeIn(animationSpec = fade) +
slideIntoContainer(
animationSpec = spring,
towards = AnimatedContentTransitionScope.SlideDirection.End,
initialOffset = {initialOffsetValue}
)
}
val navHostExitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition = {
fadeOut(animationSpec = fade) +
slideOutOfContainer(
animationSpec = spring,
towards = AnimatedContentTransitionScope.SlideDirection.Start,
targetOffset = {-targetOffsetValue}
)
}
val navHostPopEnterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition = {
fadeIn(animationSpec = fade) +
slideIntoContainer(
animationSpec = spring,
towards = AnimatedContentTransitionScope.SlideDirection.End,
initialOffset = {-initialOffsetValue}
)
}
val navHostPopExitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition = {
fadeOut(animationSpec = fade) +
slideOutOfContainer(
animationSpec = spring,
towards = AnimatedContentTransitionScope.SlideDirection.Start,
targetOffset = {targetOffsetValue}
)
}
}

View File

@@ -0,0 +1,192 @@
package com.bintianqi.owndroid.ui
import android.content.Context
import android.widget.Toast
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavHostController
import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.ui.theme.bgColor
import com.bintianqi.owndroid.writeClipBoard
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable
fun SubPageItem(
@StringRes title: Int,
desc:String,
@DrawableRes icon: Int? = null,
operation: () -> Unit
){
Row(
modifier = Modifier.fillMaxWidth().clickable(onClick = operation).padding(vertical = 15.dp),
verticalAlignment = Alignment.CenterVertically
){
Spacer(Modifier.padding(start = 30.dp))
if(icon!=null){
Icon(painter = painterResource(icon), contentDescription = stringResource(title), modifier = Modifier.padding(top = 1.dp))
Spacer(Modifier.padding(start = 15.dp))
}
Column {
Text(text = stringResource(title), style = typography.titleLarge, modifier = Modifier.padding(bottom = 1.dp))
if(desc!=""){Text(text = desc, color = colorScheme.onBackground.copy(alpha = 0.8F))}
}
}
}
@Composable
fun NavIcon(operation: () -> Unit){
Icon(
painter = painterResource(R.drawable.arrow_back_fill0),
contentDescription = "Back arrow",
modifier = Modifier
.padding(horizontal = 6.dp)
.clip(RoundedCornerShape(50))
.clickable(onClick = operation)
.padding(5.dp)
)
}
@Composable
fun Information(content: @Composable ()->Unit){
Column(modifier = Modifier.fillMaxWidth().padding(start = 5.dp)){
Icon(painter = painterResource(R.drawable.info_fill0),contentDescription = "info", tint = colorScheme.onBackground.copy(alpha = 0.8F))
Spacer(Modifier.padding(vertical = 1.dp))
Row {
Spacer(Modifier.padding(horizontal = 1.dp))
content()
}
}
}
@Composable
fun RadioButtonItem(
text:String,
selected:()->Boolean,
operation:()->Unit,
textColor: Color = colorScheme.onBackground
){
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
val isWear = sharedPref.getBoolean("isWear",false)
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier
.fillMaxWidth()
.padding(vertical = if(isWear){3.dp}else{0.dp})
.clip(RoundedCornerShape(25))
.clickable(onClick = operation)
) {
RadioButton(selected = selected(), onClick = operation,modifier=if(isWear){Modifier.size(28.dp)}else{Modifier})
Text(text = text, style = if(!isWear){typography.bodyLarge}else{typography.bodyMedium}, color = textColor,
modifier = Modifier.padding(bottom = 2.dp))
}
}
@Composable
fun CheckBoxItem(
text:String,
checked:()->Boolean,
operation:()->Unit,
textColor:Color = colorScheme.onBackground
){
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
val isWear = sharedPref.getBoolean("isWear",false)
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier
.fillMaxWidth()
.padding(vertical = if(isWear){3.dp}else{0.dp})
.clip(RoundedCornerShape(25))
.clickable(onClick = operation)
) {
Checkbox(
checked = checked(),
onCheckedChange = {operation()},
modifier=if(isWear){Modifier.size(28.dp)}else{Modifier}
)
Text(text = text, style = if(!isWear){typography.bodyLarge}else{typography.bodyMedium}, color = textColor, modifier = Modifier.padding(bottom = 2.dp))
}
}
@Composable
fun SwitchItem(
@StringRes title: Int,
desc: String,
@DrawableRes icon: Int?,
getState: ()->Boolean,
onCheckedChange: (Boolean)->Unit,
enable:Boolean=true
){
var checked by remember{mutableStateOf(false)}
checked = getState()
Box(modifier = Modifier.fillMaxWidth().padding(vertical = 5.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.align(Alignment.CenterStart)){
Spacer(Modifier.padding(start = 30.dp))
if(icon!=null){
Icon(painter = painterResource(icon),contentDescription = null)
Spacer(Modifier.padding(start = 15.dp))
}
Column(modifier = Modifier.padding(end = 60.dp)){
Text(text = stringResource(title), style = typography.titleLarge)
if(desc!=""){Text(text = desc, color = colorScheme.onBackground.copy(alpha = 0.8F))}else{Spacer(Modifier.padding(vertical = 1.dp))}
}
}
Switch(
checked = checked, onCheckedChange = {onCheckedChange(it);checked=getState()},
modifier = Modifier.align(Alignment.CenterEnd).padding(end = 12.dp), enabled = enable
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TopBar(
backStackEntry:NavBackStackEntry?,
navCtrl:NavHostController,
localNavCtrl:NavHostController,
title:@Composable ()->Unit = {}
){
TopAppBar(
//Text(text = stringResource(titleMap[backStackEntry?.destination?.route]?:R.string.user_restrict))
title = title,
navigationIcon = {NavIcon{if(backStackEntry?.destination?.route=="Home"){navCtrl.navigateUp()}else{localNavCtrl.navigateUp()}}},
colors = TopAppBarDefaults.topAppBarColors(containerColor = bgColor)
)
}
@Composable
fun CopyTextButton(context: Context, @StringRes label: Int, content: String){
var ok by remember{mutableStateOf(false)}
val scope = rememberCoroutineScope()
Button(
onClick = {
if(!ok){
scope.launch{
if(writeClipBoard(context,content)){ ok = true; delay(2000); ok = false }
else{ Toast.makeText(context,context.getString(R.string.fail),Toast.LENGTH_SHORT).show() }
}
}
}
){
Row(
verticalAlignment = Alignment.CenterVertically, modifier = Modifier.animateContentSize()
){
Icon(painter = painterResource(if(ok){R.drawable.check_fill0}else{R.drawable.content_copy_fill0}),contentDescription = null)
Spacer(modifier = Modifier.padding(horizontal = 2.dp))
Text(text = stringResource(if(ok){R.string.success}else{label}))
}
}
}

View File

@@ -0,0 +1,63 @@
package com.bintianqi.owndroid.ui.theme
import androidx.compose.ui.graphics.Color
val md_theme_light_primary = Color(0xFF006A65)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFF70F7EE)
val md_theme_light_onPrimaryContainer = Color(0xFF00201E)
val md_theme_light_secondary = Color(0xFF4A6361)
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer = Color(0xFFCCE8E5)
val md_theme_light_onSecondaryContainer = Color(0xFF051F1E)
val md_theme_light_tertiary = Color(0xFF48607B)
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer = Color(0xFFD0E4FF)
val md_theme_light_onTertiaryContainer = Color(0xFF001D34)
val md_theme_light_error = Color(0xFFBA1A1A)
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
val md_theme_light_onError = Color(0xFFFFFFFF)
val md_theme_light_onErrorContainer = Color(0xFF410002)
val md_theme_light_background = Color(0xFFFAFDFB)
val md_theme_light_onBackground = Color(0xFF191C1C)
val md_theme_light_surface = Color(0xFFFAFDFB)
val md_theme_light_onSurface = Color(0xFF191C1C)
val md_theme_light_surfaceVariant = Color(0xFFDAE5E3)
val md_theme_light_onSurfaceVariant = Color(0xFF3F4947)
val md_theme_light_outline = Color(0xFF6F7978)
val md_theme_light_inverseOnSurface = Color(0xFFEFF1F0)
val md_theme_light_inverseSurface = Color(0xFF2D3130)
val md_theme_light_inversePrimary = Color(0xFF4FDAD1)
val md_theme_light_surfaceTint = Color(0xFF006A65)
val md_theme_light_outlineVariant = Color(0xFFBEC9C7)
val md_theme_light_scrim = Color(0xFF000000)
val md_theme_dark_primary = Color(0xFF4FDAD1)
val md_theme_dark_onPrimary = Color(0xFF003734)
val md_theme_dark_primaryContainer = Color(0xFF00504C)
val md_theme_dark_onPrimaryContainer = Color(0xFF70F7EE)
val md_theme_dark_secondary = Color(0xFFB0CCC9)
val md_theme_dark_onSecondary = Color(0xFF1C3533)
val md_theme_dark_secondaryContainer = Color(0xFF324B49)
val md_theme_dark_onSecondaryContainer = Color(0xFFCCE8E5)
val md_theme_dark_tertiary = Color(0xFFB0C9E7)
val md_theme_dark_onTertiary = Color(0xFF18324A)
val md_theme_dark_tertiaryContainer = Color(0xFF304962)
val md_theme_dark_onTertiaryContainer = Color(0xFFD0E4FF)
val md_theme_dark_error = Color(0xFFFFB4AB)
val md_theme_dark_errorContainer = Color(0xFF93000A)
val md_theme_dark_onError = Color(0xFF690005)
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
val md_theme_dark_background = Color(0xFF000000)
val md_theme_dark_onBackground = Color(0xFFE0E3E2)
val md_theme_dark_surface = Color(0xFF191C1C)
val md_theme_dark_onSurface = Color(0xFFE0E3E2)
val md_theme_dark_surfaceVariant = Color(0xFF3F4947)
val md_theme_dark_onSurfaceVariant = Color(0xFFBEC9C7)
val md_theme_dark_outline = Color(0xFF889391)
val md_theme_dark_inverseOnSurface = Color(0xFF191C1C)
val md_theme_dark_inverseSurface = Color(0xFFE0E3E2)
val md_theme_dark_inversePrimary = Color(0xFF006A65)
val md_theme_dark_surfaceTint = Color(0xFF4FDAD1)
val md_theme_dark_outlineVariant = Color(0xFF3F4947)
val md_theme_dark_scrim = Color(0xFF000000)

View File

@@ -0,0 +1,129 @@
package com.bintianqi.owndroid.ui.theme
import android.app.Activity
import android.content.Context
import android.os.Build
import android.os.Build.VERSION
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
private val DarkColorScheme = darkColorScheme(
primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
primaryContainer = md_theme_dark_primaryContainer,
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_secondary,
onSecondary = md_theme_dark_onSecondary,
secondaryContainer = md_theme_dark_secondaryContainer,
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
tertiary = md_theme_dark_tertiary,
onTertiary = md_theme_dark_onTertiary,
tertiaryContainer = md_theme_dark_tertiaryContainer,
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
error = md_theme_dark_error,
errorContainer = md_theme_dark_errorContainer,
onError = md_theme_dark_onError,
onErrorContainer = md_theme_dark_onErrorContainer,
background = md_theme_dark_background,
onBackground = md_theme_dark_onBackground,
surface = md_theme_dark_surface,
onSurface = md_theme_dark_onSurface,
surfaceVariant = md_theme_dark_surfaceVariant,
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
outline = md_theme_dark_outline,
inverseOnSurface = md_theme_dark_inverseOnSurface,
inverseSurface = md_theme_dark_inverseSurface,
inversePrimary = md_theme_dark_inversePrimary,
surfaceTint = md_theme_dark_surfaceTint,
outlineVariant = md_theme_dark_outlineVariant,
scrim = md_theme_dark_scrim
)
private val LightColorScheme = lightColorScheme(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
onPrimaryContainer = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_secondary,
onSecondary = md_theme_light_onSecondary,
secondaryContainer = md_theme_light_secondaryContainer,
onSecondaryContainer = md_theme_light_onSecondaryContainer,
tertiary = md_theme_light_tertiary,
onTertiary = md_theme_light_onTertiary,
tertiaryContainer = md_theme_light_tertiaryContainer,
onTertiaryContainer = md_theme_light_onTertiaryContainer,
error = md_theme_light_error,
errorContainer = md_theme_light_errorContainer,
onError = md_theme_light_onError,
onErrorContainer = md_theme_light_onErrorContainer,
background = md_theme_light_background,
onBackground = md_theme_light_onBackground,
surface = md_theme_light_surface,
onSurface = md_theme_light_onSurface,
surfaceVariant = md_theme_light_surfaceVariant,
onSurfaceVariant = md_theme_light_onSurfaceVariant,
outline = md_theme_light_outline,
inverseOnSurface = md_theme_light_inverseOnSurface,
inverseSurface = md_theme_light_inverseSurface,
inversePrimary = md_theme_light_inversePrimary,
surfaceTint = md_theme_light_surfaceTint,
outlineVariant = md_theme_light_outlineVariant,
scrim = md_theme_light_scrim
)
var bgColor = Color(0xFF000000)
@Composable
fun SetDarkTheme(){
val dark = isSystemInDarkTheme()
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
val bg = colorScheme.background
val lightBg = colorScheme.primary.copy(alpha = 0.05F)
bgColor = if(dark){
if(sharedPref.getBoolean("blackTheme",true)){ Color(0xFF000000) }else{ bg }
}else{
lightBg
}
}
@Composable
fun OwnDroidTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
SetDarkTheme()
val context = LocalContext.current
val sharedPref = context.getSharedPreferences("data", Context.MODE_PRIVATE)
if(!sharedPref.contains("dynamicColor")&&VERSION.SDK_INT>=32){
sharedPref.edit().putBoolean("dynamicColor",true).apply()
}
val dynamicColor = sharedPref.getBoolean("dynamicColor",false)
val colorScheme = when {
dynamicColor && VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = Color.Transparent.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}

View File

@@ -0,0 +1,34 @@
package com.bintianqi.owndroid.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
)
*/
)