diff --git a/app/src/main/java/es/verdnatura/presentation/composable/CustomToolbar.kt b/app/src/main/java/es/verdnatura/presentation/composable/CustomToolbar.kt new file mode 100644 index 00000000..ccae1833 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/composable/CustomToolbar.kt @@ -0,0 +1,220 @@ +package es.verdnatura.presentation.composable + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterVertically +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.onFocusEvent +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.ImeAction +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 es.verdnatura.R + +@Composable +fun CustomToolbar( + title: String, + subtitle: String? = null, + showBackButton: Boolean = true, + showSwitch: Boolean = false, + iconList: List = emptyList(), + onBackClick: () -> Unit = {}, + onSwitchChange: (Boolean) -> Unit = {} +) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(Color.Black) + ) { + + Row( + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + verticalAlignment = CenterVertically, + + ) { + if (showBackButton) { + IconButton( + onClick = { onBackClick() }, + modifier = Modifier.padding(start = 0.dp), + ) { + Icon( + painter = painterResource(id = R.drawable.ic_chevron_left), + contentDescription = "Back", + tint = Color.White + ) + } + } + Text( + text = title, + color = Color.White, + fontSize = dimensionResource(id = R.dimen.title).value.sp, + fontWeight = FontWeight.Bold, + + ) + + if (!subtitle.isNullOrEmpty()) { + Text( + modifier = Modifier.weight(1f), + text = subtitle, + color = Color.White.copy(alpha = 0.7f), + fontSize = dimensionResource(id = R.dimen.subtitle).value.sp + ) + } + } + + if (iconList.isNotEmpty()) { + LazyRow { + items(iconList) { iconRes -> + IconButton(onClick = { /* Acción del icono */ }) { + Icon( + painter = painterResource(id = iconRes), + contentDescription = "Icon", + tint = Color.White + ) + } + } + } + } + + if (showSwitch) { + var switchState by remember { mutableStateOf(false) } + Switch( + checked = switchState, + onCheckedChange = { + switchState = it + onSwitchChange(it) + } + ) + } + } + + + HorizontalDivider( + thickness = 1.dp, + color = colorResource(id = R.color.verdnatura_brown_grey) + ) +} + +@Composable +fun ScanLineTextSearch( + value: String, + onValueChange: (String) -> Unit, + onImeAction: () -> Unit, + modifier: Modifier = Modifier.wrapContentSize(), +) { + + val keyboardController = LocalSoftwareKeyboardController.current + + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + TextField( + value = value, + onValueChange = onValueChange, + textStyle = TextStyle( + color = Color.White, + textAlign = TextAlign.Center + ), + placeholder = { + Text( + text = stringResource(id = R.string.Escaneaetiqueta), + textAlign = TextAlign.Center, + color = Color.White, + modifier = Modifier.fillMaxWidth() + ) + }, + singleLine = true, + keyboardActions = KeyboardActions( + onDone = { + onImeAction() + } + + ), + keyboardOptions = KeyboardOptions.Default.copy( + imeAction = ImeAction.Done + ), + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.DarkGray, // Fondo cuando está enfocado + unfocusedContainerColor = Color.DarkGray, // Fondo cuando NO está enfocado + cursorColor = Color.White, // Color del cursor + focusedTextColor = Color.White, // Color del texto cuando está enfocado + unfocusedTextColor = Color.White, // Color del texto cuando NO está enfocado + focusedPlaceholderColor = Color.Black, // Color del placeholder cuando está enfocado + unfocusedPlaceholderColor = Color.Black // Color del placeholder cuando NO está enfocado + ), + modifier = modifier + .fillMaxWidth(fraction = 0.67f) + .border(2.dp, Color.White, RoundedCornerShape(8.dp)) + .height(54.dp) + .padding(bottom = 4.dp) + .onFocusEvent { + if (it.isFocused) { + keyboardController?.hide() + } + } + ) + + } +} + +@Preview +@Composable +fun PreviewToolbar() { + CustomToolbar( + title = "Mi Toolbar", + subtitle = "10/20", + showBackButton = true, + showSwitch = true, + iconList = listOf(R.drawable.ic_launcher_foreground, R.drawable.ic_launcher_foreground), + onBackClick = { /* Acción de volver atrás */ }, + onSwitchChange = { /* Acción del switch */ } + ) +} + +@Preview +@Composable +fun PreviewScanLineTextSearch() { + ScanLineTextSearch( + value = "Escanea etiqueta", + onValueChange = {}, + onImeAction = {}) +} + + diff --git a/app/src/main/java/es/verdnatura/presentation/composable/ImageViewActivityComposable.kt b/app/src/main/java/es/verdnatura/presentation/composable/ImageViewActivityComposable.kt new file mode 100644 index 00000000..30122f7a --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/composable/ImageViewActivityComposable.kt @@ -0,0 +1,17 @@ +package es.verdnatura.presentation.composable + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import es.verdnatura.R + +class ImageViewActivityComposable : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + val imageUrl = intent.getStringExtra(getString(R.string.url)) ?: "" + val title = intent.getStringExtra(getString(R.string.title)) ?: "" + ImageViewScreen(imageUrl = imageUrl, titleToolBar = title, onBackClick = { finish() }) + } + } +} diff --git a/app/src/main/java/es/verdnatura/presentation/composable/ImageViewComposable.kt b/app/src/main/java/es/verdnatura/presentation/composable/ImageViewComposable.kt new file mode 100644 index 00000000..5ada753f --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/composable/ImageViewComposable.kt @@ -0,0 +1,59 @@ +package es.verdnatura.presentation.composable + +import android.widget.ImageView +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.bumptech.glide.Glide + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ImageViewScreen(imageUrl: String, titleToolBar:String ="",onBackClick: () -> Unit ) { + + CustomToolbar( + title = titleToolBar, + subtitle = "", + showBackButton = true, + showSwitch = false, + iconList = listOf(), + onBackClick = onBackClick , + onSwitchChange = { } + ) + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top + ) { + + Spacer(modifier = Modifier.height(16.dp)) + GlideImage(imageUrl = imageUrl) + } +} + +@Composable +fun GlideImage(imageUrl: String) { + androidx.compose.ui.viewinterop.AndroidView( + factory = { context -> + ImageView(context).apply { + Glide.with(context) + .load(imageUrl) + .into(this) + } + }, + modifier = Modifier.fillMaxSize() + ) +} + +@Preview(showBackground = true) +@Composable +fun DefaultPreview() { + ImageViewScreen(imageUrl = "https://example.com/image.jpg", "titleToolbar") {} +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/articulo/fragment/ImageViewActivity.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/articulo/fragment/ImageViewActivity.kt index e415bc01..2cd3544f 100644 --- a/app/src/main/java/es/verdnatura/presentation/view/feature/articulo/fragment/ImageViewActivity.kt +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/articulo/fragment/ImageViewActivity.kt @@ -6,26 +6,21 @@ import es.verdnatura.domain.toast import es.verdnatura.presentation.base.BaseActivity import es.verdnatura.presentation.common.loadUrl -class ImageViewActivity : BaseActivity(){ +class ImageViewActivity : BaseActivity() { override fun getLayoutId(): Int = R.layout.activity_imageview - - override fun init() { binding.mainToolbar.toolbarTitle.text = intent.getStringExtra(getString(R.string.title)) try { binding.imgView.loadUrl(intent.getStringExtra(getString(R.string.url))!!) - }catch(ex:Exception){ + } catch (ex: Exception) { getString(R.string.errorImage).toast(this) finish() } - binding.mainToolbar.backButton.setOnClickListener { finish() } } - - } diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/articulo/fragment/ItemCardFragment.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/articulo/fragment/ItemCardFragment.kt index 7509fb19..1633c35d 100644 --- a/app/src/main/java/es/verdnatura/presentation/view/feature/articulo/fragment/ItemCardFragment.kt +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/articulo/fragment/ItemCardFragment.kt @@ -27,6 +27,7 @@ import es.verdnatura.presentation.common.ToolBarAdapterTooltip import es.verdnatura.presentation.common.hideKeyboard import es.verdnatura.presentation.common.itemScanValue import es.verdnatura.presentation.common.loadUrl +import es.verdnatura.presentation.composable.ImageViewActivityComposable import es.verdnatura.presentation.view.component.CustomDialogDynamicButtons import es.verdnatura.presentation.view.component.CustomDialogInput import es.verdnatura.presentation.view.component.CustomDialogList @@ -272,7 +273,9 @@ class ItemCardFragment( } binding.itemcardImage.setOnClickListener { - val i = Intent(activity, ImageViewActivity::class.java) + //JETPACKCOMPOSE + // val i = Intent(activity, ImageViewActivity::class.java) + val i = Intent(activity, ImageViewActivityComposable::class.java) i.putExtra(getString(R.string.url), urlLarge) i.putExtra(getString(R.string.title), titleImage) startActivity(i) diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 332640bd..d2b71579 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -40,6 +40,10 @@ 4dp + + 18sp + 16sp + 96sp 60sp diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b3fef6f8..b30bffab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,4 +1,5 @@ [versions] +activityCompose = "1.9.2" androidImagePicker = "3.0.0-beta5" appcompat = "1.7.0" constraintlayout = "2.2.0" @@ -12,10 +13,13 @@ fragmentKtx = "1.8.5" glide = "4.16.0" ink = "1.0.0" koin = "2.1.6" +koinAndroidxCompose = "3.5.3" kotlinStdlibJdk7 = "2.0.0" legacySupportV4 = "1.0.0" lifecycleExtensions = "2.2.0" +lifecycleViewmodelCompose = "2.8.5" lifecycleViewmodelKtx = "2.8.7" +lottieCompose = "6.3.0" lottieVersion = "3.4.0" material = "1.12.0" navigationFragmentKtx = "2.8.6" @@ -32,11 +36,14 @@ androidGradlePlugin = "8.7.3" kotlin = "2.0.20" googleServices = "4.4.2" firebaseCrashlytics = "3.0.3" +junit = "4.12" [libraries] #pickerImage android-image-picker = { module = "com.github.esafirm:android-image-picker", version.ref = "androidImagePicker" } #android +androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" } +androidx-adaptive = { module = "androidx.compose.material3.adaptive:adaptive" } androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" } @@ -48,7 +55,12 @@ androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref androidx-legacy-support-v4 = { module = "androidx.legacy:legacy-support-v4", version.ref = "legacySupportV4" } androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycleExtensions" } androidx-lifecycle-livedata-ktx = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycleViewmodelKtx" } +androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" } androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } +androidx-material = { module = "androidx.compose.material:material" } +androidx-material-icons-core = { module = "androidx.compose.material:material-icons-core" } +androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" } +androidx-material3 = { module = "androidx.compose.material3:material3" } androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigationUiKtx" } androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" } #room @@ -56,10 +68,18 @@ androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomCompiler" } #ui androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomCompiler" } +androidx-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata" } +androidx-ui = { module = "androidx.compose.ui:ui" } +androidx-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" } +androidx-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" } +androidx-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } +androidx-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" } converter-scalars = { module = "com.squareup.retrofit2:converter-scalars", version.ref = "retrofit" } #qr core = { module = "com.google.zxing:core", version.ref = "core" } +koin-androidx-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koinAndroidxCompose" } +lottie-compose = { module = "com.airbnb.android:lottie-compose", version.ref = "lottieCompose" } zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroidEmbedded" } #analytics firebase-analytics = { module = "com.google.firebase:firebase-analytics", version.ref = "firebaseAnalyticsKtx" } @@ -90,8 +110,9 @@ androidGradlePlugin = { module = "com.android.tools.build:gradle", version.ref = kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } googleServices = { module = "com.google.gms:google-services", version.ref = "googleServices" } firebaseCrashlyticsGradle = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebaseCrashlytics" } +junit = { group = "junit", name = "junit", version.ref = "junit" } [plugins] google-devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "googleDevtoolsKsp" } -#jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" } -#compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } \ No newline at end of file +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }