Toolbar
A control provided by the AndroidX library to replace the ActionBar.
The detailed information
The ActionBar is the title bar at the top of each Activity, which is displayed by default for any new project. However, it is limited to the top of the Activity and cannot achieve Material Design effects, so it is no longer recommended. You can set it to a theme without ActionBar in the res/values/styles.xml file. More recommended is the Toolbar, which not only inherits all the functions of ActionBar, but also has high flexibility and can cooperate with other controls to achieve some Material Design effects.
Specify a topic without ActionBar. There are two common topics:
- Theme. AppCompat. NoActionBar. Represents a dark theme, which sets the main color of the interface to dark and the background color to light.
- Theme. AppCompat. Light. NoActionBar. Represents a light body, which sets the main color of the interface to light and the background color to dark.
Add controls to XML:
<LinearLayout
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:layout_height="match_parent">// A new namespace is specified because many Material properties were added to the new system for compatibility with the old system. / / it often can be used in the development of MD / / XMLNS: app = "http://schemas.android.com/apk/res-auto" / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / / Toolbar controls provided by appcompat library / / height is set to ActionBar height // Lets the Toolbar use a dark theme alone. // (The system theme is a light color, and the Toolbar will be a light color, so elements on it will automatically use dark colors to distinguish them from the main color, making the font black ugly.) // Specify the pop-up menu item as a light-colored theme separately. // (The Toolbar now has a dark theme, and if it contains a menu item, the pop-up menu item will also have a dark theme, which will be ugly.)<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="? attr/actionBarSize"
android:id="@+id/toolbar"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</LinearLayout>
Copy the code
Modify the text displayed on the title bar: Added the label attribute to the Activity. If not specified, the label content specified in the application is used by default.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.material">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ToolbarActivity"
android:label="Toolbar"/>
</application>
</manifest>
Copy the code
Add the action button: res directory -> Menu Folder -> New File (select Menu Resource 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">
// Define the action button with the item tag
// ------------------------------------------------------------------------
// app:showAsAction Specifies the display position of the button: (App namespace is also used for compatibility with earlier versions)
// always: always in the Toolbar, not if there is not enough screen space.
// ifRoom: displays in the Toolbar if screen space is sufficient, otherwise displays in the menu.
// never: displays in the menu forever.
// ------------------------------------------------------------------------
// Note: The Toolbar action button only displays the icon. The Action button in the menu displays only text.
<item android:id="@+id/backup"
android:icon="@drawable/ic_backup"
android:title="Backup"
app:showAsAction="always" />
<item android:id="@+id/delete"
android:icon="@drawable/ic_delete"
android:title="Delete"
app:showAsAction="ifRoom" />
<item android:id="@+id/settings"
android:icon="@drawable/ic_settings"
android:title="Settings"
app:showAsAction="never" />
</menu>
Copy the code
Modify code:
class ToolbarActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_toolbar)
// Call setSupportActionBar and pass in an instance of the Toolbar.
// This uses the Toolbar and makes it look and function the same as the ActionBar.
setSupportActionBar(toolbar)
}
/** * This method loads the toolanto. XML menu file */
override fun onCreateOptionsMenu(menu: Menu?).: Boolean {
menuInflater.inflate(R.menu.toolbar, menu)
return true
}
/** * handle button click events */
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.backup ->
Toast.makeText(this."You clicked Backup",Toast.LENGTH_SHORT).show()
R.id.delete ->
Toast.makeText(this."You clicked Delete",Toast.LENGTH_SHORT).show()
R.id.settings ->
Toast.makeText(this."You clicked Settings",Toast.LENGTH_SHORT).show()
}
return true}}Copy the code
Sliding menu
The so-called sliding menu is a hidden menu option, rather than placed on the home screen, and then can be sliding to display the menu. This method saves screen space and achieves very good animation.
DrawerLayout
It is a layout in which you can put two direct child controls. The first child control is what is displayed in the home screen, and the second child control is what is displayed in the slide menu.
Modify the XML code:
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/drawerLayout">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="? attr/actionBarSize"
android:id="@+id/toolbar"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</FrameLayout>
<! Slide menu display content, in fact, use any can be used, DrawerLayout does not limit the use of fixed controls. -->
<! However, the Android :layout_gravity property must be specified because it tells DrawerLayout whether the slide menu is on the left or right side of the screen. -->
<! -- Left: left. Right: Right. Start: Checks the system language. -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#FFF"
android:text="This is menu"
android:textSize="30sp" />
</androidx.drawerlayout.widget.DrawerLayout>
Copy the code
By default, menus can only be dragged out by dragging at the edge of the screen. Now add a navigation button to the far left of the Toolbar. Clicking the button will also display the contents of the slide menu.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
// Add navigation buttons for the slide menu
// call getSupportActionBar() to get an instance of the ActionBar, even though the ActionBar is implemented by the Toolbar.supportActionBar? .let {// If the ActionBar is not empty, do the following.
// Display the navigation button
it.setDisplayHomeAsUpEnabled(true)
// Set the navigation button icon.
// In fact, the left-most button of the Toolbar is called the Home button,
// Its default icon is a return arrow, meaning to return to the previous Activity, which has changed its default style and function.
it.setHomeAsUpIndicator(R.drawable.ic_menu)
}
}
...
/** * handle button click events */
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
// Handle the click event of the Home button. Its ID is always Android.r.home.
// Call DrawerLayout openDrawer() to display the slide menu, where the argument is specified as in XML.
android.R.id.home -> drawerLayout.openDrawer(GravityCompat.START)
...
}
return true}}Copy the code
NavigationView
NavigationView is a control provided in the Material library. It is not only designed strictly according to the Material Design requirements, but also can make the implementation of the sliding menu page very simple.
First add the dependency library:
implementation 'com. Google. Android. Material: material: 1.1.0'
// make the image round
implementation 'DE. Hdodenhof: circleimageview: 3.0.1'
Copy the code
Then go to res -> Menu -> New File (select Menu Resource File) :
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<! The group tag indicates a group, and single indicates that all menu items in the group are single-only. -->
<item android:id="@+id/navCall"
android:icon="@drawable/nav_call"
android:title="Call"/>
<item android:id="@+id/navFriends"
android:icon="@drawable/nav_friends"
android:title="Friends"/>
<item android:id="@+id/navLocation"
android:icon="@drawable/nav_location"
android:title="Location"/>
<item android:id="@+id/navMail"
android:icon="@drawable/nav_mail"
android:title="Mail"/>
<item android:id="@+id/navTask"
android:icon="@drawable/nav_task"
android:title="Tasks"/>
</group>
</menu>
Copy the code
Prepare headerLayout, which is a customized layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
android:padding="10dp"
android:background="@color/colorPrimary">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="70dp"
android:layout_height="70dp"
android:id="@+id/iconImage"
android:src="@drawable/nav_icon"
android:layout_centerInParent="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tvMailText"
android:layout_alignParentBottom="true"
android:text="[email protected]"
android:textColor="#FFF"
android:textSize="14sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tvUserText"
android:layout_above="@id/tvMailText"
android:text="Tony Green"
android:textColor="#FFF"
android:textSize="14sp"/>
</RelativeLayout>
Copy the code
Modify the layout page code:
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/drawerLayout">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="? attr/actionBarSize"
android:id="@+id/toolbar"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</FrameLayout>
<! NavigationView --> NavigationView
<com.google.android.material.navigation.NavigationView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/navView"
android:layout_gravity="start"
app:menu="@menu/nav_menu"
app:headerLayout="@layout/navheader"/>
</androidx.drawerlayout.widget.DrawerLayout>
Copy the code
Handle click events for NavigationView’s menu items:
// Handle click events for NavigationView's menu items
navView.setCheckedItem(R.id.navCall)
// Set a listener for the menu item selected event
navView.setNavigationItemSelectedListener {
// Handle the logic for menu item selection here
// Close the slide menu and return true to indicate that the event has been handled.
drawerLayout.closeDrawers()
true
}
Copy the code
Hover buttons and interactive prompts
Facade design is a very important design idea in MD, and hover button is one of the simplest and most representative facade design.
FloatingActionButton
It is a control provided in the Material library to make it easier to hover buttons. It uses colorAccent as the button’s color by default, and you can name the button by specifying an icon for what the button does.
Modify the layout code:
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/drawerLayout">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">.<! -- end: According to the system language, end means on the right if it is from left to right. Otherwise, end is on the left. -->
<! App :elevation="8dp" :elevation The larger the value, the larger the projection range, but the lighter the projection effect. Generally, use the default value. -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fab"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_done"
/>
</FrameLayout>.</androidx.drawerlayout.widget.DrawerLayout>
Copy the code
Handling click events:
// Handle the click event for the hover Button, just like a Button.
fab.setOnClickListener{
Toast.makeText(this."FAB clicked",Toast.LENGTH_SHORT).show()
}
Copy the code
Snackbar
Tooltip:
- The purpose of Toast is to tell the user what is happening now, but the user can only passively receive this event.
- Snackbar allows you to add an interactive button to the prompt. (For example, you can undo actions the user is currently doing, such as accidentally deleting data.)
// Interactive prompt tool
Call make() to create a Snackbar object.
// The first argument can be any View of the current layout. Snackbar will use this View to automatically find the outermost layout and display the prompt information.
// Call setAction() to set an action
Snackbar.make(view,"Data deleted",Snackbar.LENGTH_SHORT).setAction("Undo"){
Toast.makeText(this."Data restored",Toast.LENGTH_SHORT).show()
}.show()
Copy the code
CoordinatorLayout
It’s an enhanced version of FrameLayout, provided by the AndroidX library. It works basically the same as FrameLayout in normal cases, but it has some additional Material abilities.
In fact, CoordinatorLayout can listen to all the child controls for various events and automatically respond to the most reasonable. For example, if the Snackbar suggestion above hides the float button, the CoordinatorLayout will automatically shift the internal FloatingActionButton upwards if it can listen to the Snackbar’s eject event. (Although the Snackbar is not a child, the first argument the Snackbar receives, View, specifies the view on which the Snackbar is triggered, and we pass in the FloatingActionButton itself, The FloatingActionButton is a child of the CoordinatorLayout, so the event can be heard.)
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/drawerLayout">
<! -- You replace FrameLayout, and the CoordinatorLayout itself is an enhanced version of FrameLayout, so there are no side effects. -->
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="? attr/actionBarSize"
android:id="@+id/toolbar"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fab"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_done"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>.</androidx.drawerlayout.widget.DrawerLayout>
Copy the code
Card layout
Card layout is also a new concept in MD, which allows elements on a page to look like they are in a card, with rounded corners and shadows.
MaterialCardView
It is an important control provided by the Material library for implementing card-like layout effects. In fact, it is also a FrameLayout, but with extra rounded corners and shadows, it will look like a three-dimensional citrus.
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="5dp"
app:cardCornerRadius="4dp">
<! App :cardCornerRadius: Specifies the degree of the card corner -->
<! App :elevation: specify the card elevation -->
</com.google.android.material.card.MaterialCardView>
Copy the code
Then combine RecyclerView and Glide to show:
First add dependencies:
implementation 'androidx. Recyclerview: recyclerview: 1.1.0'
implementation 'com. Making. Bumptech. Glide: glide: 4.9.0'
Copy the code
Then define an entity class:
class Fruit(val name: String,val imageId:Int)
Copy the code
Then specify a custom layout for RecyclerView’s children:
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="5dp"
app:cardCornerRadius="4dp">
<! App :cardCornerRadius: Specifies the degree of the card corner -->
<! App :elevation: specify the card elevation -->
<! -- The MaterialCardView is a FrameLayout. There is no convenient way to locate the MaterialCardView. -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<! ScaleType refers to the zoom mode of the image, and centerCrop refers to filling the ImageView with the image at its original scale and trimming off the parts that are out of the screen. -->
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="@+id/iv"
android:scaleType="centerCrop" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv"
android:layout_gravity="center_horizontal"
android:layout_margin="5dp"
android:textSize="16sp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
Copy the code
Prepare an adapter for RecyclerView:
class FruitAdapter(val mContext: Context,val mList:List<Fruit>):RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
inner class ViewHolder(view: View):RecyclerView.ViewHolder(view){
val iv:ImageView = view.findViewById(R.id.iv)
val tv:TextView = view.findViewById(R.id.tv)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitAdapter.ViewHolder {
val view =LayoutInflater.from(mContext).inflate(R.layout.item_cardview,parent,false)
return ViewHolder(view)
}
override fun getItemCount(a) = mList.size
override fun onBindViewHolder(holder: FruitAdapter.ViewHolder, position: Int) {
val fruit = mList[position]
holder.tv.text = fruit.name
Glide.with(mContext).load(fruit.imageId).into(holder.iv)
}
}
Copy the code
Finally modify the code in MainActivity:
class MainActivity : AppCompatActivity() {
val fruits = mutableListOf(Fruit("Apple", R.drawable.apple),
Fruit("Banana", R.drawable.banana),
Fruit("Orange", R.drawable.orange),
Fruit("Watermelon", R.drawable.watermelon),
Fruit("Pear", R.drawable.pear),
Fruit("Grape", R.drawable.grape),
Fruit("Pineapple", R.drawable.pineapple),
Fruit("Strawberry", R.drawable.strawberry),
Fruit("Cherry", R.drawable.cherry),
Fruit("Mango", R.drawable.mango))
val fruitList = ArrayList<Fruit>()
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
initData()
}
private fun initData(a) {
initFruits()
val layoutManager = GridLayoutManager(this.2)
recyclerView.layoutManager = layoutManager
val adapter = FruitAdapter(this,fruitList)
recyclerView.adapter = adapter
}
private fun initFruits(a) {
fruitList.clear()
repeat(50) {val index = (0 until fruits.size).random()
fruitList.add(fruits[index])
}
}
private fun initView(a){... }... }Copy the code
Note: When introducing the Material library, also need to res/values/style.css. XML AppTheme parent Theme instead of the Theme. MaterialComponents. Light. NoActionBar, Otherwise, you may experience crash problems when using the following controls.
<resources>
<! -- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<! -- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
Copy the code
AppBarLayout
In the example above, you end up with RecyclerView blocking out the Toolbar because they’re all placed in CoordinatorLayout, which is a reinforced FrameLayout, The controls in FrameLayout are in the upper left corner by default, which creates occlusion. Because of CoordinatorLayout, there are some more ingenious solutions.
AppBarLayout is another tool provided in the Material library. It is actually a vertical LinearLayout that encapsulates a lot of rolling events inside and applies some MD design concepts.
There are only two steps to solve the above example:
- Nest the Toolbar in AppBarLayout
- Specify a layout behavior for RecyclerView
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/drawerLayout">
<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">// Nest the Toolbar in AppBarLayout<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="? attr/actionBarSize"
android:id="@+id/toolbar"
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:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recyclerView"/ / toRecyclerViewSpecify a layout behaviorapp:layout_behavior="@string/appbar_scrolling_view_behavior"/>.</androidx.coordinatorlayout.widget.CoordinatorLayout>.</androidx.drawerlayout.widget.DrawerLayout>
Copy the code
In fact, when RecyclerView scrolls, AppBarLayout is notified of scrolling events. When AppBarLayout receives scrolling events, its child controls can specify how to respond to those events. Through the app:layout_scrollFlags property.
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="? attr/actionBarSize"
android:id="@+id/toolbar"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
// srcoll: Indicates that when the RV scrolls up, the Toolbar scrolls up and hides.
// enterAlways: indicates that when the RV scrolls down, the Toolbar scrolls down and redisplays.
// Snap: Indicates that when the Toolbar is not fully hidden or displayed, it will automatically choose to hide or show based on the current sliding distance.
app:layout_scrollFlags="scroll|enterAlways|snap"/>
Copy the code
The drop-down refresh
SwipeRefreshLayout is the core class that implements the drop-down refresh function.
First add dependencies:
implementation 'androidx. Swiperefreshlayout: swiperefreshlayout: 1.1.0'
Copy the code
Modify the layout file:
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"/ / becauseRecyclerViewIt becomes a subclass, soapp:layout_behaviorThe declared layout behavior is also moved over.app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recyclerView"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
Copy the code
Modify the MainActivity code:
private fun initView(a) {
// Set the color of the drop-down refresh progress bar
swipeRefresh.setColorSchemeResources(R.color.colorPrimary)
// Set the listener for the pull-down refresh
swipeRefresh.setOnRefreshListener {
refreshFruits(adapter)
}
}
private fun refreshFruits(adapter: FruitAdapter) {
thread {
// The local refresh operation is very fast, so we put the thread to sleep for two seconds to see the refresh effect.
Thread.sleep(2000)
// Switch back to the main thread
runOnUiThread{
initFruits()
adapter.notifyDataSetChanged()
// Call setRefreshing() and pass false to indicate the end of the refresh event and hide the refresh progress bar.
swipeRefresh.isRefreshing = false}}}Copy the code
Collapsible title bar
CollapsingToolbarLayout
It is a layout that works on top of the Toolbar provided by the Material library. It makes the Toolbar much richer, not just to show a title bar, but to be very flashy.
Note that CollapsingToolbarLayout does not exist independently and was limited to be used as a direct child of AppBarLayout at design time. AppBarLayout must be a child of CoordinatorLayout.
Example (Kotlin) :
Create a detail page for the RecyclerView item:
<androidx.coordinatorlayout.widget.CoordinatorLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FruitActivity">
<! -- Title bar -->
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp">
<! The android:theme attribute specifies a theme, which is the same as the previous Toolbar, except for a more advanced Toolbar effect that requires the theme designation up a level. -->
<! The app:contentScrim property is used to specify the background color in CollapsingToolbarLayout as it collapses and after the collapse. When folded, this is a normal Toolbar. -->
<! -- app:layout_scrollFlags Scroll indicates that information rolls with it, exitUntilCollapsed indicates that information remains on the interface after folding and does not move out of the screen. -->
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/collapsingToolbar"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="@color/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<! The advanced title bar is a combination of a normal title bar and an image.
<! -- app:layout_collapseMode specifies the collapse mode of the control in CollapsingToolbarLayout. Pin means the position is always the same and parallax means there will be a dislocation in the collapse toolbarLayout. -->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ivFruit"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"/>
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="? attr/actionBarSize"
android:id="@+id/toolbar"
app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<! -- Content section -->
<! -- NestedScrollView (ScrollView, NestedScrollView)
<! Since CoordinatorLayout can already respond to scrolling events, it needs to use a layout like NestedScrollView or RecyclerView internally. -->
<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_marginBottom="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="35dp"
app:cardCornerRadius="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tvFruitContent"
android:layout_margin="10dp"/>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<! -- Use app:layout_anchor to set an anchor so that the hover button will appear in the title bar area. -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_comment"
app:layout_anchor="@id/appBar"
app:layout_anchorGravity="bottom|end"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Copy the code
Modify the code in FruitActivity:
class FruitActivity : AppCompatActivity() {
companion object{
const val FRUIT_NAME = "fruit_name"
const val FRUIT_IMAGE_ID = "fruit_image_id"
}
private var fruitName = ""
private var fruitImageId = 0
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fruit)
initView()
initData()
}
private fun initData(a){ fruitName = intent.getStringExtra(FRUIT_NAME)? :""
fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID,0)
collapsingToolbar.title = fruitName
Glide.with(this).load(fruitImageId).into(ivFruit)
tvFruitContent.text = generateFruitContent(fruitName)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
android.R.id.home -> {
finish()
return true}}return super.onOptionsItemSelected(item)
}
private fun generateFruitContent(fruitName: String) = fruitName.repeat(500)
private fun initView(a){ setSupportActionBar(toolbar) supportActionBar? .setDisplayHomeAsUpEnabled(true)}}Copy the code
Modify the code in the FruitAdapter and add the click event:
class FruitAdapter(val mContext: Context,val mList:List<Fruit>):RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
inner class ViewHolder(view: View):RecyclerView.ViewHolder(view){
val iv:ImageView = view.findViewById(R.id.iv)
val tv:TextView = view.findViewById(R.id.tv)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitAdapter.ViewHolder {
val view =LayoutInflater.from(mContext).inflate(R.layout.item_cardview,parent,false)
val holder = ViewHolder(view)
holder.itemView.setOnClickListener{
val position = holder.adapterPosition
val fruit = mList[position]
val intent = Intent(mContext,FruitActivity::class.java).apply {
putExtra(FruitActivity.FRUIT_NAME,fruit.name)
putExtra(FruitActivity.FRUIT_IMAGE_ID,fruit.imageId)
}
mContext.startActivity(intent)
}
return holder
}
override fun getItemCount(a) = mList.size
override fun onBindViewHolder(holder: FruitAdapter.ViewHolder, position: Int) {
val fruit = mList[position]
holder.tv.text = fruit.name
Glide.with(mContext).load(fruit.imageId).into(holder.iv)
}
}
Copy the code
Make full use of system status bar space
After the Android 5.0 system, can through the Android: fitsSystemWindows attribute to the background of the status bar, or color.
In CoordinatorLayout, AppBarLayout, CollapsingToolbarLayout this nested structure layout, the control of the android: fitsSystemWindows attribute specifies into true, This means that the control will appear in the system status bar, and all parent layouts in the control layout structure will be set to this property.
Modify the layout code:
<androidx.coordinatorlayout.widget.CoordinatorLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FruitActivity"// Add attributesandroid:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="250dp"// Add attributesandroid:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/collapsingToolbar"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:contentScrim="@color/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"// Add attributesandroid:fitsSystemWindows="true">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ivFruit"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"// Add attributesandroid:fitsSystemWindows="true"/>.</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>.</androidx.coordinatorlayout.widget.CoordinatorLayout>
Copy the code
Next set the status bar color to transparent in the program’s subject:
<resources>. // Define a theme specifically for FruitActivity. It inherits the parent theme and all its features, and is customized on top of it.<style name="FruitActivityTheme" parent="AppTheme">// Specify a transparent color for the status bar<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
Copy the code
Finally use this theme:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.material">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">.<activity
android:name=".FruitActivity"
android:theme="@style/FruitActivityTheme">
</activity>
</application>
</manifest>
Copy the code
note
References:
Line 1 of code (Version 3)
Welcome to follow wechat official account:No reason also