try to design ios-like settings activity

This commit is contained in:
Kavish Devar
2024-10-08 14:39:10 +05:30
parent f2a36834f0
commit b29451ce9e
4 changed files with 584 additions and 69 deletions

View File

@@ -1,35 +1,48 @@
package me.kavishdevar.aln package me.kavishdevar.aln
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.content.res.Configuration
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.Button import androidx.compose.material.icons.Icons
import androidx.compose.material3.ButtonDefaults import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SegmentedButton import androidx.compose.material3.Slider
import androidx.compose.material3.SegmentedButtonDefaults import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Shapes
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -37,10 +50,22 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.luminance
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import me.kavishdevar.aln.ui.theme.ALNTheme import me.kavishdevar.aln.ui.theme.ALNTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@@ -49,17 +74,15 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
val address = mutableStateOf("28:2D:7F:C2:05:5B")
// val bluetoothManager: BluetoothManager = getSystemService(BluetoothManager::class.java) val bluetoothManager: BluetoothManager = getSystemService(BluetoothManager::class.java)
// val bluetoothAdapter = bluetoothManager.adapter val bluetoothAdapter = bluetoothManager.adapter
// val device = bluetoothAdapter.getRemoteDevice("28:2d:7f:c2:05:5b") val device = bluetoothAdapter.getRemoteDevice(address.value)
// val deviceName = device.name
// val deviceAddress = device.address
setContent { setContent {
ALNTheme { ALNTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> Scaffold { innerPadding ->
AirPodsSettingsScreen(innerPadding) AirPodsSettingsScreen(innerPadding, device)
} }
} }
} }
@@ -67,81 +90,550 @@ class MainActivity : ComponentActivity() {
} }
@Composable @Composable
fun AirPodsSettingsScreen(paddingValues: PaddingValues) { fun StyledSwitch(
var ancMode by remember { mutableStateOf("Off") } checked: Boolean,
var deviceName by remember { mutableStateOf(TextFieldValue("Kavish's AirPods Pro")) } onCheckedChange: (Boolean) -> Unit
var conversationalAwarenessEnabled by remember { mutableStateOf(false) } ) {
var earDetectionEnabled by remember { mutableStateOf(true) } val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5
val thumbColor = Color.White
val trackColor = if (checked) Color(0xFF34C759) else if (isDarkTheme) Color(0xFF262629) else Color(0xFFD1D1D6)
// Animate the horizontal offset of the thumb
val thumbOffsetX by animateDpAsState(targetValue = if (checked) 20.dp else 0.dp, label = "Test")
Box(
modifier = Modifier
.width(51.dp)
.height(31.dp)
.clip(RoundedCornerShape(15.dp))
.background(trackColor) // Dynamic track background
.padding(horizontal = 3.dp),
contentAlignment = Alignment.CenterStart
) {
Box(
modifier = Modifier
.offset(x = thumbOffsetX) // Animate the offset for smooth transition
.size(27.dp)
.clip(CircleShape)
.background(thumbColor) // Dynamic thumb color
.clickable { onCheckedChange(!checked) } // Make the switch clickable
)
}
}
@Composable
fun StyledTextField(
name: String,
value: String,
onValueChange: (String) -> Unit
) {
val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5
val backgroundColor = if (isDarkTheme) Color(0xFF0E0E0E) else Color(0xFFFFFFFF)
val textColor = if (isDarkTheme) Color.White else Color.Black
val cursorColor = if (isDarkTheme) Color.White else Color.Black
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(vertical = 8.dp)
.fillMaxWidth()
.background(
backgroundColor,
RoundedCornerShape(10.dp)
) // Dynamic background based on theme
.padding(horizontal = 16.dp, vertical = 12.dp)
) {
Text(
text = name,
style = TextStyle(
fontSize = 16.sp,
color = textColor // Text color based on theme
)
)
BasicTextField(
value = value,
onValueChange = onValueChange,
textStyle = TextStyle(
color = textColor, // Dynamic text color
fontSize = 16.sp,
),
cursorBrush = SolidColor(cursorColor), // Dynamic cursor color
decorationBox = { innerTextField ->
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
innerTextField()
}
},
modifier = Modifier
.fillMaxWidth() // Ensures text field takes remaining available space
.padding(start = 8.dp) // Padding to adjust spacing between text field and icon
)
}
}
@Composable
fun BatteryIndicator(batteryPercentage: Int) {
val batteryOutlineColor = Color(0xFFBFBFBF) // Light gray outline
val batteryFillColor = if (batteryPercentage > 30) Color(0xFF30D158) else Color(0xFFFC3C3C)
val batteryTextColor = MaterialTheme.colorScheme.onSurface
// Battery indicator dimensions
val batteryWidth = 30.dp
val batteryHeight = 15.dp
val batteryCornerRadius = 4.dp
val tipWidth = 3.dp
val tipHeight = batteryHeight * 0.3f
Column(horizontalAlignment = Alignment.CenterHorizontally) {
// Row for battery icon and tip
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(0.dp),
modifier = Modifier.padding(bottom = 4.dp) // Padding between icon and percentage text
) {
// Battery Icon
Box(
modifier = Modifier
.width(batteryWidth)
.height(batteryHeight)
.border(1.dp, batteryOutlineColor, RoundedCornerShape(batteryCornerRadius))
) {
// Battery Fill
Box(
modifier = Modifier
.fillMaxHeight()
.padding(2.dp)
.width(batteryWidth * (batteryPercentage / 100f))
.background(batteryFillColor, RoundedCornerShape(2.dp))
)
}
// Battery Tip (Protrusion)
Box(
modifier = Modifier
.width(tipWidth)
.height(tipHeight)
.padding(start = 1.dp)
.background(
batteryOutlineColor,
RoundedCornerShape(
topStart = 0.dp,
topEnd = 5.dp,
bottomStart = 5.dp,
bottomEnd = 4.dp
)
)
)
}
// Battery Percentage Text
Text(
text = "$batteryPercentage%",
color = batteryTextColor,
style = TextStyle(fontSize = 16.sp, fontWeight = FontWeight.Bold)
)
}
}
@SuppressLint("MissingPermission")
@Composable
fun AirPodsSettingsScreen(paddingValues: PaddingValues, device: BluetoothDevice?) {
var deviceName by remember { mutableStateOf(TextFieldValue(device?.name ?: "Kavish's AirPods Pro")) }
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(paddingValues) .padding(paddingValues)
.padding(vertical = 24.dp, horizontal = 12.dp)
) { ) {
// Device Name Section Row {
Text(text = "Name", style = MaterialTheme.typography.titleMedium) Column (
BasicTextField( horizontalAlignment = Alignment.CenterHorizontally
value = deviceName, ){
onValueChange = { deviceName = it }, // using this temporarily until i can find an image of only the buds
modifier = Modifier Image(
.fillMaxWidth() bitmap = ImageBitmap.imageResource(R.drawable.pro_2),
.padding(vertical = 8.dp) contentDescription = null,
modifier = Modifier.fillMaxWidth(0.5f)
)
BatteryIndicator(batteryPercentage = 10)
}
Column (
horizontalAlignment = Alignment.CenterHorizontally
){
Image(
bitmap = ImageBitmap.imageResource(R.drawable.pro_2),
contentDescription = null,
modifier = Modifier.fillMaxWidth()
)
BatteryIndicator(batteryPercentage = 100)
}
}
StyledTextField(
name = "Name",
value = deviceName.text,
onValueChange = { deviceName = TextFieldValue(it) }
) )
HorizontalDivider(thickness = 2.dp, modifier = Modifier.padding(vertical = 8.dp), color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f)) Spacer(modifier = Modifier.height(16.dp))
NoiseControlSettings()
Spacer(modifier = Modifier.height(16.dp))
AudioSettings()
}
}
// ANC Mode Section @Composable
Text(text = "Noise Control", style = MaterialTheme.typography.titleMedium) fun NoiseControlSlider() {
ANCOptions(ancMode) { selectedMode -> ancMode = selectedMode } val sliderValue = remember { mutableStateOf(0f) }
val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5
HorizontalDivider(thickness = 2.dp, modifier = Modifier.padding(vertical = 8.dp), color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f)) val trackColor = if (isDarkTheme) Color(0xFFB3B3B3) else Color(0xFFD9D9D9)
val activeTrackColor = if (isDarkTheme) Color(0xFFFFFFFF) else Color(0xFF007AFF)
val thumbColor = if (isDarkTheme) Color(0xFFFFFFFF) else Color(0xFF007AFF)
val labelTextColor = if (isDarkTheme) Color.White else Color.Black
// Conversational Awareness Toggle Column(
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { modifier = Modifier
Text(text = "Conversational Awareness", modifier = Modifier.weight(1f)) .fillMaxWidth()
Switch( .padding(horizontal = 8.dp),
checked = conversationalAwarenessEnabled, horizontalAlignment = Alignment.CenterHorizontally
onCheckedChange = { conversationalAwarenessEnabled = it } ) {
// Slider
Slider(
value = sliderValue.value,
onValueChange = { sliderValue.value = it },
valueRange = 0f..100f,
steps = 99,
modifier = Modifier
.fillMaxWidth(),
colors = SliderDefaults.colors(
thumbColor = thumbColor,
activeTrackColor = activeTrackColor,
inactiveTrackColor = trackColor
) )
} )
HorizontalDivider(thickness = 2.dp, modifier = Modifier.padding(vertical = 8.dp), color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f)) // Labels
Row(
// Ear Detection Toggle modifier = Modifier.fillMaxWidth(),
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { horizontalArrangement = Arrangement.SpaceBetween
Text(text = "Automatic Ear Detection", modifier = Modifier.weight(1f)) ) {
Switch( Text(
checked = earDetectionEnabled, text = "Less Noise",
onCheckedChange = { earDetectionEnabled = it } style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Light,
color = labelTextColor
),
modifier = Modifier.padding(start = 4.dp)
)
Text(
text = "More Noise",
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Light,
color = labelTextColor
),
modifier = Modifier.padding(end = 4.dp)
) )
} }
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun ANCOptions(selectedMode: String, onModeChange: (String) -> Unit) { fun AudioSettings() {
val modes = listOf("Off", "Transparency", "Noise Cancellation") val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5
val textColor = if (isDarkTheme) Color.White else Color.Black
var conversationalAwarenessEnabled by remember { mutableStateOf(true) }
SingleChoiceSegmentedButtonRow { Text(
modes.forEach { mode -> text = "AUDIO",
SegmentedButton( style = TextStyle(
selected = (mode == selectedMode), fontSize = 14.sp,
onClick = { onModeChange(mode) }, fontWeight = FontWeight.Light,
modifier = Modifier.weight(1f), color = textColor.copy(alpha = 0.6f)
shape = ShapeDefaults.ExtraSmall ),
) { modifier = Modifier.padding(8.dp, bottom = 2.dp)
Text( )
text = mode, val backgroundColor = if (isDarkTheme) Color(0xFF0E0E0E) else Color(0xFFFFFFFF)
textAlign = TextAlign.Center val isPressed = remember { mutableStateOf(false) }
Column (
modifier = Modifier
.fillMaxWidth()
.background(backgroundColor, RoundedCornerShape(12.dp))
.padding(top = 2.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.background(shape = RoundedCornerShape(12.dp), color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent)
.padding(horizontal = 12.dp, vertical = 12.dp)
.pointerInput(Unit) { // Detect press state for iOS-like effect
detectTapGestures(
onPress = {
isPressed.value = true
tryAwaitRelease() // Wait until release
isPressed.value = false
}
)
}
.clickable(
indication = null, // Disable ripple effect
interactionSource = remember { MutableInteractionSource() } // Required for clickable
) {
conversationalAwarenessEnabled = !conversationalAwarenessEnabled
},
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "Conversational Awareness", modifier = Modifier.weight(1f), fontSize = 16.sp)
StyledSwitch(
checked = conversationalAwarenessEnabled,
onCheckedChange = { conversationalAwarenessEnabled = it },
)
}
Column (
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 10.dp)
) {
Text(
text = "Adaptive Audio",
modifier = Modifier
.padding(end = 8.dp, bottom = 2.dp, start = 2.dp)
.fillMaxWidth(),
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
color = textColor
) )
)
Text(
text = "Adaptive audio dynamically responds to your environment and cancels or allows external noise. You can customize Adaptive Audio to allow more or less noise",
modifier = Modifier
.padding(8.dp, top = 2.dp)
.fillMaxWidth(),
style = TextStyle(
fontSize = 12.sp,
color = textColor.copy(alpha = 0.6f)
)
)
NoiseControlSlider()
}
}
}
@Composable
fun NoiseControlSettings() {
val isDarkTheme = MaterialTheme.colorScheme.surface.luminance() < 0.5
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFF2F2F7)
val textColor = if (isDarkTheme) Color.White else Color.Black
val textColorSelected = if (isDarkTheme) Color.White else Color.Black
val selectedBackground = if (isDarkTheme) Color(0xFF090909) else Color(0xFFFFFFFF)
val noiseControlMode = remember { mutableStateOf(NoiseControlMode.OFF) }
// val paddingAnim by animateDpAsState(
// targetValue = when (noiseControlMode.value) {
// NoiseControlMode.OFF -> 0.dp
// NoiseControlMode.TRANSPARENCY -> 150.dp
// NoiseControlMode.ADAPTIVE -> 250.dp
// NoiseControlMode.NOISE_CANCELLATION -> 350.dp
// }, label = ""
// )
val d1a = remember { mutableStateOf(0f) }
val d2a = remember { mutableStateOf(0f) }
val d3a = remember { mutableStateOf(0f) }
fun onModeSelected(mode: NoiseControlMode) {
noiseControlMode.value = mode
when (mode) {
NoiseControlMode.NOISE_CANCELLATION -> {
d1a.value = 1f
d2a.value = 1f
d3a.value = 0f
}
NoiseControlMode.OFF -> {
d1a.value = 0f
d2a.value = 1f
d3a.value = 1f
}
NoiseControlMode.ADAPTIVE -> {
d1a.value = 1f
d2a.value = 0f
d3a.value = 0f
}
NoiseControlMode.TRANSPARENCY -> {
d1a.value = 0f
d2a.value = 0f
d3a.value = 1f
} }
} }
} }
Text(
text = "NOISE CONTROL",
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Light,
color = textColor.copy(alpha = 0.6f)
),
modifier = Modifier.padding(8.dp, bottom = 2.dp)
)
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(65.dp)
.padding(8.dp)
) {
// Box(
// modifier = Modifier
// .fillMaxHeight()
// .width(80.dp)
// .offset(x = paddingAnim)
// .background(selectedBackground, RoundedCornerShape(8.dp))
// )
Row(
modifier = Modifier
.fillMaxWidth()
.background(backgroundColor, RoundedCornerShape(8.dp))
) {
NoiseControlButton(
icon = Icons.Default.Person, // Replace with your icon
onClick = { onModeSelected(NoiseControlMode.OFF) },
textColor = if (noiseControlMode.value == NoiseControlMode.OFF) textColorSelected else textColor,
backgroundColor = if (noiseControlMode.value == NoiseControlMode.OFF) selectedBackground else Color.Transparent,
modifier = Modifier.weight(1f)
)
VerticalDivider(
thickness = 1.dp,
modifier = Modifier
.padding(vertical = 10.dp)
.alpha(d1a.value),
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
)
NoiseControlButton(
icon = Icons.Default.Person, // Replace with your icon
onClick = { onModeSelected(NoiseControlMode.TRANSPARENCY) },
textColor = if (noiseControlMode.value == NoiseControlMode.TRANSPARENCY) textColorSelected else textColor,
backgroundColor = if (noiseControlMode.value == NoiseControlMode.TRANSPARENCY) selectedBackground else Color.Transparent,
modifier = Modifier.weight(1f)
)
VerticalDivider(
thickness = 1.dp,
modifier = Modifier
.padding(vertical = 10.dp)
.alpha(d2a.value),
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
)
NoiseControlButton(
icon = Icons.Default.Person, // Replace with your icon
onClick = { onModeSelected(NoiseControlMode.ADAPTIVE) },
textColor = if (noiseControlMode.value == NoiseControlMode.ADAPTIVE) textColorSelected else textColor,
backgroundColor = if (noiseControlMode.value == NoiseControlMode.ADAPTIVE) selectedBackground else Color.Transparent,
modifier = Modifier.weight(1f)
)
VerticalDivider(
thickness = 1.dp,
modifier = Modifier
.padding(vertical = 10.dp)
.alpha(d3a.value),
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
)
NoiseControlButton(
icon = Icons.Default.Person, // Replace with your icon
onClick = { onModeSelected(NoiseControlMode.NOISE_CANCELLATION) },
textColor = if (noiseControlMode.value == NoiseControlMode.NOISE_CANCELLATION) textColorSelected else textColor,
backgroundColor = if (noiseControlMode.value == NoiseControlMode.NOISE_CANCELLATION) selectedBackground else Color.Transparent,
modifier = Modifier.weight(1f)
)
}
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
.padding(top = 1.dp)
) {
Text(
text = "Off",
style = TextStyle(fontSize = 12.sp, color = textColor),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
modifier = Modifier.weight(1f)
)
Text(
text = "Transparency",
style = TextStyle(fontSize = 12.sp, color = textColor),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
modifier = Modifier.weight(1f)
)
Text(
text = "Adaptive",
style = TextStyle(fontSize = 12.sp, color = textColor),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
modifier = Modifier.weight(1f)
)
Text(
text = "Noise Cancellation",
style = TextStyle(fontSize = 12.sp, color = textColor),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
modifier = Modifier.weight(1f)
)
}
}
} }
@Preview(showBackground = true) @Composable
fun NoiseControlButton(
icon: ImageVector,
onClick: () -> Unit,
textColor: Color,
backgroundColor: Color,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxHeight()
.padding(horizontal = 4.dp, vertical = 4.dp)
.background(color = backgroundColor, shape = RoundedCornerShape(6.dp))
.clickable(onClick = onClick, indication = null, interactionSource = remember { MutableInteractionSource() }),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = textColor,
modifier = Modifier.size(32.dp)
)
}
}
enum class NoiseControlMode {
OFF, TRANSPARENCY, ADAPTIVE, NOISE_CANCELLATION
}
@Preview(showBackground = true, name = "AirPods Settings",
uiMode = Configuration.UI_MODE_NIGHT_YES, showSystemUi = true,
device = "spec:width=411dp,height=891dp"
)
@Composable @Composable
fun PreviewAirPodsSettingsScreen() { fun PreviewAirPodsSettingsScreen() {
AirPodsSettingsScreen(PaddingValues(16.dp)) AirPodsSettingsScreen(PaddingValues(8.dp), null)
} }

View File

@@ -0,0 +1,23 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="154.38dp"
android:height="148.1dp"
android:viewportWidth="154.38"
android:viewportHeight="148.1">
<path
android:fillColor="#FF000000"
android:pathData="M0,0h154.38v148.1h-154.38z"
android:strokeAlpha="0"
android:fillAlpha="0"/>
<path
android:pathData="M134.81,86.77C137.13,88.33 140,87.77 141.69,85.39C149.69,74.39 154.38,59.27 154.38,43.83C154.38,28.39 149.75,13.14 141.69,2.27C140,-0.17 137.13,-0.67 134.81,0.89C132.5,2.46 132.13,5.39 133.94,7.96C140.81,17.58 144.69,30.52 144.69,43.83C144.69,57.14 140.69,69.96 133.94,79.71C132.19,82.27 132.5,85.21 134.81,86.77Z"
android:fillColor="#ffffff"
android:fillAlpha="0.85"/>
<path
android:pathData="M111.69,70.46C113.75,71.89 116.69,71.46 118.38,69.02C123.19,62.71 126.06,53.39 126.06,43.83C126.06,34.27 123.19,25.02 118.38,18.58C116.69,16.21 113.75,15.71 111.69,17.21C109.13,18.96 108.75,22.08 110.69,24.64C114.31,29.64 116.38,36.58 116.38,43.83C116.38,51.08 114.25,57.96 110.69,63.02C108.81,65.64 109.13,68.64 111.69,70.46Z"
android:fillColor="#ffffff"
android:fillAlpha="0.85"/>
<path
android:pathData="M26.13,130.21L104.63,130.21C114.44,130.21 117.94,127.39 117.94,121.89C117.94,105.77 97.75,83.52 65.38,83.52C32.94,83.52 12.75,105.77 12.75,121.89C12.75,127.39 16.25,130.21 26.13,130.21ZM65.38,72.33C78.81,72.33 90.38,60.33 90.38,44.71C90.38,29.27 78.75,17.83 65.38,17.83C52,17.83 40.38,29.52 40.38,44.83C40.38,60.33 52,72.33 65.38,72.33Z"
android:fillColor="#ffffff"
android:fillAlpha="0.85"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB