无需 XML 的 Android Jetpack Compose 片段

4

晚安!我正在使用drawerContent和navigationIcon创建菜单,但是在Compose Jetpack中是否可以创建不带xml的Fragment()呢?如果有任何参考资料,我将不胜感激...


1
你为什么要在Compose中使用Fragment? - ianhanniballake
我想做类似于菜单导航的东西。 - Rafael Souza
1
@RafaelSouza https://developer.android.com/jetpack/compose/navigation - Gabriele Mariotti
2个回答

1

使用Compose,你可以尝试一些不同的东西。
你可以使用导航组件(目前版本为1.0.0-alpha10)在不同的组合间进行导航。

创建一个NavController

val navController = rememberNavController()

定义一个具有以下目标的NavHost

NavHost(
    navController,
    startDestination = "entry1"
) {
    composable("entry1") { Entry1(..) }
    composable("entry2") { Entry2(..) }
    composable("entry3") { Entry3(..) }
}

为了简化导航,只需创建一个密封类(这不是必需的)。
sealed class Screen(val route: String, @StringRes val resourceId: Int) {
    object Entry1 : Screen("entry1", R.string.entry1)
    object Entry2 : Screen("entry2", R.string.entry2)
    object Entry3 : Screen("entry3", R.string.entry3)
}

NavHost更改为:
NavHost(
    navController,
    startDestination = Screen.Entry1.route
) {
    composable(Screen.Entry1.route) { Entry1(/*..*/) }
    composable(Screen.Entry2.route) { Entry2(/*..*/) }
    composable(Screen.Entry3.route) { Entry3(/*..*/) }
}

现在只需使用 Scaffold 创建一个 drawerContent 和 navigationIcon,以打开菜单并导航到目标:
val navController = rememberNavController()
val current by navController.currentBackStackEntryAsState()
val scaffoldState = rememberScaffoldState()
val scope = rememberCoroutineScope()

val items = listOf(
    Screen.Entry1,
    Screen.Entry2,
    Screen.Entry3
)

Scaffold(
    scaffoldState = scaffoldState,
    drawerContent = {
        //val currentRoute = current?.arguments?.getString(KEY_ROUTE)
        val currentRoute = current?.destination?.route

        items.forEach { screen ->
            val selected = currentRoute == screen.route
            val selectedColor = if (selected) Color.Yellow else Color.Transparent
            Row(modifier = Modifier
                .fillMaxWidth()
                .height(32.dp)
                .background(selectedColor)
                .clickable {
                    scope.launch { scaffoldState.drawerState.close()}
                    navController.navigate(screen.route) {
                        popUpTo = navController.graph.startDestination
                        launchSingleTop = true
                    }
                }) {
                   Text(stringResource(screen.resourceId))
            }
        }
    },
    topBar = {
        TopAppBar(){
            IconButton(
                onClick = {
                    scope.launch { scaffoldState.drawerState.open() }
                }
            ) {
                Icon(Icons.Filled.Menu,"")
            }
        }
    },
    content = {
        NavHost(
            navController,
            startDestination = Screen.Entry1.route
        ) {
          composable(Screen.Entry1.route) { Entry1(/*..*/) }
          composable(Screen.Entry2.route) { Entry2(/*..*/) }
          composable(Screen.Entry3.route) { Entry3(/*..*/) }
        }
    }
)

where:

@Composable
fun Entry1(navigateTo: () -> Unit) {

    Column(){
         /*.....*/
    }
}

enter image description here


1
当我将实现 "androidx.navigation:navigation-compose:1.0.0-alpha10" 添加到gradle中时,我的应用程序会出现错误。 - Rafael Souza
E/AndroidRuntime: 致命异常:主要 进程:com.example.quitanda,PID:18006 java.lang.NoSuchFieldError:在类Landroidx/compose/foundation/layout/BoxScope中没有类型为Landroidx/compose/foundation/layout/BoxScope$Companion的Companion字段;或者它的超类('androidx.compose.foundation.layout.BoxScope'的声明出现在/data/app/com.example.quitanda-sLmYSWEY6MCvkQJc8-SiSw==/base.apk中) - Rafael Souza
@RafaelSouza 你正在使用Compose 1.0.0-beta04吗? - Gabriele Mariotti
1
不,我正在使用Compose 1.0.0-alpha10版本,我所做的其他修改是添加了一个实现到图像:implementation "com.google.accompanist:accompanist-coil:0.7.0"。 - Rafael Souza
我正在我的手机J Prime 5上进行仿真。 - Rafael Souza
显示剩余4条评论

-1

它起作用了,我的类看起来像这样:

package com.example.quitanda

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Menu
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import androidx.navigation.compose.*
import com.google.accompanist.coil.CoilImage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch


class MainActivity : ComponentActivity() {
    private val responseState = mutableStateOf("")

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


    @Composable
    private fun RecyclerView(){
        Text(text = responseState.value)

        LazyColumn(/*contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp),*/
                modifier = Modifier.fillMaxSize()){
            for(i in 0..50){
                item {
                    Text(text = "Categoria 2, categoria 1",fontSize = 15.sp,
                            color=Color.White,modifier= Modifier
                        .background(
                                colorResource(id = R.color.red)
                        )
                        .fillMaxWidth(100f))
                    Row(verticalAlignment = Alignment.CenterVertically,
                            modifier= Modifier
                                .padding(bottom = 8.dp)
                                .fillMaxWidth(100f)
                        ) {

                        Images("https://quitandadivino.com.br/_next/image?url=https%3A%2F%2Fapi.quitandadivino.com.br%2Fuploads%2Fabacaxi_perola_20afb6c700.jpg&w=300&q=75")

                        Column {
                            Text("Abacaxi",fontSize = 20.sp)
                            Text("Aprox. 0,185g/un",fontSize = 15.sp,color=Color.LightGray)
                            Text("R$ 120,00/UN",fontSize = 15.sp,color=Color.Red)
                            Text("R$ 120,00/KG",fontSize = 15.sp,color=Color.Red)
                        }

                        Column(modifier= Modifier
                            .fillMaxWidth(100f)
                            .padding(5.dp)
                           ,horizontalAlignment = Alignment.End) {
                            Button(
                                    onClick = {},
                                    colors = ButtonDefaults.buttonColors(
                                            backgroundColor = Color.Red,
                                            contentColor = Color.White)
                            ) {
                                Text(text = stringResource(id = R.string.comprar))
                            }
                        }
                    }

                    Text(text = " ",fontSize = 15.sp,
                            modifier = Modifier
                                .padding(bottom = 2.dp) // margin
                                .fillMaxWidth(100f)
                                .background(colorResource(id = R.color.red))
                        )

                }
            }
        }

    }

    private fun onPressView(){
        Toast.makeText(this,"Testar",Toast.LENGTH_LONG).show();
    }

    @Composable
    private fun Images(url:String){
        Card(
                modifier = Modifier
                    .size(110.dp)
                    .testTag("circle")
                    .fillMaxSize()
                    .clickable(onClick = { onPressView() })
                    .padding(10.dp),
                shape = CircleShape,
                elevation = 2.dp,
        ) {

            CoilImage(
                    data = url,
                    contentDescription = "Abacaxi",
                    fadeIn = true
            )
        }
    }

    @Composable
    private fun MainContent(){
        val scaffoldState = rememberScaffoldState()
        val scope = rememberCoroutineScope()
        val navController = rememberNavController()

         Scaffold(
                topBar = {
                    TopBar(scope,scaffoldState)
                         },
                content={

                    NavHost(
                            navController,
                            startDestination = Screen.Entry1.route
                    ) {
                        composable(Screen.Entry1.route) { Entry1() }
                        composable(Screen.Entry2.route) { Entry2() }
                        composable(Screen.Entry3.route) { Entry3() }
                    }
                },
                floatingActionButton = { MainFab() },
                drawerContent = {
                    DrawerContent(scope,scaffoldState,navController)
                },
                scaffoldState = scaffoldState
        )
    }


    @Composable
    private fun DrawerContent(scope: CoroutineScope,scaffoldState:ScaffoldState
    ,navController: NavController
    ){

        val items = listOf(
                Screen.Entry1,
                Screen.Entry2,
                Screen.Entry3
        )

        Text("Drawer content", style = MaterialTheme.typography.h5)

        items.forEach { screen ->
            Row(modifier = Modifier
                .fillMaxWidth()
                .height(32.dp)
                .clickable {
                    scope.launch { scaffoldState.drawerState.close() }
                    navController.navigate(screen.route) {
                        popUpTo = navController.graph.startDestination
                        launchSingleTop = true
                    }
                }) {
                Text(stringResource(screen.resourceId))
            }
        }
    }

    @Composable
    private fun TopBar(scope: CoroutineScope,scaffoldState:ScaffoldState){
        TopAppBar(title={
            Text(text = stringResource(id = R.string.app_name))
        },
                backgroundColor = colorResource(id = R.color.green),
                contentColor = Color.White,
                navigationIcon ={
                    IconButton(
                            onClick = {scope.launch { scaffoldState.drawerState.open() } }
                    ) {
                        Icon(imageVector = Icons.Default.Menu, contentDescription ="Menu" )
                    }
                }
        )
    }

    @Composable
    private fun MainFab () {
        FloatingActionButton(onClick = {showAddForm()}) {
            Icon(imageVector = Icons.Filled.Add, contentDescription = "Adicionar")
        }
    }

   private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            // There are no request codes
            val response = result.data?.getParcelableExtra<AddUserState>("user_state")
            responseState.value = response.toString()
        }
    }

    private fun showAddForm() {
        val intent = Intent(this, FormActivity::class.java)
        resultLauncher.launch(intent)
    }

    @Composable
    private fun Entry1(){
        Text(text = stringResource(id = R.string.entry1))
        RecyclerView()
    }

    @Composable
    private fun Entry2(){
        Text(text = stringResource(id = R.string.entry2))
    }

    @Composable
    private fun Entry3(){
        Text(text = stringResource(id = R.string.entry3))
    }
}

@Gabriele Mariotti 非常感谢你


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接