-2

problem gifAs you can see in the gif, when I drop down, the view below is pushed out. I want the dropdown to be above the view below without being pushed out. How can I do this?

In particular, I'd like to have the animation be as smooth as it is now.

I tried using DropdownMenu and PopUp, but I couldn't get the results I wanted. In particular, using PopUp seemed to work, but then failed.

@Composable
fun RewardTypeDropdown(
    modifier: Modifier = Modifier,
    selectedText: String,
    onSelectedChange: (String) -> Unit
) {
    var expanded by remember { mutableStateOf(false) }

    val options = listOf(
        "선착순",
        "직접 선정 (1인)",
        "순위 선정 (다수)"
    )

    Column(
        modifier = modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(12.dp))
            .background(Color(0xFF2C2C2C))
            .animateContentSize(
                animationSpec = spring(
                    dampingRatio = Spring.DampingRatioNoBouncy,
                    stiffness = Spring.StiffnessMediumLow
                )
            )
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { expanded = !expanded }
                .padding(horizontal = 12.dp, vertical = 10.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = selectedText,
                modifier = Modifier.weight(1f),
                style = MaterialTheme.typography.bodyMedium,
                color = Color.LightGray
            )

            Icon(
                painter = painterResource(
                    if (expanded) R.drawable.ic_launcher_background
                    else R.drawable.ic_launcher_background
                ),
                contentDescription = null,
                tint = Color.LightGray
            )
        }

        if (expanded) {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
            ) {
                options.forEach { option ->
                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .clickable {
                                onSelectedChange(option)
                                expanded = false
                            }
                            .padding(horizontal = 16.dp, vertical = 12.dp),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Text(
                            text = option,
                            style = MaterialTheme.typography.bodyMedium,
                            color = if (option == selectedText) {
                                Color.White
                            } else {
                                Color.LightGray
                            }
                        )
                    }
                }
            }
        }
    }
}

@Composable
fun CreateDemandScreen(
    modifier: Modifier = Modifier,
    padding: PaddingValues,
    onPopBackStack: () -> Unit
) {
    var isContentPublic by remember { mutableStateOf(false) }
    var rewardType by remember { mutableStateOf("선착순") }

    var title by remember { mutableStateOf("") }
    var content by remember { mutableStateOf("") }
    var tag by remember { mutableStateOf("") }

    Column(
        modifier = modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .padding(padding)
            .verticalScroll(rememberScrollState())
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(start = 16.dp, end = 16.dp, top = 10.dp)
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(48.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_launcher_background),
                    contentDescription = null,
                    modifier = Modifier
                        .size(24.dp)
                        .clickable { onPopBackStack() }
                )
                Spacer(Modifier.width(12.dp))
                Text(
                    text = "디맨드 작성",
                    style = MaterialTheme.typography.titleMedium,
                    fontWeight = FontWeight.Bold
                )
            }

            Spacer(Modifier.height(32.dp))
        }

        OutlinedTextField(
            value = title,
            onValueChange = { title = it },
            singleLine = false,
            placeholder = { Text("제목을 입력해주세요.") },
            modifier = Modifier.fillMaxWidth()
        )

        HorizontalDivider(
            modifier = Modifier.height(1.dp),
            color = Color.DarkGray
        )

        OutlinedTextField(
            value = content,
            onValueChange = { content = it },
            singleLine = false,
            placeholder = { Text("요청 사항들을 자세히 입력해주세요.") },
            modifier = Modifier
                .fillMaxWidth()
                .heightIn(min = 120.dp)
        )

        HorizontalDivider(
            modifier = Modifier.height(1.dp),
            color = Color.DarkGray
        )

        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            Icon(
                modifier = Modifier
                    .size(24.dp)
                    .clickable {},
                painter = painterResource(id = R.drawable.ic_launcher_background),
                contentDescription = null
            )
            Icon(
                modifier = Modifier
                    .size(24.dp)
                    .clickable {},
                painter = painterResource(id = R.drawable.ic_launcher_background),
                contentDescription = null
            )
        }

        HorizontalDivider(
            modifier = Modifier.height(1.dp),
            color = Color.DarkGray
        )

        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(start = 16.dp, end = 16.dp)
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 20.dp, bottom = 14.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    text = "태그",
                    modifier = Modifier.padding(end = 10.dp),
                    color = MaterialTheme.colorScheme.onBackground,
                    style = MaterialTheme.typography.bodyMedium,
                    fontWeight = FontWeight.Bold
                )
                Text(
                    text = "*",
                    modifier = Modifier.padding(end = 2.dp),
                    color = MaterialTheme.colorScheme.primary,
                    style = MaterialTheme.typography.bodySmall
                )
                Text(
                    text = "태그는 최대 4개까지 가능합니다.",
                    color = Color.Gray,
                    style = MaterialTheme.typography.bodySmall
                )
            }

            OutlinedTextField(
                value = tag,
                onValueChange = { tag = it },
                singleLine = false,
                placeholder = { Text("태그 입력") },
                modifier = Modifier.fillMaxWidth()
            )

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 14.dp, bottom = 20.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(
                    text = "마감 기한",
                    color = MaterialTheme.colorScheme.onBackground,
                    style = MaterialTheme.typography.bodyMedium,
                    fontWeight = FontWeight.Bold
                )

                Spacer(modifier = Modifier.weight(1f))

                Icon(
                    modifier = Modifier
                        .padding(end = 4.dp)
                        .size(24.dp)
                        .clickable {},
                    painter = painterResource(id = R.drawable.ic_launcher_background),
                    contentDescription = null
                )
            }

            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 14.dp, bottom = 20.dp)
            ) {
                Text(
                    text = "콘텐츠 공개 여부",
                    color = MaterialTheme.colorScheme.onBackground,
                    style = MaterialTheme.typography.bodyMedium,
                    fontWeight = FontWeight.Bold
                )

                Spacer(Modifier.height(16.dp))

                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    Button(
                        modifier = Modifier.weight(1f),
                        onClick = { isContentPublic = false },
                        colors = ButtonDefaults.buttonColors(
                            containerColor = if (!isContentPublic)
                                MaterialTheme.colorScheme.primary
                            else
                                Color.DarkGray
                        )
                    ) {
                        Text("비공개", color = Color.White)
                    }
                    Button(
                        modifier = Modifier.weight(1f),
                        onClick = { isContentPublic = true },
                        colors = ButtonDefaults.buttonColors(
                            containerColor = if (isContentPublic)
                                MaterialTheme.colorScheme.primary
                            else
                                Color.DarkGray
                        )
                    ) {
                        Text("공개", color = Color.White)
                    }
                }

                Spacer(modifier = Modifier.height(16.dp))

                Text(
                    text = "리워드 선정 기준",
                    color = MaterialTheme.colorScheme.onBackground,
                    style = MaterialTheme.typography.bodyMedium,
                    fontWeight = FontWeight.Bold
                )

                Spacer(modifier = Modifier.height(16.dp))

                Test(
                    modifier = Modifier.fillMaxWidth(),
                    selectedText = rewardType,
                    onSelectedChange = { rewardType = it }
                )

                Spacer(modifier = Modifier.height(18.dp))

                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 14.dp, bottom = 16.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    Text(
                        text = "리워드 금액",
                        modifier = Modifier.padding(end = 10.dp),
                        color = MaterialTheme.colorScheme.onBackground,
                        style = MaterialTheme.typography.bodyMedium,
                        fontWeight = FontWeight.Bold
                    )
                    Text(
                        text = "*",
                        modifier = Modifier.padding(end = 2.dp),
                        color = MaterialTheme.colorScheme.primary,
                        style = MaterialTheme.typography.bodySmall
                    )
                    Text(
                        text = "10단위로 리워드 지급이 가능합니다.",
                        color = Color.Gray,
                        style = MaterialTheme.typography.bodySmall
                    )
                }

                Row(
                    modifier = Modifier.fillMaxWidth(),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    Button(onClick = {}) {
                        Icon(
                            painter = painterResource(id = R.drawable.ic_launcher_background),
                            contentDescription = null
                        )
                    }
                    Spacer(Modifier.width(8.dp))
                    Button(onClick = {}) {
                        Icon(
                            painter = painterResource(id = R.drawable.ic_launcher_background),
                            contentDescription = null
                        )
                    }
                }

                Spacer(Modifier.height(20.dp))
            }
        }
    }
}


New contributor
Juco is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
14
  • 1
    Please edit the question to remove all references to R and PoolAosTheme, since we don't have them. If they are relevant for your question (it doesn't seem like they are), then you have to add a minimal version of them as well. Please also clarify what the problem is. The code so far looks good. Make sure the code you provide qualify as a minimal reproducible example. And finally, you talk about a gif, but there is none in the question. Commented Nov 18 at 17:56
  • And the rest of my comment, do you plan to address that as well? Commented Nov 18 at 18:52
  • What I'm wondering is, I want to make UI containers (e.g., Columns and Rows) behave like GIFs, like in DropdownMenu. With DropdownMenu, the container that triggers the click event and the container where the items are created are separate, making it difficult to reproduce a smooth animation effect. With PopUp, positioning is difficult. Is there another way? Since English is unfamiliar to me, I don't know if I'm asking politely or not. ;-; Commented Nov 18 at 18:57
  • 1
    Your English is fine, don't worry. What is missing is the relevant information I asked for in my first comment. Commented Nov 18 at 18:59
  • I've fixed it. Is this okay? Commented Nov 18 at 19:10

1 Answer 1

0

You can use a DropdownMenu where

the menu is displayed in a separate window, on top of other content.

Please try to use it as follows:

@Composable
fun RewardTypeDropdown(
    selectedText: String,
    onSelectedChange: (String) -> Unit
) {
    var expanded by remember { mutableStateOf(false) }

    val options = listOf(
        "Option A",
        "Option B",
        "Option C"
    )

    Box {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clip(RoundedCornerShape(12.dp))
                .background(Color(0xFF2C2C2C))
                .clickable { expanded = true }
                .padding(horizontal = 12.dp, vertical = 10.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = selectedText,
                modifier = Modifier.weight(1f),
                color = Color.LightGray,
                style = MaterialTheme.typography.bodyMedium
            )

            Icon(
                imageVector = Icons.Default.ArrowDropDown,
                contentDescription = null,
                tint = Color.LightGray
            )
        }

        DropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false }
        ) {
            options.forEach { option ->
                DropdownMenuItem(
                    text = {
                        Text(
                            text = option,
                            color = if (option == selectedText) Color.White else Color.LightGray
                        )
                    },
                    onClick = {
                        onSelectedChange(option)
                        expanded = false
                    }
                )
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.