You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter开发安卓旅行应用:圆形Toggle Button实现需求求助

双圆形Toggle Button(FROM/TO)实现方案

Android 实现(Jetpack Compose)

核心思路

通过状态变量控制选中状态,结合自定义圆形可点击组件或修改RadioButton样式,点击时触发页面跳转逻辑。

基础RadioButton样式实现

import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

fun FromToToggle(onPageChange: (String) -> Unit) {
    val selectedOption = remember { mutableStateOf("FROM") }
    
    Row(verticalAlignment = Alignment.CenterVertically) {
        // FROM 选项
        Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(end = 16.dp)) {
            RadioButton(
                selected = selectedOption.value == "FROM",
                onClick = {
                    selectedOption.value = "FROM"
                    onPageChange("FROM")
                }
            )
            Text(text = "FROM", modifier = Modifier.padding(start = 4.dp))
        }
        
        // TO 选项
        Row(verticalAlignment = Alignment.CenterVertically) {
            RadioButton(
                selected = selectedOption.value == "TO",
                onClick = {
                    selectedOption.value = "TO"
                    onPageChange("TO")
                }
            )
            Text(text = "TO", modifier = Modifier.padding(start = 4.dp))
        }
    }
}

自定义纯圆形按钮样式

如果需要更贴合设计的纯圆形带文字按钮:

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

fun CustomFromToToggle(onPageChange: (String) -> Unit) {
    val selected = remember { mutableStateOf("FROM") }
    
    Row {
        // FROM 圆形按钮
        Box(
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .background(if (selected.value == "FROM") Color.Blue else Color.LightGray)
                .clickable {
                    selected.value = "FROM"
                    onPageChange("FROM")
                },
            contentAlignment = Alignment.Center
        ) {
            Text(text = "F", color = Color.White)
        }
        
        // TO 圆形按钮
        Box(
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .background(if (selected.value == "TO") Color.Blue else Color.LightGray)
                .clickable {
                    selected.value = "TO"
                    onPageChange("TO")
                }
                .padding(start = 16.dp),
            contentAlignment = Alignment.Center
        ) {
            Text(text = "T", color = Color.White)
        }
    }
}

iOS 实现(SwiftUI)

核心思路

用@State变量管理选中状态,自定义圆形按钮组件,点击时更新导航路径跳转到对应页面。

基础单选按钮样式实现

import SwiftUI

struct FromToToggleView: View {
    @State private var selectedOption: String = "FROM"
    var onPageChange: (String) -> Void
    
    var body: some View {
        HStack(spacing: 16) {
            HStack(spacing: 4) {
                RadioButton(selected: $selectedOption, option: "FROM")
                Text("FROM")
            }
            
            HStack(spacing: 4) {
                RadioButton(selected: $selectedOption, option: "TO")
                Text("TO")
            }
        }
        .onChange(of: selectedOption) { newValue in
            onPageChange(newValue)
        }
    }
}

// 自定义RadioButton组件
struct RadioButton: View {
    @Binding var selected: String
    let option: String
    
    var body: some View {
        Button(action: {
            selected = option
        }) {
            Circle()
                .stroke(selected == option ? Color.blue : Color.gray, lineWidth: 2)
                .background(
                    Circle()
                        .fill(selected == option ? Color.blue : Color.clear)
                        .frame(width: 12, height: 12)
                )
                .frame(width: 24, height: 24)
        }
    }
}

自定义纯圆形按钮样式

struct CustomFromToToggle: View {
    @State private var selected: String = "FROM"
    var onPageChange: (String) -> Void
    
    var body: some View {
        HStack(spacing: 16) {
            Button(action: {
                selected = "FROM"
                onPageChange("FROM")
            }) {
                Circle()
                    .fill(selected == "FROM" ? Color.blue : Color.lightGray)
                    .frame(width: 40, height: 40)
                    .overlay(Text("F").foregroundColor(.white))
            }
            
            Button(action: {
                selected = "TO"
                onPageChange("TO")
            }) {
                Circle()
                    .fill(selected == "TO" ? Color.blue : Color.lightGray)
                    .frame(width: 40, height: 40)
                    .overlay(Text("T").foregroundColor(.white))
            }
        }
    }
}

页面跳转逻辑补充

  • Android:在onPageChange回调中使用NavController完成导航:
    // 假设已配置NavHost
    FromToToggle { page ->
        navController.navigate(page.lowercase())
    }
    
  • iOS:通过NavigationStack的路径更新完成页面跳转:
    struct MainView: View {
        @State private var path = NavigationPath()
        
        var body: some View {
            NavigationStack(path: $path) {
                CustomFromToToggle { page in
                    path.append(page)
                }
                .navigationDestination(for: String.self) { page in
                    page == "FROM" ? FromView() : ToView()
                }
            }
        }
    }
    

内容的提问来源于stack exchange,提问作者ubaid khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 12:12:07