diff --git a/.idea/.gitignore b/.idea/.gitignore
index 26d3352..8f00030 100644
--- a/.idea/.gitignore
+++ b/.idea/.gitignore
@@ -1,3 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
+# GitHub Copilot persisted chat sessions
+/copilot/chatSessions
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 0da7e9f..4183055 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,10 +4,8 @@
diff --git a/app/build.gradle b/app/build.gradle
index c1d7c6b..2b4bb35 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,13 +4,13 @@ plugins {
}
android {
- compileSdk 33
+ compileSdk 34
namespace 'com.canopas.campose.countypickerdemo'
defaultConfig {
applicationId "com.canopas.campose.countypickerdemo"
minSdk 21
- targetSdk 33
+
versionCode 1
versionName "1.0"
@@ -52,17 +52,17 @@ android {
dependencies {
implementation project(":countrypicker")
- implementation 'androidx.core:core-ktx:1.10.1'
+ implementation 'androidx.core:core-ktx:1.13.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
- implementation 'com.google.android.material:material:1.9.0'
+ implementation 'com.google.android.material:material:1.11.0'
implementation platform("androidx.compose:compose-bom:$compose_bom_version")
implementation "androidx.compose.ui:ui"
implementation "androidx.compose.material3:material3"
implementation "androidx.compose.ui:ui-tooling-preview"
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
- implementation 'androidx.activity:activity-compose:1.7.2'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
+ implementation 'androidx.activity:activity-compose:1.9.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
diff --git a/app/src/main/java/com/canopas/campose/jetcountypicker/MainActivity.kt b/app/src/main/java/com/canopas/campose/jetcountypicker/MainActivity.kt
index efd4fcf..2a768e7 100644
--- a/app/src/main/java/com/canopas/campose/jetcountypicker/MainActivity.kt
+++ b/app/src/main/java/com/canopas/campose/jetcountypicker/MainActivity.kt
@@ -3,11 +3,18 @@ package com.canopas.campose.jetcountypicker
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
+import androidx.compose.foundation.clickable
+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.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.RadioButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -16,8 +23,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -25,10 +32,11 @@ 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 com.canopas.campose.countrypicker.CountryPickerBottomSheet
+import com.canopas.campose.countrypicker.CountryPickerView
import com.canopas.campose.countrypicker.CountryTextField
import com.canopas.campose.countrypicker.countryList
import com.canopas.campose.countrypicker.model.Country
+import com.canopas.campose.countrypicker.model.PickerType
import com.canopas.campose.countypickerdemo.R
import com.canopas.campose.jetcountypicker.ui.theme.JetCountyPickerTheme
@@ -38,7 +46,9 @@ class MainActivity : ComponentActivity() {
setContent {
JetCountyPickerTheme {
Surface(color = MaterialTheme.colorScheme.background) {
- SampleCountryPicker()
+ Column {
+ SampleCountryPickerDialog()
+ }
}
}
}
@@ -47,9 +57,12 @@ class MainActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun SampleCountryPicker() {
- var openBottomSheet by rememberSaveable { mutableStateOf(false) }
+fun SampleCountryPickerDialog() {
+ var showCountryPicker by rememberSaveable { mutableStateOf(false) }
var selectedCountry by remember { mutableStateOf(null) }
+ var pickerType by remember {
+ mutableStateOf(PickerType.DIALOG)
+ }
Box {
CountryTextField(
@@ -57,17 +70,53 @@ fun SampleCountryPicker() {
modifier = Modifier
.fillMaxWidth()
.padding(top = 50.dp, start = 40.dp, end = 40.dp),
+ textStyle = MaterialTheme.typography.bodyMedium,
+ labelTextStyle = MaterialTheme.typography.labelMedium,
selectedCountry = selectedCountry,
defaultCountry = countryList(LocalContext.current).firstOrNull { it.code == "IN" },
onShowCountryPicker = {
- openBottomSheet = true
- }, isPickerVisible = openBottomSheet
+ showCountryPicker = true
+ }, isPickerVisible = showCountryPicker
)
}
- if (openBottomSheet) {
- CountryPickerBottomSheet(
- bottomSheetTitle = {
+ Column(horizontalAlignment = Alignment.Start) {
+ Spacer(modifier = Modifier.height(28.dp))
+ Text(
+ text = stringResource(R.string.picker_type),
+ modifier = Modifier.padding(16.dp),
+ style = MaterialTheme.typography.bodyMedium
+ )
+ PickerType.entries.forEach {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .clickable(
+ onClick = {
+ pickerType = it
+ }
+ ),
+ horizontalArrangement = Arrangement.Start,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ RadioButton(
+ selected = pickerType == it,
+ onClick = {
+ pickerType = it
+ }
+ )
+ Text(
+ text = stringResource(it.value),
+ modifier = Modifier.padding(start = 8.dp),
+ style = MaterialTheme.typography.bodyMedium
+ )
+ }
+ }
+ }
+
+ if (showCountryPicker) {
+ CountryPickerView(
+ pickerTitle = {
Text(
modifier = Modifier
.fillMaxWidth()
@@ -78,12 +127,16 @@ fun SampleCountryPicker() {
fontSize = 20.sp
)
},
- containerColor = Color.White,
+ searchFieldTextStyle = MaterialTheme.typography.bodyMedium,
+ placeholderTextStyle = MaterialTheme.typography.labelMedium,
+ countriesTextStyle = MaterialTheme.typography.bodyMedium,
onItemSelected = {
selectedCountry = it
- openBottomSheet = false
- }, onDismissRequest = {
- openBottomSheet = false
+ showCountryPicker = false
+ },
+ pickerType = pickerType,
+ onDismissRequest = {
+ showCountryPicker = false
}
)
}
@@ -93,6 +146,6 @@ fun SampleCountryPicker() {
@Composable
fun DefaultPreview() {
JetCountyPickerTheme {
- SampleCountryPicker()
+ SampleCountryPickerDialog()
}
}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f4b28ae..1ac6a34 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,4 +1,5 @@
JetCountyPicker
Select country
+ Picker Type
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 89abfe8..70015dd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,14 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
- compose_compiler_version = "1.5.0"
- compose_bom_version = "2023.06.01"
+ compose_compiler_version = "1.5.12"
+ compose_bom_version = "2024.04.01"
}
}
plugins {
- id 'com.android.application' version '8.1.0' apply false
- id 'com.android.library' version '8.1.0' apply false
- id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
+ id 'com.android.application' version '8.3.2' apply false
+ id 'com.android.library' version '8.3.2' apply false
+ id 'org.jetbrains.kotlin.android' version '1.9.23' apply false
id 'io.github.gradle-nexus.publish-plugin' version "1.3.0"
}
apply from: "${rootDir}/scripts/publish-root.gradle"
diff --git a/countrypicker/build.gradle b/countrypicker/build.gradle
index d2fcc64..d4a2db0 100644
--- a/countrypicker/build.gradle
+++ b/countrypicker/build.gradle
@@ -11,12 +11,11 @@ ext {
apply from: "${rootDir}/scripts/publish-module.gradle"
android {
- compileSdk 33
+ compileSdk 34
namespace 'com.canopas.campose.countrypicker'
defaultConfig {
minSdk 21
- targetSdk 33
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
@@ -50,9 +49,9 @@ android {
dependencies {
- implementation 'androidx.core:core-ktx:1.10.1'
+ implementation 'androidx.core:core-ktx:1.13.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
- implementation 'com.google.android.material:material:1.9.0'
+ implementation 'com.google.android.material:material:1.11.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
diff --git a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerBottomSheet.kt b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerBottomSheet.kt
index fa7300a..c585be7 100644
--- a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerBottomSheet.kt
+++ b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerBottomSheet.kt
@@ -9,6 +9,8 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.material3.BottomSheetDefaults
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
@@ -25,22 +27,46 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import com.canopas.campose.countrypicker.model.Country
import kotlinx.coroutines.launch
+/**
+ * Composable for displaying a bottom sheet country picker.
+ *
+ * @param sheetState The state of the bottom sheet.
+ * @param shape The shape of the bottom sheet.
+ * @param containerColor The color of the bottom sheet container.
+ * @param contentColor The color of the bottom sheet content.
+ * @param tonalElevation The elevation of the bottom sheet.
+ * @param scrimColor The color of the bottom sheet scrim.
+ * @param bottomSheetTitle The title composable for the bottom sheet.
+ * @param onItemSelected Callback when a country is selected.
+ * @param searchFieldTextStyle The text style for the search field.
+ * @param placeholderTextStyle The text style for the search field placeholder.
+ * @param countriesTextStyle The text style for the countries list.
+ * @param onDismissRequest Callback when the bottom sheet is dismissed.
+ */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CountryPickerBottomSheet(
sheetState: SheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false),
- shape: Shape = BottomSheetDefaults.ExpandedShape,
+ shape: Shape = MaterialTheme.shapes.medium,
containerColor: Color = BottomSheetDefaults.ContainerColor,
contentColor: Color = contentColorFor(containerColor),
tonalElevation: Dp = BottomSheetDefaults.Elevation,
scrimColor: Color = BottomSheetDefaults.ScrimColor,
bottomSheetTitle: @Composable () -> Unit,
onItemSelected: (country: Country) -> Unit,
+ searchFieldTextStyle: TextStyle = LocalTextStyle.current.copy(fontSize = 14.sp),
+ placeholderTextStyle: TextStyle = MaterialTheme.typography.labelMedium.copy(
+ color = Color.Gray,
+ fontSize = 16.sp,
+ ),
+ countriesTextStyle: TextStyle = TextStyle(),
onDismissRequest: () -> Unit
) {
var searchValue by rememberSaveable { mutableStateOf("") }
@@ -57,11 +83,11 @@ fun CountryPickerBottomSheet(
) {
bottomSheetTitle()
- CountrySearchView(searchValue) {
+ CountrySearchView(searchValue, searchFieldTextStyle, placeholderTextStyle) {
searchValue = it
}
- Countries(searchValue) {
+ Countries(searchValue, countriesTextStyle) {
scope.launch {
sheetState.hide()
onItemSelected(it)
@@ -70,9 +96,17 @@ fun CountryPickerBottomSheet(
}
}
+/**
+ * Composable for displaying a list of countries.
+ *
+ * @param searchValue The search value for filtering countries.
+ * @param textStyle The text style for the country list.
+ * @param onItemSelected Callback when a country is selected.
+ */
@Composable
-fun Countries(
+internal fun Countries(
searchValue: String,
+ textStyle: TextStyle = TextStyle(),
onItemSelected: (country: Country) -> Unit
) {
val context = LocalContext.current
@@ -92,21 +126,25 @@ fun Countries(
.clickable { onItemSelected(country) }
.padding(12.dp)
) {
- Text(text = localeToEmoji(country.code))
+ Text(
+ text = localeToEmoji(country.code),
+ style = textStyle
+ )
Text(
text = country.name,
modifier = Modifier
.padding(start = 8.dp)
- .weight(2f)
+ .weight(2f),
+ style = textStyle
)
Text(
text = country.dial_code,
modifier = Modifier
- .padding(start = 8.dp)
+ .padding(start = 8.dp),
+ style = textStyle
)
}
Divider(color = Color.LightGray, thickness = 0.5.dp)
}
}
-
}
diff --git a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerDialog.kt b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerDialog.kt
new file mode 100644
index 0000000..bfe5e41
--- /dev/null
+++ b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerDialog.kt
@@ -0,0 +1,102 @@
+package com.canopas.campose.countrypicker
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.shape.CornerSize
+import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.Dialog
+import androidx.compose.ui.window.DialogProperties
+import com.canopas.campose.countrypicker.model.Country
+import kotlinx.coroutines.launch
+
+
+/**
+ * Composable for displaying a country picker as a dialog.
+ *
+ * @param shape The shape of the dialog.
+ * @param backgroundColor The color of the dialog container.
+ * @param dialogTitle The title composable for the dialog.
+ * @param onItemSelected Callback when a country is selected.
+ * @param searchFieldTextStyle The text style for the search field.
+ * @param placeholderTextStyle The text style for the search field placeholder.
+ * @param countriesTextStyle The text style for the countries list.
+ * @param showFullScreenDialog Whether to show the dialog as a full screen dialog.
+ * @param onDismissRequest Callback when the dialog is dismissed.
+ */
+@Composable
+fun CountryPickerDialog(
+ shape: Shape = MaterialTheme.shapes.small,
+ backgroundColor: Color = MaterialTheme.colorScheme.background,
+ dialogTitle: @Composable () -> Unit,
+ onItemSelected: (country: Country) -> Unit,
+ searchFieldTextStyle: TextStyle = LocalTextStyle.current.copy(fontSize = 14.sp),
+ placeholderTextStyle: TextStyle = MaterialTheme.typography.labelMedium.copy(
+ color = Color.Gray,
+ fontSize = 16.sp,
+ ),
+ countriesTextStyle: TextStyle = TextStyle(),
+ showFullScreenDialog: Boolean = false,
+ onDismissRequest: () -> Unit
+) {
+ var searchValue by rememberSaveable { mutableStateOf("") }
+ val configuration = LocalConfiguration.current
+ val screenHeight = configuration.screenHeightDp.dp
+ val scope = rememberCoroutineScope()
+ val modifier = if (showFullScreenDialog) {
+ Modifier
+ .fillMaxSize()
+ .background(color = backgroundColor)
+ } else {
+ Modifier
+ .wrapContentHeight()
+ .heightIn(max = (screenHeight * 0.85f))
+ .clip(shape = shape)
+ .background(color = backgroundColor, shape)
+ }
+
+ Dialog(
+ onDismissRequest = onDismissRequest,
+ properties = DialogProperties(
+ usePlatformDefaultWidth = !showFullScreenDialog,
+ dismissOnBackPress = true,
+ dismissOnClickOutside = !showFullScreenDialog
+ )
+ ) {
+ Column(
+ modifier = modifier
+ ) {
+ dialogTitle()
+ CountrySearchView(searchValue, searchFieldTextStyle, placeholderTextStyle) {
+ searchValue = it
+ }
+
+ Countries(searchValue, countriesTextStyle) {
+ scope.launch {
+ onDismissRequest()
+ onItemSelected(it)
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerTextField.kt b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerTextField.kt
index d7a83e0..015d96f 100644
--- a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerTextField.kt
+++ b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerTextField.kt
@@ -22,9 +22,24 @@ import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.onClick
import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.text.TextStyle
import com.canopas.campose.countrypicker.model.Country
-@OptIn(ExperimentalMaterial3Api::class)
+/**
+ * Composable for displaying a text field with a country picker.
+ *
+ * @param label The label for the text field.
+ * @param isError Whether the text field should display an error state.
+ * @param modifier The modifier for the text field.
+ * @param shape The shape of the text field.
+ * @param selectedCountry The currently selected country.
+ * @param defaultCountry The default country to display if none is selected.
+ * @param colors The colors for the text field.
+ * @param textStyle The text style for the text field.
+ * @param labelTextStyle The text style for the label.
+ * @param isPickerVisible Whether the country picker bottom sheet is visible.
+ * @param onShowCountryPicker Callback when the country picker is shown.
+ */
@Composable
fun CountryTextField(
label: String = "",
@@ -33,8 +48,9 @@ fun CountryTextField(
shape: Shape = MaterialTheme.shapes.small,
selectedCountry: Country? = null,
defaultCountry: Country? = null,
- colors: TextFieldColors = OutlinedTextFieldDefaults.colors(
- ),
+ colors: TextFieldColors = OutlinedTextFieldDefaults.colors(),
+ textStyle: TextStyle = TextStyle(),
+ labelTextStyle: TextStyle = TextStyle(),
isPickerVisible: Boolean = false,
onShowCountryPicker: () -> Unit
) {
@@ -44,7 +60,6 @@ fun CountryTextField(
defaultCountry ?: countryList(context).first()
}
-
val countryValue = "${defaultSelectedCountry.dial_code} ${defaultSelectedCountry.name}"
OutlinedTextField(
@@ -54,7 +69,8 @@ fun CountryTextField(
}),
readOnly = true,
isError = isError,
- label = { Text(label) },
+ textStyle = textStyle,
+ label = { Text(label, style = labelTextStyle) },
value = if (selectedCountry == null) countryValue else "${selectedCountry.dial_code} ${selectedCountry.name}",
onValueChange = {},
colors = colors,
@@ -71,9 +87,14 @@ fun CountryTextField(
)
}
-fun Modifier.expandable(
+/**
+ * Modifier for making a composable expandable when clicked.
+ *
+ * @param onExpandedChange Callback when the expandable state changes.
+ */
+internal fun Modifier.expandable(
onExpandedChange: () -> Unit
-) = pointerInput(Unit) {
+) = this.pointerInput(Unit) {
awaitEachGesture {
var event: PointerEvent
do {
diff --git a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerView.kt b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerView.kt
new file mode 100644
index 0000000..1ae724d
--- /dev/null
+++ b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountryPickerView.kt
@@ -0,0 +1,103 @@
+package com.canopas.campose.countrypicker
+
+import androidx.compose.material3.BottomSheetDefaults
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.SheetState
+import androidx.compose.material3.contentColorFor
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.sp
+import com.canopas.campose.countrypicker.model.Country
+import com.canopas.campose.countrypicker.model.PickerType
+
+/**
+ * Composable for displaying a country picker.
+ *
+ * @param sheetState The state of the bottom sheet.
+ * @param shape The shape of the bottom sheet or dialog.
+ * @param containerColor The color of the bottom sheet or dialog container.
+ * @param contentColor The color of the bottom sheet items.
+ * **[For bottom sheet only].**
+ * @param tonalElevation The elevation of the bottom sheet
+ * **[For bottom sheet only].**
+ * @param scrimColor Color of the scrim that obscures content when the bottom sheet is open.
+ * **[For bottom sheet only].**
+ * @param pickerTitle The title composable for the bottom sheet or dialog.
+ * @param onItemSelected Callback when a country is selected.
+ * @param searchFieldTextStyle The text style for the search field.
+ * @param placeholderTextStyle The text style for the search field placeholder.
+ * @param countriesTextStyle The text style for the countries list.
+ * @param pickerType The type of picker to display (bottom sheet, full-screen dialog, or dialog).
+ * Also see [PickerType].
+ * @param onDismissRequest Callback when the bottom sheet or dialog is dismissed.
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun CountryPickerView(
+ sheetState: SheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false),
+ shape: Shape = MaterialTheme.shapes.medium,
+ containerColor: Color = MaterialTheme.colorScheme.background,
+ contentColor: Color = contentColorFor(containerColor),
+ tonalElevation: Dp = BottomSheetDefaults.Elevation,
+ scrimColor: Color = BottomSheetDefaults.ScrimColor,
+ pickerTitle: @Composable () -> Unit,
+ onItemSelected: (country: Country) -> Unit,
+ searchFieldTextStyle: TextStyle = LocalTextStyle.current.copy(fontSize = 14.sp),
+ placeholderTextStyle: TextStyle = MaterialTheme.typography.labelMedium.copy(
+ color = Color.Gray,
+ fontSize = 16.sp,
+ ),
+ countriesTextStyle: TextStyle = TextStyle(),
+ pickerType: PickerType = PickerType.BOTTOM_SHEET,
+ onDismissRequest: () -> Unit
+) {
+ when(pickerType) {
+ PickerType.BOTTOM_SHEET -> {
+ CountryPickerBottomSheet(
+ sheetState = sheetState,
+ shape = shape,
+ containerColor = containerColor,
+ contentColor = contentColor,
+ tonalElevation = tonalElevation,
+ scrimColor = scrimColor,
+ bottomSheetTitle = pickerTitle,
+ onItemSelected = onItemSelected,
+ searchFieldTextStyle = searchFieldTextStyle,
+ placeholderTextStyle = placeholderTextStyle,
+ countriesTextStyle = countriesTextStyle,
+ onDismissRequest = onDismissRequest
+ )
+ }
+ PickerType.FULL_SCREEN_DIALOG -> {
+ CountryPickerDialog(
+ shape = shape,
+ backgroundColor = containerColor,
+ onItemSelected = onItemSelected,
+ dialogTitle = pickerTitle,
+ searchFieldTextStyle = searchFieldTextStyle,
+ placeholderTextStyle = placeholderTextStyle,
+ countriesTextStyle = countriesTextStyle,
+ showFullScreenDialog = true,
+ onDismissRequest = onDismissRequest
+ )
+ }
+ PickerType.DIALOG -> {
+ CountryPickerDialog(
+ shape = shape,
+ backgroundColor = containerColor,
+ onItemSelected = onItemSelected,
+ dialogTitle = pickerTitle,
+ searchFieldTextStyle = searchFieldTextStyle,
+ placeholderTextStyle = placeholderTextStyle,
+ countriesTextStyle = countriesTextStyle,
+ onDismissRequest = onDismissRequest
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountrySearchView.kt b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountrySearchView.kt
index 7e8ba57..cf8a625 100644
--- a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountrySearchView.kt
+++ b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountrySearchView.kt
@@ -12,11 +12,8 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.rounded.Cancel
-import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
-import androidx.compose.material3.LocalTextStyle
-import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
@@ -25,16 +22,27 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-@OptIn(ExperimentalMaterial3Api::class)
+/**
+ * Composable for displaying a search field.
+ *
+ * @param searchValue The current search value.
+ * @param searchFieldTextStyle The text style for the search field.
+ * @param placeholderTextStyle The text style for the placeholder.
+ * @param onSearch Callback when the search value changes.
+ */
@Composable
-fun CountrySearchView(searchValue: String, onSearch: (searchValue: String) -> Unit) {
-
+internal fun CountrySearchView(
+ searchValue: String,
+ searchFieldTextStyle: TextStyle = TextStyle(),
+ placeholderTextStyle: TextStyle = TextStyle(),
+ onSearch: (searchValue: String) -> Unit
+) {
val focusManager = LocalFocusManager.current
Row {
@@ -48,14 +56,10 @@ fun CountrySearchView(searchValue: String, onSearch: (searchValue: String) -> Un
Color.LightGray.copy(0.6f), shape = RoundedCornerShape(10.dp)
), value = searchValue, onValueChange = {
onSearch(it)
- }, textStyle = LocalTextStyle.current.copy(
- fontSize = 14.sp
- ), placeholder = {
+ }, textStyle = searchFieldTextStyle, placeholder = {
Text(
text = stringResource(R.string.search_text),
- style = MaterialTheme.typography.labelMedium,
- color = Color.Gray,
- fontSize = 16.sp,
+ style = placeholderTextStyle
)
}, singleLine = true,
leadingIcon = {
@@ -96,5 +100,5 @@ fun CountrySearchView(searchValue: String, onSearch: (searchValue: String) -> Un
@Preview
@Composable
fun PreviewSearchView() {
- CountrySearchView("search", {})
+ CountrySearchView("search", onSearch = {})
}
\ No newline at end of file
diff --git a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountyUtils.kt b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountyUtils.kt
index 2d4e4ff..1672d79 100644
--- a/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountyUtils.kt
+++ b/countrypicker/src/main/java/com/canopas/campose/countrypicker/CountyUtils.kt
@@ -8,6 +8,12 @@ import com.squareup.moshi.Types
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import java.io.IOException
+/**
+ * Retrieves a list of countries from a JSON file stored in the assets directory.
+ *
+ * @param context The context used to access the assets directory.
+ * @return A mutable list of countries parsed from the JSON file, or an empty list if parsing fails.
+ */
fun countryList(context: Context): MutableList {
val moshi =
Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
@@ -16,16 +22,16 @@ fun countryList(context: Context): MutableList {
val jsonAdapter: JsonAdapter> = moshi.adapter(personListType)
val jsonFileString = getJsonDataFromAsset(context, "Countries.json")
- return jsonAdapter.fromJson(jsonFileString) ?: mutableListOf()
+ return jsonFileString?.let { jsonAdapter.fromJson(it) } ?: mutableListOf()
}
-fun localeToEmoji(countryCode: String): String {
+internal fun localeToEmoji(countryCode: String): String {
val firstLetter = Character.codePointAt(countryCode, 0) - 0x41 + 0x1F1E6
val secondLetter = Character.codePointAt(countryCode, 1) - 0x41 + 0x1F1E6
return String(Character.toChars(firstLetter)) + String(Character.toChars(secondLetter))
}
-fun getJsonDataFromAsset(context: Context, fileName: String): String? {
+internal fun getJsonDataFromAsset(context: Context, fileName: String): String? {
val jsonString: String
try {
jsonString = context.assets.open(fileName).bufferedReader().use { it.readText() }
@@ -36,7 +42,7 @@ fun getJsonDataFromAsset(context: Context, fileName: String): String? {
return jsonString
}
-fun List.searchCountryList(countryName: String): MutableList {
+internal fun List.searchCountryList(countryName: String): MutableList {
val countryList = mutableListOf()
this.forEach {
if (it.name.lowercase().contains(countryName.lowercase()) ||
diff --git a/countrypicker/src/main/java/com/canopas/campose/countrypicker/model/PickerType.kt b/countrypicker/src/main/java/com/canopas/campose/countrypicker/model/PickerType.kt
new file mode 100644
index 0000000..adf0a0a
--- /dev/null
+++ b/countrypicker/src/main/java/com/canopas/campose/countrypicker/model/PickerType.kt
@@ -0,0 +1,12 @@
+package com.canopas.campose.countrypicker.model
+
+import com.canopas.campose.countrypicker.R
+
+/**
+ * Enum class for the type of picker to display.
+ */
+enum class PickerType(val value: Int) {
+ DIALOG(R.string.picker_type_dialog),
+ FULL_SCREEN_DIALOG(R.string.picker_type_full_screen),
+ BOTTOM_SHEET(R.string.picker_type_bottom_sheet)
+}
\ No newline at end of file
diff --git a/countrypicker/src/main/res/values/strings.xml b/countrypicker/src/main/res/values/strings.xml
index 011989d..ba7bdd0 100644
--- a/countrypicker/src/main/res/values/strings.xml
+++ b/countrypicker/src/main/res/values/strings.xml
@@ -1,4 +1,7 @@
Search
+ Dialog
+ Full Screen Dialog
+ Bottom Sheet
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0638b3f..07c5c61 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Fri Aug 11 12:20:35 IST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists