如何在 Jetpack Compose 中显示透明背景的底页?

问题描述 投票:0回答:3

我的应用程序由主屏幕组成,在这个屏幕上,有一个按钮,当用户点击它时,他们会导航到登录底页。

我打算在应用程序的其他地方使用这个登录底页,所以我更喜欢把它做成一个单独的屏幕,然后从主页导航到登录。

希望将主屏幕显示为登录屏幕的背景。我的意思是登录底部表单的主要内容应该是空的和透明的,以便将主屏幕视为背景。但是显示的不是背景的主屏幕,而是白色背景。

这是我的代码:

登录屏幕:

@Composable
fun LoginScreen(
    loginViewModel: LoginViewModel = hiltViewModel()
) {
    val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
    )
    val coroutineScope = rememberCoroutineScope()

    BottomSheetScaffold(
        scaffoldState = bottomSheetScaffoldState,
        sheetContent = {
            LoginContent()
        },
        sheetPeekHeight = 400.dp,
        sheetShape = RoundedCornerShape(topEnd = 52.dp, topStart = 52.dp),
        backgroundColor = Color.Transparent
    ) {
        Box(modifier = Modifier.fillMaxSize().background(color = Color.Transparent)) {

        }
    }
}

主屏幕

@Composable
fun HomeScreen(
    modifier: Modifier = Modifier,
    viewModel: HomeViewModel = hiltViewModel(),
) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(color = Color.White)
    ) {
        somecontent 
        ...
        ...
        ...
        Button(onClick = {
            viewModel.navigate(
                LoginDestination.route()
            )

        }) {
            Text("Go to the login screen")
        }
    }
}

我这样使用导航:

fun interface NavigationDestination {

    fun route(): String
    val arguments: List<NamedNavArgument>
        get() = emptyList()

    val deepLinks: List<NavDeepLink>
        get() = emptyList()
} 

然后登录目标覆盖它:

object LoginDestination : NavigationDestination {
    override fun route(): String = "login"
}

这里是导航器的实现:

@Singleton
internal class ClientNavigatorImpl @Inject constructor() : ClientNavigator {

    private val navigationEvents = Channel<NavigatorEvent>()
    override val destinations = navigationEvents.receiveAsFlow()

    override fun navigateUp(): Boolean =
        navigationEvents.trySend(NavigatorEvent.NavigateUp).isSuccess

    override fun popBackStack(): Boolean =
        navigationEvents.trySend(NavigatorEvent.PopBackStack).isSuccess

    override fun navigate(route: String, builder: NavOptionsBuilder.() -> Unit): Boolean =
        navigationEvents.trySend(NavigatorEvent.Directions(route, builder)).isSuccess
}

导航器事件是:

sealed class NavigatorEvent {
    object NavigateUp : NavigatorEvent()
    object PopBackStack : NavigatorEvent()
    class Directions(
        val destination: String,
        val builder: NavOptionsBuilder.() -> Unit
    ) : NavigatorEvent()
}

kotlin android-jetpack-compose bottom-sheet
3个回答
2
投票

您尝试显示 LoginScreen 的方式不会像您预期的那样工作,因为当您导航到 LoginScreen 时,就像打开一个新屏幕一样,然后将 HomeScreen 添加到后台堆栈,而不是在您的 LoginScreen 后面显示。要让它工作,请像这样尝试:

@Composable
fun HomeScreen(
    modifier: Modifier = Modifier,
    viewModel: HomeViewModel = hiltViewModel(),
) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(color = Color.White)
    ) {
        Button(onClick = {
            //TODO: Add functionality
        }) {
            Text("Go to the login screen")
        }
    }
}

并更改 LoginScreen 参数,您可以给它一个 Composable:

@Composable
fun LoginScreen(
    loginViewModel: LoginViewModel = hiltViewModel(),
    screen: @Composable (() -> Unit)
) {
    val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
    )
    val coroutineScope = rememberCoroutineScope()

    BottomSheetScaffold(
        scaffoldState = bottomSheetScaffoldState,
        sheetContent = {
            //The Login Content needs to be here
*EDIT*

            BackHandler(enabled = true) {
              coroutineScope.launch {   
                 bottomSheetScaffoldState.bottomSheetState.collapse()
              }
            }
*EDIT*
        },
        sheetPeekHeight = 400.dp,
        sheetShape = RoundedCornerShape(topEnd = 52.dp, topStart = 52.dp),
        backgroundColor = Color.Transparent
    ) {
        screen() //Adds the content which is shown on the Screen behind bottomsheet
    }
}

然后像这样使用它:

LoginScreen( /*YourLoginViewModel*/) {
    HomeScreen(Modifier, /*YourHomeScreenModel*/){
    }
}

现在你的底部工作表一直显示,要隐藏它你需要使用 BottomSheetState 折叠/展开和你需要设置为 0 的

sheetPeekHeight = 400.dp,
工作表首先完全隐藏

最后,您需要在第一次尝试导航到屏幕的 ButtonClick 上实现 BottomSheetState 更改

编辑: 也不要使用

backgroundColor
。要更改 bottomSheets 背景,您需要使用
sheetBackgroundColor = Color.Transparent


0
投票

helpinghand 你对处理设备后退按钮是正确的。但是现在,当用户按下后退按钮时,只有登录屏幕的工作表内容会折叠,而登录屏幕的主要内容(主屏幕的主要内容)仍然存在。为了让它工作,我不需要可组合的回调屏幕作为登录屏幕功能的参数,而是将其替换为另一个回调,如 (callback: () -> Unit) 并且每当想要摆脱登录屏幕时只需在登录屏幕中调用它(例如,在底部工作表外部单击或折叠它时),然后在主屏幕中创建一个布尔可变状态,用于检测何时需要显示登录屏幕,因此在尾随的 lambda 中创建状态假的。


0
投票

这样你就可以在 compose 中创建透明的 bottomsheet, 延伸到 custombottomsheet 下方

 abstract class CustomBottomSheeet : 
         BottomSheetDialogFragment() {
       var isDraggable: Boolean = true

   abstract fun init()

   @Composable
   abstract fun BuildContentComposable()

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
   }

   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
       super.onViewCreated(view, savedInstanceState)
       dialog?.let {
           val sheet = it as BottomSheetDialog
           sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
           sheet.behavior.peekHeight = 
         Resources.getSystem().displayMetrics.heightPixels
           sheet.behavior.isDraggable = isDraggable
       }
   }

   override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
       val dialog = super.onCreateDialog(savedInstanceState)

       dialog.setOnShowListener {
           //this line transparent your dialog background
           (view?.parent as ViewGroup).background =
               ColorDrawable(android.graphics.Color.TRANSPARENT)
       }

       return dialog
   }

   
   override fun onCreateView(
       inflater: LayoutInflater,
       container: ViewGroup?,
       savedInstanceState: Bundle?
   ): View? {
       val view = ComposeView(requireContext()).apply {
           setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
           setContent {
               BottomSheetTop {
                   BuildContentComposable()
               }
            
           }
       }

       init()
       return view
   }
   @Preview
   @Composable
   private fun Preview(){
       BottomSheetTop(){}
   }

   @Composable
   private fun BottomSheetTop(content: @Composable () -> Unit) {
       Box(modifier = Modifier
               .fillMaxWidth()
               .background(
                   colorResource(id = R.color.transparent),
                   shape = RoundedCornerShape(topStart = 14.sdp, topEnd = 14.sdp)
               )
               .clip(RoundedCornerShape(topStart = 14.sdp, topEnd = 14.sdp))
       ) {
           ConstraintLayout(
               modifier = Modifier
                   .fillMaxWidth()
                   .background(color = colorResource(id = R.color.transparent))
           ) {
               val (topImage, contentView) = createRefs()
             //  ImageViewCustomPainterSource(painterResource = R.drawable.bg_transparent,modifier = Modifier.fillMaxSize())
               Box(
                   modifier = Modifier
                       .width(40.sdp)
                       .height(3.sdp)
                       .constrainAs(topImage) {
                           top.linkTo(parent.top)
                           start.linkTo(parent.start)
                           end.linkTo(parent.end)
                       }
                       .background(
                           colorResource(id = R.color.white),
                           shape = RoundedCornerShape(20.sdp)
                       )
               )
                val marginHorizontal = 6.sdp
                val marginTop = 4.sdp
               val marginBottom = 10.sdp
               Box(modifier = Modifier.background(color = colorResource(id = R.color.white),shape = RoundedCornerShape(14.sdp))
                   .padding(start = 4.sdp, end = 4.sdp, top = 6.sdp, bottom = 10.sdp)
                   .constrainAs(contentView) {
                       start.linkTo(parent.start,marginHorizontal)
                       end.linkTo(parent.end,marginHorizontal)
                       top.linkTo(topImage.bottom,marginTop)
                       bottom.linkTo(parent.bottom,marginBottom)
                       width = Dimension.fillToConstraints
                   }) {
                   content()
               }
           }
       }
   }

  

}

© www.soinside.com 2019 - 2024. All rights reserved.