Guilherme Delgado
12/29/2025, 10:43 AMView inside a UIViewController using UIHostingController, and then presenting that controller inside a Jetpack Compose UIKitViewController . Even though I set opaque = false, the SwiftUI content always appears with an opaque background. Why? 🧵Guilherme Delgado
12/29/2025, 10:44 AMvar body: some View {
Button(action: { shuffle() }) {
Text("Shuffle")
.font(.body)
.foregroundColor(.white)
.padding(.horizontal, 20)
.padding(.vertical, 10)
}
.buttonStyle(PillButtonStyle())
}
struct PillButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.background(
Capsule()
.fill(Color.blue)
)
.scaleEffect(configuration.isPressed ? 0.96 : 1)
.opacity(configuration.isPressed ? 0.85 : 1)
}
}
The SwiftUI view is wrapped like this:
private class ButtonViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let swiftUIView = ButtonView()
let hostingController = UIHostingController(rootView: swiftUIView)
addChild(hostingController)
view.addSubview(hostingController.view)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
hostingController.view.topAnchor.constraint(equalTo: view.topAnchor),
hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
hostingController.didMove(toParent: self)
}
}
Note: currently I’m only using UIHostingController(rootView: swiftUIView) since the remaining configurations seem to be ignored:
struct ComposeView: UIViewControllerRepresentable {
let controller: UIViewController
func makeUIViewController(context: Context) -> UIViewController {
MainViewControllerKt.MainViewController(controller: controller)
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
struct ContentView: View {
var body: some View {
ComposeView(controller: UIHostingController(rootView: ButtonView(onClick: { })))
}
On the Compose side, I’m using:
ComposeUIViewController(configure = { opaque = false }) {
Box(contentAlignment = Alignment.Center) {
Crossfade(targetState = state) {
...
}
UIKitViewController(
factory = { controller },
)
}Guilherme Delgado
12/29/2025, 11:09 AMstruct View: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
let controller = UIHostingController(rootView: ButtonView(onClick: {}))
controller.view.backgroundColor = .clear
return controller
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
struct ContentView: View {
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
View()
.frame(width: 98, height: 40)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
}
}
Which makes me believe the problem is on the Compose side.Guilherme Delgado
12/29/2025, 11:15 AMGuilherme Delgado
12/29/2025, 2:08 PMcontroller.view.backgroundColor = UIColor.clearColor inside
UIKitViewController(
factory
from Compose, otherwise it will ignore the configurations from Swift. I believe this could be a bug, I’ve opened an issue about this too: https://youtrack.jetbrains.com/issue/CMP-9469/SwiftUI-background-transparency-configured[…]stingController-is-ignored-by-Compose-UIKitViewController