Application of Scaffold in Android JetPack Compose component

1. Create the Activity Empty Compose module
. Create a new project in Android Studio and select an Empty Compose Activity, as shown in the figure below:
Empty Compose Activity
2. Build the main structure of the Scaffold scaffolding

/**
 * Main activity
 * 定义主活动
 * @constructor Create empty Main activity
 */
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Ch04_ComposeTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    MainScreen()
                }
            }
        }
    }
}//end MainActivity
/**
 * Main screen
 * 定义主界面的脚手架框架
 */
@Composable
fun MainScreen(){
    val scaffoldState = rememberScaffoldState()
    Scaffold(scaffoldState = scaffoldState,
        //定义头部
        topBar={

        },
        //定义侧滑内容
        drawerContent = {

        },
        //定义中心区内容,实现界面的切换
        content={

        },
        //定义底部的导航内容
        bottomBar = {

        },
        //定义悬浮按钮
        floatingActionButton={
        
        }
    )//end Scaffold
}

Call the scaffolding main frame in the main activity MainActivity
3. Define the three interfaces that need to be switched: HomeScreen, SettingScreen, HelpScreen The
display effect is as shown in the figure:
Switch interface

/** 定义首页界面*/
@Preview
@Composable
fun HomeScreen(){
    Column(modifier= Modifier
        .fillMaxSize()
        .padding(10.dp)
        .background(colorResource(id = R.color.teal_200)),
          horizontalAlignment = Alignment.CenterHorizontally,
          verticalArrangement = Arrangement.Center,
          content = {
            Text(text="首页界面",color=Color.White,
                 fontSize=36.sp, fontWeight = FontWeight.ExtraBold)
         })
}

/**定义配置界面*/
@Preview
@Composable
fun SettingScreen(){
    Column(
        content = {
            Text("配置界面",
                fontSize=36.sp,
                color = Color.White)
        },
        modifier = Modifier
            .fillMaxSize()
            .background(colorResource(R.color.teal_200)),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
    )
}
/**定义帮助界面*/
@Preview
@Composable
fun HelpScreen(){
    Column(modifier= Modifier.fillMaxSize()
                             .background(colorResource(id = R.color.teal_200)),
           verticalArrangement = Arrangement.Center,
           horizontalAlignment = Alignment.CenterHorizontally){
            Text("帮助界面",color= Color.White,fontSize=36.sp)
        }
}

You can also define a general combination function, and then let the combination function that defines an interface be called, like this:

@Composable
fun DisplayText(content:String){
    Column(modifier= Modifier.fillMaxSize()
                             .background(colorResource(id = R.color.teal_200)),
           verticalArrangement = Arrangement.Center,
           horizontalAlignment = Alignment.CenterHorizontally){
            Text("$content",color= Color.White,fontSize=36.sp)
        }
}

The modifications to the three interfaces are as follows:

/** 定义首页界面*/
@Preview
@Composable
fun HomeScreen(){
    DisplayText("首页界面")
}

/**定义配置界面*/
@Preview
@Composable
fun SettingScreen(){
    DisplayText("配置界面")
}
/**定义帮助界面*/
@Preview
@Composable
fun HelpScreen(){
    DisplayText("帮助界面")
}

4. Define the switching screen interface in the sealed class

/**
 * 定义要切换界面的密封类
 * @property route String 导航线路
 * @property title String  标题
 * @property icon ImageVector 图标
 * @property screenToLoad [@androidx.compose.runtime.Composable] Function0<Unit> 加载动作处理
 * @constructor
 */
sealed class Screens(val route:String, val title:String, val icon: ImageVector, val screenToLoad:@Composable ()-> Unit){
    object HomePage:Screens("home","首页界面", Icons.Filled.Home,{
        HomeScreen()
    })
    object SettingPage:Screens("setting","配置界面",Icons.Filled.Settings,{
        SettingScreen()
    })
    object HelpPage:Screens("help","帮助界面",Icons.Filled.Info,{
        HelpScreen()
    })
}

Define the list of saved screen interfaces
//Define the list of interfaces to be switched

val screens = listOf<Screens>(Screens.HomePage,Screens.SettingPage,Screens.HelpPage)

5. Create the navigation of the side-sliding menu.
Create the side-sliding menu. The display effect is as follows:

Insert image description here

(1) Define the top content of the side-sliding menu

/**
 * Top bar view
 * 定义头部
 */
@Preview
@Composable
fun HeaderBarView(){
   Box(modifier= Modifier
       .fillMaxWidth()
       .wrapContentHeight()
       .background(color = colorResource(id = R.color.purple_200))){
       Row(modifier= Modifier
           .fillMaxWidth()
           .padding(5.dp)){
           Column{
                   Image(painter=painterResource(id = android.R.mipmap.sym_def_app_icon),
                       contentDescription = "logo图标",
                       modifier= Modifier .width(dimensionResource(id = R.dimen.image_width))
                           .height(60.dp)
                           .clip(shape = CircleShape)
                           .background(Color.Black))
               }//end Column
          Column{
                   Text(stringResource(id = R.string.title_robot))
                   Text(stringResource(id = R.string.title_introduction))
           }
       }//end Column
   }
}

(2) Define side sliding menu

/**
 * 定义侧滑的下面的菜单
 * @param scaffoldState ScaffoldState 脚手架的状态
 * @param action Function1<[@kotlin.ParameterName] Screens, Unit>? 要处理的切换动作,默认为空
 */
@Composable
fun DrawerViews(scaffoldState: ScaffoldState,
                action: ((screen:Screens) -> Unit)?=null){
    val scope = rememberCoroutineScope()
    Column(modifier= Modifier.fillMaxSize()){
        screens.forEach { screen->
            val clickable =remember{ mutableStateOf(false) }
            Row(verticalAlignment = Alignment.CenterVertically){

                IconButton(onClick={
                    action?.invoke(screen)
                    clickable.value = !clickable.value
                    scope.launch {
                        scaffoldState.drawerState.close()
                    }
                }){
                    Icon(imageVector = screen.icon,"${screen.title}")
                }
                Text("${screen.title}",fontSize=20.sp, fontWeight = FontWeight.Bold,
                    color = if(clickable.value)  colorResource(id = R.color.purple_500) else colorResource(id = R.color.teal_700))
            }
        }
    }
}

(3) Combine the contents of the two parts into the main frame of the scaffolding.
Add processing of side sliding menu in scaffolding

/**
 * Main screen
 * 定义主界面的脚手架框架
 */
@Composable
fun MainScreen(){
    //脚手架的状态
    val scaffoldState = rememberScaffoldState()
    //当前的屏幕
Val currentScreen:MutableState<Screens>= 
remember{ mutableStateOf(Screens.Home) }

    Scaffold(scaffoldState = scaffoldState,
        //定义头部
        topBar={

        },
        //定义侧滑内容
        drawerContent = {
        HeaderBarView()
        DrawerViews(scaffoldState){screen->
            currentScreens.value = screen
        }
    },
    //主界面显示区
    content={
        currentScreens.value.screenToLoad()
    },
    
        .......
    )//end Scaffold
}

6. Create navigation for the application header

/**
 * 定义应用头部内容
 * 在头部定义一个导航菜单
 * @param scaffoldState ScaffoldState 脚手架的状态
 */
@Composable
fun TopBarView(currentScreen:MutableState<Screens>,scaffoldState: ScaffoldState){
    //协程的范围
    val scope = rememberCoroutineScope()
    TopAppBar(
        title={
              Text("${currentScreen.title}",fontSize=20.sp)
        },
        navigationIcon={
            IconButton(onClick={
                scope.launch {
                    scaffoldState.drawerState.open()
                }
            }){
                Icon(imageVector =  Icons.Filled.Home,contentDescription="",tint=Color.White)
            }
        },
        actions={
            IconButton(onClick = {

            }) {
                Icon(imageVector =  Icons.Filled.MoreVert,contentDescription="",tint=Color.White)
            }
        },
        modifier = Modifier
            .fillMaxWidth()
            .wrapContentHeight(),
        backgroundColor = Color.Black,
        contentColor = Color.White
    )
}

Description:
(1) scaffoldState: ScaffoldState is used to handle scaffolding-related operations, here it is used to open the side-sliding menu.
(2) Define TopAppBar to define a head action bar similar to ActionBar.
Modify the scaffolding defined in MainActivity.kt and add TopBar functionality

/**
 * Main screen
 * 定义主界面的脚手架框架
 */
@Composable
fun MainScreen(){
    val scaffoldState = rememberScaffoldState()
    val currentScreens:MutableState<Screens> = remember{ mutableStateOf(Screens.HomePage) }

    Scaffold(scaffoldState = scaffoldState,
    topBar = {
        TopBarView(currentScreen,scaffoldState)
    },
    drawerContent = {
        HeaderBarView()
        DrawerViews(scaffoldState){screen->
            currentScreens.value = screen
        }
    },
    content={
        currentScreens.value.screenToLoad()
    },
   ......
}

7. Create the navigation at the bottom of the application.
The running effect is as follows:
Bottom navigation
Define the content of the bottom navigation bar

/**
 * 定义应用底部的视图
  *接收从外部传递的要显示的当前界面
 */
@Composable
fun BottomViews(currentScreen:MutableState<Screens>){
    BottomAppBar(
        backgroundColor = Color.Blue,
        contentColor = Color.Yellow){
            screens.forEach { screen->
                    BottomNavigationItem(
                        icon = {
                               Icon(imageVector = item.icon, contentDescription = "${screen.title}")
                        } ,
                        label={
                             Text("${screen.title}")
                        },
                        selected = screen.route == currentScreen.value.route,
                        onClick = {
                            currentScreen.value = screen
                        }
                    )
            }
       }
}

(3) The bottom navigation bar is added to the scaffolding and bottom navigation is implemented.
In the scaffolding in MainActivity.kt, the processing of the bottom navigation bar is added.

@Composable
fun MainScreen(){
    val scaffoldState = rememberScaffoldState()
    val currentScreens:MutableState<Screens> = remember{ mutableStateOf(Screens.HomePage) }

    Scaffold(scaffoldState = scaffoldState,
    topBar = {
        TopBarView(currentScreen,scaffoldState)
    },
    drawerContent = {
        HeaderBarView()
        DrawerViews(scaffoldState){screen->
            currentScreens.value = screen
        }
    },
    content={
        currentScreens.value.screenToLoad()
    },
    bottomBar = {
        BottomViews(currentScreen = currentScreens)
    },
    ......
}

8. Scaffolding adds a floating button to return to the homepage
Add floating button

@Composable
fun MainScreen(){
    //脚手架的状态
    val scaffoldState = rememberScaffoldState()
    //当前显示的界面
    val currentScreen:MutableState<Screens> = remember{ mutableStateOf(Screens.HomePage) }
    //当前的上下文
    val context = LocalContext.current        
    Scaffold(scaffoldState = scaffoldState,
    topBar = {
        TopBarView(currentScreen,scaffoldState)
    },
    drawerContent = {
        HeaderBarView()
        DrawerViews(scaffoldState){screen->
            currentScreen.value = screen
        }
    },
    content={
        currentScreen.value.screenToLoad()
    },
    bottomBar = {
        BottomViews(currentScreen = currentScreen)
    },
    floatingActionButton = {
        FloatingActionButton(
        backgroundColor = Color.Red,
             onClick = {
            Toast.makeText(context,"返回首页",Toast.LENGTH_LONG).show()
            currentScreen.value = Screens.HomePage
        }){
            Icon(Icons.Filled.Home, contentDescription = "返回首页")
        }
    })
}

参考文献
(1)https://www.geeksforgeeks.org/bottom-navigation-bar-in-android-jetpack-compose/
(2)https://amryousef.me/side-drawer-jetpack-compose


Guess you like

Origin blog.csdn.net/userhu2012/article/details/127482137