Search code examples
androidkotlinandroid-alertdialogandroid-jetpack-compose

How to use custom AlertDialog properly in jetpack compose?


I have TeamCard which shows teamname only.

@Composable
fun TeamCard(team: Teams , openLink :()-> Unit) {
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            ..
            .clickable { openLink()}
    ) {
        Row(
           ..
        ) {
           ..
        }
    }
}

And we have a TeamScreen where all teams are showing

@Composable
fun TeamsScreen() {

    val openDialog = remember { mutableStateOf(false) }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(color = darkBackground),
        contentAlignment = Alignment.Center
    ) {

        AppDialog( link = "https://www.fcbarcelona.com/en/ ", dialogState = openDialog.value)
        Image(.. )
       Row(..) {
        Column(
                         verticalArrangement = Arrangement.spacedBy(20.dp)
            ) {
                TeamCard(team = allTeamsLists[0]){openDialog.value = true }
                TeamCard(team = allTeamsLists[1]){ openDialog.value = true}
                TeamCard(team = allTeamsLists[2]){ openDialog.value = true}
            }
             Column(
            verticalArrangement = Arrangement.spacedBy(20.dp)
            ) {
                TeamCard(team = allTeamsLists[3]){}
                TeamCard(team = allTeamsLists[4]){}
            }
        }
    }
}

Now when i want to click on any of TeamCard there should a custom AlertDialog popUp with link and cross button to dismiss it.

@Composable
fun AppDialog(
    link: String,
    modifier: Modifier = Modifier,
    dialogState: Boolean = false,
    onDialogPositiveButtonClicked: (() -> Unit)? = null,
    onDialogStateChange: ((Boolean) -> Unit)? = null,
    onDismissRequest: (() -> Unit)? = null,
) {

    val buttonPaddingAll = 8.dp
    val dialogShape = RoundedCornerShape(16.dp)
    val context = LocalContext.current

    if (dialogState) {
        AlertDialog(
            onDismissRequest = {
                Toast.makeText(context, "outside dialog is clicked ", Toast.LENGTH_SHORT).show()
                onDialogStateChange?.invoke(true)
                onDismissRequest?.invoke()
            },
            title = null,
            text = null,
            buttons = {


                Row(
                    modifier = Modifier.padding(all = buttonPaddingAll),
                    horizontalArrangement = Arrangement.Center
                ) {
                    TextButton(
                        modifier = Modifier,
                        onClick = {
                            Toast.makeText(context, "link  is clicked ", Toast.LENGTH_SHORT).show()

                            //Open link to web
                        }
                    ) {
                        Text(text = link, color = MaterialTheme.colors.onSurface)
                    }
                    Icon(
                        imageVector = Icons.Default.Add.also { rotationMatrix(45f) },
                        contentDescription = null,
                        modifier = Modifier
                            .rotate(45f)
                            .clickable {
                                Toast.makeText(context, "cancle is clicked ", Toast.LENGTH_SHORT).show()
                                !dialogState
                            },
                        tint = Color.Black.copy(alpha = 0.8f)
                    )

                }

            },
            properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true),
            modifier = modifier,
            shape = dialogShape
        )
    }
}

And allTeamsLists have a list of all teams link and team name associated example.

Teams( R.drawable.logo_1, "Real Madrid" , R.drawable.player1, "https://www.realmadrid.com/ " , R.drawable.blue_hands)  

I am not able to properly setup this, please suggest me better way.

Also every time I click particular teamcard, alert is showing with that link which associated with it.


Solution

  • You store a simple boolean value indicating whether the alert is currently open. This information is not enough if you need to display a specific URL.

    Instead, store an optional URL of the selected command and display the alert if it is not null.

    I also suggest that you avoid repeating code as you do now. Instead of putting multiple Column-s in a Row and filling them with elements manually, you can use LazyVerticalGrid:

    val dialogUrl by remember { mutableStateOf<String?>(null) }
    if (dialogUrl != null) {
        AppDialog(
            dialogUrl,
            onDismissRequest = { 
                dialogUrl = null 
            },
        )
    } 
    LazyVerticalGrid(
        cells = GridCells.Fixed(3),
        verticalArrangement = Arrangement.spacedBy(20.dp),
    ) {
        items(allTeamsLists) { team ->
            TeamCard(team = team){
                dialogUrl = team.url
            }
        }
    }