Android jetpack составляет фрагмент без xml

#android #android-jetpack-compose

Вопрос:

Спокойной ночи! Я использую drawerContent и navigationIcon для создания меню, но могу ли я создать фрагмент () без xml? в реактивном ранце. Если у кого-нибудь есть какие-либо рекомендации, я был бы признателен …

Комментарии:

1. Почему вы пытаетесь использовать фрагмент в Compose?

2. Я хочу сделать что-то похожее на навигацию по меню

3. @Рафаэлсуза developer.android.com/jetpack/compose/navigation

Ответ №1:

С помощью Compose вы можете попробовать что-то другое.
Вы можете перемещаться между составными элементами с помощью компонента навигации (в настоящее время в 1.0.0-alpha10 )

Создайте NavController с:

 val navController = rememberNavController()
 

и определите a 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(/*..*/) }
}
 

Теперь просто используйте a 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(/*..*/) }
        }
    }
)
 

где:

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

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

введите описание изображения здесь

Комментарии:

1. Когда я добавляю реализацию «androidx.навигация:навигация-составление:1.0.0-alpha10» в gradle, это приводит к ошибке в моем приложении

2. E/AndroidRuntime: ФАТАЛЬНОЕ ИСКЛЮЧЕНИЕ: основной процесс: com.example.quitanda, PID: 18006 java.lang. NoSuchFieldError: Нет поля-компаньона типа Landroidx/compose/foundation/layout/BoxScope$Companion; в классе Landroidx/compose/foundation/layout/BoxScope; или его суперклассов (объявление «androidx.compose. основа. расположение. BoxScope’ отображается в /data/app/com.пример.quitanda-sLmYSWEY6MCvkQJc8-SiSw==/база.apk)

3. @RafaelSouza Вы используете compose 1.0.0-beta04?

4. Нет, я использую compose 1.0.0-alpha10, другие изменения, которые я внес, заключались в добавлении элемента в изображение: реализация «com.google.аккомпаниатор:аккомпаниатор-катушка:0.7.0»

5. Я эмулирую на своем телефоне J Prime 5

Ответ №2:

Это сработало, мой класс выглядел так:

 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://api.quitandadivino.com.br/uploads/abacaxi_perola_20afb6c700.jpgamp;w=300amp;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))
    }
}
 

@Габриэле Мариотти Большое вам спасибо