kotlin 如何显示透明背景的底部工作表在喷气背包组成?

wpcxdonn  于 2023-04-12  发布在  Kotlin
关注(0)|答案(3)|浏览(302)

我的应用程序由主屏幕和在这个屏幕上,有一个按钮,当用户点击它,他们导航到登录底部工作表。
我将在应用程序的其他地方使用此登录底表,所以我更喜欢将其作为一个单独的屏幕,并从主页导航到登录。
显示主屏幕作为登录屏幕的背景是可取的。我的意思是登录底部工作表的主要内容应该是空的和透明的,以便看到主屏幕作为背景。但是,而不是主屏幕作为背景,白色背景显示出来。
以下是我的代码:

登录界面:

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

wz3gfoph1#

您尝试显示LoginScreen的方式不会像您预期的那样工作,因为当您导航到LoginScreen时,就像打开一个新屏幕一样,HomeScreen随后被添加到backstack,并且不会显示在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折叠/展开和sheetPeekHeight = 400.dp,,你需要设置为0,工作表是完全隐藏在第一
最后,您需要在第一次尝试导航到Screen的ButtonClick上实现BottomSheetState更改
编辑:也不要使用backgroundColor。要更改底部的Sheets背景,您需要使用sheetBackgroundColor = Color.Transparent

hm2xizp9

hm2xizp92#

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

ufj5ltwl

ufj5ltwl3#

这样你就可以在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()
               }
           }
       }
   }

}

相关问题