如何在喷气背包构图中显示透明背景的底片



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

我将在应用程序的其他地方使用这个登录页,所以我更喜欢将其作为一个单独的屏幕,从主页导航到登录。

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

这是我的代码:

登录屏幕:

@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()
}

您尝试显示登录屏幕的方式不会像您预期的那样工作,因为当您导航到登录屏幕时,就像打开一个新屏幕一样,主屏幕会添加到后台,而不会显示在登录屏幕后面。要使其发挥作用,请这样尝试:

@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
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和sheetPeekHeight = 400.dp,,您需要将其设置为0,以便在第一次时完全隐藏工作表

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

编辑:也不要使用backgroundColor。要更改底页背景,您需要使用sheetBackgroundColor = Color.Transparent

通过这种方式,您可以在compose中创建透明的底部页,延伸至低于客户底线

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()
}
}
}
}

}

helpinghand处理设备后退按钮是正确的。但现在,当用户按下后退按钮时,只有登录屏幕的表单内容会塌陷,并且作为主屏幕主要内容的登录屏幕的主要内容会保留下来。为了让它发挥作用,我不需要可组合的回调屏幕作为登录屏幕函数的参数,而是用另一个回调来代替它,比如(callback:((->Unit(,并且每当想要摆脱登录屏幕时,只需在登录屏幕中调用它(例如,在底部页面外单击或折叠它时(,然后在主屏幕中创建一个布尔可变状态,用于检测何时需要显示登录屏幕,因此在后面的lambda中使状态为false。

最新更新