Android kotlin material design technology points

Posted by andymt on Sun, 13 Feb 2022 17:16:14 +0100

1.Material design definition

Material design is a new set of interface design language developed by google design engineers based on excellent design principles and combined with rich creativity and science and technology, including visual, sports, interactive special effects and other characteristics.

2. Use of toolbar

Toolbar not only inherits all the functions of ActionBar, but also has high flexibility. It can cooperate with other controls to complete some Material Design effects.

When creating a project, ActionBar will be used by default, which is defined in AppTheme. If you want to use toolbar, you need to specify a theme without ActionBar. Generally use theme AppCompat. Noactionbar or theme Appcompat. Light. NoActionBar.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:context=".MaterialActivity">

    <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolBar"
            android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
             android:background="@color/colorPrimary"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
             app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    />

</FrameLayout>

The title of setaction bar can be set in the ToolBar file, but the effect of setaction bar is not the same as that of the next ToolBar.

Specifies that the label label is used for the copy of the ToolBar

<activity android:name=".MaterialActivity"
    android:label="beauty">

Now it looks monotonous. Set a menu to the ToolBar, create a new menu folder under the Res file, and create a ToolBar XML file

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/backup"
          android:icon="@mipmap/ic_backup"
          android:title="Backup"
          app:showAsAction="always"/>

    <item android:id="@+id/delete"
          android:icon="@mipmap/ic_delete"
          android:title="Delete"
          app:showAsAction="ifRoom"/>

    <item android:id="@+id/settings"
          android:icon="@mipmap/ic_settings"
          android:title="settings"
          app:showAsAction="never"/>

</menu>

There are two methods to rewrite the menu in the activity. One is onCreateOptionsMenu, which is to create the menu and return to the above menu. The other is onoptionsiteselected, which is the menu click callback.

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.toolbar,menu)
    return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    when(item.itemId){
        R.id.backup -> showToast("backup")
        R.id.delete -> showToast("delete")
        R.id.settings -> showToast("settings")
    }

    return true
}

3. Slide the menu DrawerLayout

DrawerLayout is a sliding menu, which can be hidden when not in use. It can be displayed by sliding. It saves screen controls and has very good animation effect, which is the recommended practice in Material Design.

DrawerLayout allows two direct sub controls. The first is the content of the displayed main screen and the other is the content of the sub menu. Examples are as follows:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawerLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
       >

    <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".materila.MaterialActivity">

        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolBar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@color/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        />

    </FrameLayout>

    <TextView android:layout_width="match_parent"
              android:text="this is menu"
              android:background="#fff"
              android:textSize="29sp"
              android:layout_gravity="start"
              android:layout_height="match_parent"/>

</androidx.drawerlayout.widget.DrawerLayout>

Note: Android: layout must be specified_ Gravity = "start", so you can slide right to display the menu. Since the user may not know that there is such a menu, it is generally necessary to add a navigation button.

 override fun onCreate(savedInstanceState: Bundle?) {
       ...
        setSupportActionBar(toolBar)
        supportActionBar?.let {
            it.setDisplayHomeAsUpEnabled(true)
            it.setHomeAsUpIndicator(R.mipmap.ic_menu)
        }
    }


    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId){
            android.R.id.home -> {
                drawerLayout.openDrawer(GravityCompat.START)
            }
         ...
        }

        return true
    }
}

In this way, the Home navigation button and click event are set. The left button of the ToolBar is the Home button, and the default image is a return arrow

4.NavigationView

This control is very suitable for sliding menu content. The effect is very good and the implementation is very simple.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
                android:id="@+id/navCall"
                android:icon="@mipmap/nav_call"
                android:title="Call"/>

        <item android:id="@+id/navFriends"
              android:icon="@mipmap/nav_friends"
              android:title="Friends"/>

        <item android:id="@+id/navLocation"
              android:icon="@mipmap/nav_location"
              android:title="Location"/>

        <item android:id="@+id/navMail"
              android:icon="@mipmap/nav_mail"
              android:title="Mail"/>

        <item android:id="@+id/navTask"
              android:icon="@mipmap/nav_task"
              android:title="Tasks"/>
    </group>

</menu>

Create NavMenu

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:padding="10dp"
                android:background="@color/colorPrimary"
                android:layout_height="180dp">

    <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/iconImage"
            app:civ_border_width="2dp"
            app:civ_border_color="#fff"
            android:layout_width="70dp"
            android:src="@mipmap/nav_icon"
            android:layout_centerInParent="true"
            android:layout_height="70dp"/>

    <TextView
            android:id="@+id/mailText"
            android:layout_width="wrap_content"
            android:layout_alignParentBottom="true"
            android:textColor="#fff"
            android:textSize="14sp"
            android:text="She's skiing at the ski resort"
            android:layout_height="wrap_content"/>

    <TextView
            android:id="@+id/userText"
            android:layout_width="wrap_content"
            android:textColor="#fff"
            android:textSize="14sp"
            android:layout_height="wrap_content"
        android:layout_above="@+id/mailText"
              android:text="Liu Ruoxi and snowman"
    />

</RelativeLayout>

Create Nav_Header

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawerLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
       >

   ...

    <com.google.android.material.navigation.NavigationView
            android:id="@+id/navView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            app:menu="@menu/nav_menu"
            app:headerLayout="@layout/nav_header"
    />

</androidx.drawerlayout.widget.DrawerLayout>

nav_menu and nav_ Add header to NavigationView.

override fun onCreate(savedInstanceState: Bundle?) {
   ...
    navView.setCheckedItem(R.id.navCall)  //An item is selected by default
    navView.setNavigationItemSelectedListener {
        when(it.itemId){
            R.id.navCall-> showToast("Call")
            R.id.navLocation-> showToast("Location")
        }
        drawerLayout.closeDrawers()
        true
    }
}

Set the click event and default selection of navicationView

5. Floating action button

This is a suspended button with a shadow at the bottom. It has a three-dimensional effect. By default, colorAccent is used as the color of the button.

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawerLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
       >

    <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".materila.MaterialActivity">

      ...

        <com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/fab"
                android:layout_gravity="bottom|end"
                android:layout_margin="15dp"
                android:src="@mipmap/ic_done"
                app:elevation="4dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

    </FrameLayout>

...

</androidx.drawerlayout.widget.DrawerLayout>

Add this control to the layout file. You can set the height value through the elcvation property. The larger the height value, the smaller the projection range.

backgroundTint this property allows you to change the default background color

fab.setOnClickListener {
    showToast("FAB click")
}

Set the click event for the hover button

6.SnackBar

This control is more similar to Toast, but it is not a substitute for Toast. It has different application scenarios. SnackBar can not only prompt users, but also provide an interactive design.

fab.setOnClickListener {
    Snackbar.make(it,"Data deleted",Snackbar.LENGTH_LONG).setAction("Done"){
        showToast("confirm delete data")
    }.show()
}

It can be seen that the usage is similar to Toast. A setAction method is added. SnackBar pops up from the bottom with animation effect and will automatically disappear from the bottom.

7.CoordinatorLayout

The SnackBar pop-up above will block the FloatActionButton. At this time, you can solve this small bug by using CoordinatorLayout, which is an enhanced version of FrameLayout. This container extends the event listening of child controls and automatically helps us make the most reasonable response.

To fix the problem that the FloatActionButton is blocked, just replace FrameLayout with CoordinatorLayout. There are no other problems after replacement. After the SnackBar pops up, the hover button will automatically move upward. The SnackBar disappears and the hover button will automatically return to its original position. The whole process is very smooth with animation.

8.MaterialCardView and RecyclerView

MaterialCardView is an important control of card layout effect. It is also a FrameLayout, but it provides additional fillet and shadow effects.

RecyclerView is an enhanced version of ListView.

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_margin="6dp"
        app:cardCornerRadius="4dp"
        android:layout_height="wrap_content">
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" >
        <ImageView android:id="@+id/girlImage" android:layout_width="match_parent" android:layout_height="100dp" android:scaleType="centerCrop"/>
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"
                  android:layout_margin="5dp"
                  android:textSize="15sp"
                  android:id="@+id/girlName"
        />
    </LinearLayout>

</com.google.android.material.card.MaterialCardView>

Create card Item layout

class GirlAdapter(private val context:Context, private val girlList:List<BeautyGirl>): RecyclerView.Adapter<GirlAdapter.GirlHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GirlHolder {
        val view:View = LayoutInflater.from(context).inflate(R.layout.girl_item,parent,false)
        return GirlHolder(view)
    }

    override fun getItemCount(): Int {
        return girlList.size
    }

    override fun onBindViewHolder(holder: GirlHolder, position: Int) {
        val girl= girlList[position]
        holder.girlName.text = girl.name
        Glide.with(context).load(girl.imageId).into(holder.girlImage)
    }

    class GirlHolder(view : View) : RecyclerView.ViewHolder(view){
        var girlImage:ImageView = view.findViewById(R.id.girlImage)
        var girlName:TextView = view.findViewById(R.id.girlName)
    }

}

Create a new adapter used by RecyclerView, and set the data through the construction method

private fun initRecyclerView() {
    val girls= mutableListOf(BeautyGirl("Beauty 1",R.mipmap.g1),BeautyGirl("Beauty 2",R.mipmap.g2),BeautyGirl("Beauty 3",R.mipmap.g3),
        BeautyGirl("Beauty 4",R.mipmap.g4),BeautyGirl("Beauty 5",R.mipmap.g5),BeautyGirl("Beauty 6",R.mipmap.g6))

    val layoutManger=GridLayoutManager(this,2)
    recyclerView.layoutManager=layoutManger
    val adapter=GirlAdapter(this,girls)
    recyclerView.adapter=adapter
}

Initialize RecyclerView and set the data so that the card style view can be displayed on the mobile phone. The whole list is elegant and beautiful.

9.AppBarLayout

When displaying the list above, I found that the list obscured the toolbar. The traditional solution is to let RecyclerView set the marginTop value to be the height of the toolbar. The currently used outer container is CoordinatorLayout. This problem can be fixed with the help of AppBarLayout. The advantage of using this control is that AppBarLayout has the design concept of Material Design.

<androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
      >

    <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent"
                                                     android:layout_height="wrap_content">
        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolBar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@color/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        />
    </com.google.android.material.appbar.AppBarLayout>



    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
    />

...

</androidx.coordinatorlayout.widget.CoordinatorLayout>

The change is not big. You just need to move the ToolBar to the AppBarLayout, and then specify the behavior behavior of RecyclerView, including appbar_scrolling_view_behavior is in the material library.

When RecyclerView scrolls, AppBarLayout will receive the sliding event, so that the Material Design effect is not seen. This is because AppBarLayout received the sliding event and did not process the sliding event.

Add an app: layout to the ToolBar_ Scrollflags and set the value to sroll|enterAlways|snap

Scroll means that when RecyclerView scrolls, the Toolbar will scroll with it and hide it.

enterAlways indicates that when the RecyclerView scrolls down, the ToolBar will scroll down and reappear

snap means that when the Toolbar is not completely hidden or displayed, it will automatically select whether to display or hide according to the current scrolling distance.

10. Implement drop-down refresh SwipeRefreshLayout

There are various implementation versions and styles of list drop-down refresh. The following describes the implementation of drop-down refresh using SwipeRefreshLayout officially provided by Google.

implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'

Increase this dependency

<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
>

    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
    />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

Add RecyclerView to the SwipeRefreshLayout, and note that the behavior mentioned above is added to the SwipeRefreshLayout, so that it will automatically have the function of drop-down refresh.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
   ...
    swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary)
    swipeRefreshLayout.setOnRefreshListener {
        refreshGirls()
    }
}

    fun refreshGirls(){
        thread {
            Thread.sleep(2000)
            runOnUiThread{
                initGirls()
                adapter.setData(girls)
                swipeRefreshLayout.isRefreshing=false
            }
        }
    }

Add specific refresh code logic

11. Collapse the title bar CollapsingToolbarLayout

CollapsingToolbarLayout is a layout file based on toolbar, which can make the effect of toolbar colorful. This control cannot exist independently, but can only be used as a sub layout of AppBarLayout, which must be a sub layout of CoordinatorLayout.

Create a detail page, and the layout file is as follows

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".materila.GirlDetailActivity">
    <com.google.android.material.appbar.AppBarLayout android:id="@+id/appBar"
                                                     android:layout_width="match_parent"
                                                     android:layout_height="250dp">
        <com.google.android.material.appbar.CollapsingToolbarLayout android:id="@+id/collapsingToolBar"
                                                                    android:layout_width="match_parent"
                                                                    android:layout_height="match_parent"
                                                                    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                                                                    app:contentScrim="@color/colorPrimary"
                                                                    app:layout_scrollFlags="scroll|exitUntilCollapsed">
            <ImageView
                    android:id="@+id/girlImage"
                    android:layout_width="match_parent"
                    android:scaleType="centerCrop"
                    android:layout_height="match_parent"
                    app:layout_collapseMode="parallax"
            />

            <androidx.appcompat.widget.Toolbar
                    android:id="@+id/toolBar"
                    android:layout_width="match_parent"
                    android:layout_height="?actionBarSize"
                    app:layout_collapseMode="pin"
            />

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView android:layout_width="match_parent"
                                           android:layout_height="match_parent"
                                           app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <LinearLayout android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:orientation="vertical">
            <com.google.android.material.card.MaterialCardView android:layout_width="match_parent"
                                                               android:layout_height="wrap_content"
                                                               android:layout_margin="15dp" app:cardCornerRadius="4dp">
                <TextView android:id="@+id/content"
                          android:layout_width="wrap_content"
                          android:layout_height="wrap_content"
                          android:layout_margin="10dp"
                />
            </com.google.android.material.card.MaterialCardView>
        </LinearLayout>

    </androidx.core.widget.NestedScrollView>

    <com.google.android.material.floatingactionbutton.FloatingActionButton android:layout_width="wrap_content"
                                                                           android:layout_height="wrap_content"
                                                                           android:layout_margin="16dp"
                                                                           android:src="@mipmap/ic_comment"
                                                                           app:layout_anchor="@id/appBar"
                                                                           app:layout_anchorGravity="bottom|end"
    />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

1. The outermost container is CoordinatorLayout, because the parent container of AppBarLayout must be CoordinatorLayout

2. The outermost layer of the toolbar part is AppBarLayout, and the inner layer is CollapsingToolBarLayout. The CollapsingToolBarLayout control is set to 3 App: contentscrim = "@ color / colorprimary" indicates the color that tends to be folded or after folding

4.exitUntilCollapsed: it means that the collapsingToolBarLayout will remain on the interface after it is folded, and will not move out of the screen

5.app:layout_collapseMode = "parallax" this indicates the style in the folding process. If it is set to parallax, it indicates that there is a certain dislocation effect in the folding process, and the dislocation vision is poor.

6.NestedScrollView adds nested response to scrolling events compared with ScrollView, and specifies a layout behavior for this control. Only one child control is allowed inside

7. Finally, a suspension button is added,

  • layout_anchor: specify an anchor point, where the anchor point is AppBarLayout
  • app:layout_anchorGravity = "bottom|end": the position relative to the anchor point
class GirlDetailActivity : AppCompatActivity() {

    companion object{
        const val GIRL_NAME="girl_name"
        const val GIRL_IMAGE="girl_image"
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_gril_detail)
        val girlName=intent.getStringExtra(GIRL_NAME)?:""
        val girlImageId=intent.getIntExtra(GIRL_IMAGE,0)
        setSupportActionBar(toolBar)
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        collapsingToolBar.title=girlName
        Glide.with(this).load(girlImageId).into(girlImage)
        content.text = initContent(girlName)

    }

    private fun initContent(girlName:String): String =girlName.repeat(500)

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId){
            android.R.id.home->{
                finish()
                return true
            }
        }
        return super.onOptionsItemSelected(item)
    }

}

Here is the code logic of the details page, setting the title of collapsingToobar, starting the HomeButton and rewriting the click event of menu

class GirlAdapter(private val context:Context): RecyclerView.Adapter<GirlAdapter.GirlHolder>() {

    private   val mGirlList:MutableList<BeautyGirl> =ArrayList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GirlHolder {
        val view:View = LayoutInflater.from(context).inflate(R.layout.girl_item,parent,false)
        val holder=GirlHolder(view)
        holder.itemView.setOnClickListener {
            val position=holder.adapterPosition
            val girl=mGirlList[position]
            val intent= Intent(context,GirlDetailActivity::class.java).apply {
                putExtra(GirlDetailActivity.GIRL_NAME,girl.name)
                putExtra(GirlDetailActivity.GIRL_IMAGE,girl.imageId)
            }
            context.startActivity(intent)
        }
        return holder
    }

    fun setData(girlList:MutableList<BeautyGirl>?){
        mGirlList.clear()
        girlList?.let { mGirlList.addAll(it) }
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return mGirlList.size
    }

    override fun onBindViewHolder(holder: GirlHolder, position: Int) {
        val girl= mGirlList[position]
        holder.girlName.text = girl.name
        Glide.with(context).load(girl.imageId).into(holder.girlImage)
    }

    class GirlHolder(view : View) : RecyclerView.ViewHolder(view){
        var girlImage:ImageView = view.findViewById(R.id.girlImage)
        var girlName:TextView = view.findViewById(R.id.girlName)
    }
   }

The click event of RecyclerView is added, and the parameters are passed to the details page, so that the title bar of the details page has a folding effect, which is very beautiful.

12. The background image does not match the vision of the system status bar

The background picture of the details page always doesn't match the system status bar. You can set android:fitsSystemWindows = "true" to true to indicate that the control appears in the system status bar.

Note that CoordinatorLayout, AppBarLayout, CollapsingToolbarLayout and ImageView need to be set

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context=".materila.GirlDetailActivity">
    <com.google.android.material.appbar.AppBarLayout android:id="@+id/appBar"
                                                     android:layout_width="match_parent"
                                                     android:fitsSystemWindows="true"
                                                     android:layout_height="250dp">
        <com.google.android.material.appbar.CollapsingToolbarLayout android:id="@+id/collapsingToolBar"
                                                                    android:layout_width="match_parent"
                                                                    android:layout_height="match_parent"
                                                                    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                                                                    app:contentScrim="@color/colorPrimary"
                                                                    android:fitsSystemWindows="true"
                                                                    app:layout_scrollFlags="scroll|exitUntilCollapsed">
            <ImageView
                    android:id="@+id/girlImage"
                    android:layout_width="match_parent"
                    android:scaleType="centerCrop"
                    android:layout_height="match_parent"
                    app:layout_collapseMode="parallax"
                    android:fitsSystemWindows="true"
            />

            <androidx.appcompat.widget.Toolbar
                    android:id="@+id/toolBar"
                    android:layout_width="match_parent"
                    android:layout_height="?actionBarSize"
                    app:layout_collapseMode="pin"
            />

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

...

</androidx.coordinatorlayout.widget.CoordinatorLayout>

In addition, you also need to set the system status bar to transparent status, and assign the following attribute to this detail page. Screens such as Qi bangs have effects, but Android 5 is required 0 or above.

<style name="girlActivityTheme" parent="AppTheme">
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

In this way, the system status bar is integrated with the background picture, which solves the problem that the background picture does not match the color of the system status bar.

Topics: Android Android Studio kotlin