从Android 3.0(API 11)开始,所有使用默认主题背景的Activity均使用ActionBar作为应用栏。不过,经过不同Android版本的演化,原生ActionBar的行为会有所不同,具体取决于设备用的是哪个版本的Android系统。所以Android提供了Toolbar,可以让这些功能在任何设备上保持一致。 所以,你应用使用支持库中的Toolbar来实现Activity的应用栏,来确保你的应用能在最大范围的设备上保持一致的行为。
在使用的时候你会发现除了androidx.appcompat.widget.Toolbar之后还有一个com.google.android.material.appbar.MaterialToolbar。 MaterialToolbar is a Toolbar that implements certain Material features, such as elevation overlays for Dark Themes.
-
禁止Action Bar
ToolBar相当于是ActionBar的替代版,因此需要制定一个不带ActionBar的主题, 可以通过自定义theme
继承xxx.NoActionBar
或者在theme
中通过以下配置来进行禁用ActionBar
。<item name="windowActionBar">false</item> <item name="android:windowNoTitle">true</item>
里面没有colorAccent
的颜色,唯独colorAccent这个属性比较难理解,它不是用来指定Checkbox等某一个按钮的颜色,而是更多表达了一个强调的意思,比如一些控件的选中状态也会使用colorAccent的颜色。 -
确保Activity继承自AppCompatActivity
-
在布局文件中进行声明 menu的实现如下:
<menu 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" tools:context=".MainActivity">
<item
android:id="@+id/action_search"
android:title="@string/action_search"
android:orderInCategory="100"
android:icon="@drawable/ic_action_search"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
app:showAsAction="never" />
</menu>
app:showAsAction属性用于指定操作是否应在应用栏中显示为按钮。如果您设置了app:showAsAction="ifRoom",那么只要应用栏中有足够的空间,此操作便会显示为按钮;如果空间不足,无法容纳的操作就会被发送到溢出菜单。如果您设置了app:showAsAction="never",此操作会始终列在溢出菜单中,而不会显示在应用栏中。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/tb_main"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/mtv_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hahahhd"
android:textSize="20sp" />
</LinearLayout>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mMaterialToolbar = findViewById<MaterialToolbar>(R.id.tb_main)
mMaterialToolbar.navigationIcon = getDrawable(R.drawable.vct_menu)
mMaterialToolbar.inflateMenu(R.menu.menu_toolbar_main)
mMaterialToolbar.title = "title"
mMaterialToolbar.setNavigationOnClickListener {
Snackbar.make(mMaterialToolbar, "click", Snackbar.LENGTH_SHORT).show()
}
mMaterialToolbar.setOnMenuItemClickListener {
Log.e("@@@", "lll")
true
}
// 将ToolBar设置为ActionBar,这样一设置后他就能像ActionBar一样直接显示menu目录中的菜单资源如果不用该方法,那ToolBar就只是一个普通的View,对menu要用inflateMenu去加载布局。
// setSupportActionBar(mMaterialToolbar);
// getSupportActionBar().setDisplayShowHomeEnabled(true);
}
如果Toolbar仅仅是用来对以往的ActionBar做一次替换,那也太没创意啦!完全没必要去替换了,因为它们表现出来的都是一样的,而且并没有让我们觉得用起来比ActionBar方便。那为啥要替换呢,总应该有他的理由吧:ActionBar是固定在顶部,并不能移动,我觉得这是最大的不好,而我们的ToolBar可以让我们随便摆放,就就可以带来很多灵活性和效果啦!
接下来我们看一下ToolBar
中具体有哪些内容:
ActionBar最左侧的这个按钮就叫做HomeAsUp按钮,它默认的图标是一个返回的箭头,含义是返回上一个活动,可以通过setDisplayHomeAsUpEnabled来让导航按钮显示出来。 可以在onOptionsItemSelected()方法中对HomeAsUp安阿牛的点击事件进行处理,HomeAsUp按钮的id永远都是android.R.id.home。 如需在 Activity 中支持向上功能,您需要声明 Activity 的父级。为此,您可以在应用清单中设置 android:parentActivityName 属性。 例如,假设应用有一个名为 MainActivity 的主 Activity 和一个子 Activity。以下清单代码声明了这两个 Activity,并指定了父/子关系:
<application ... >
...
<!-- The main/home activity (it has no parent activity) -->
<activity
android:name="com.example.myfirstapp.MainActivity" ...>
...
</activity>
<!-- A child of the main activity -->
<activity
android:name="com.example.myfirstapp.MyChildActivity"
android:label="@string/title_activity_child"
android:parentActivityName="com.example.myfirstapp.MainActivity" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.MainActivity" />
</activity>
</application>
如需为具有父 Activity 的 Activity 启用“向上”按钮,请调用应用栏的 setDisplayHomeAsUpEnabled() 方法。通常,您需要在创建 Activity 时调用此方法。例如,以下 onCreate() 方法将 Toolbar 设置为 MyChildActivity 的应用栏,然后启用该应用栏的“向上”按钮。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my_child)
// my_child_toolbar is defined in the layout file
setSupportActionBar(findViewById(R.id.my_child_toolbar))
// Get a support ActionBar corresponding to this toolbar and enable the Up button
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
您不需要在 Activity 的 onOptionsItemSelected() 方法中捕获向上操作。相反,该方法应该调用其父类,如响应操作中所示。该父类方法会根据应用清单的规定,通过导航到父 Activity 响应“向上”操作。
对于ToolBar
中的Menu
部分我们可以通过一下方法来设置:
toolbar.inflateMenu(R.menu.menu_main);
toolbar.setOnMenuItemClickListener();
或者也可以直接在Activity
的onCreateOptionsMenu
及onOptionsItemSelected
来处理。
现在想实现侧边栏结合Toolbar的效果。
<style name="Theme.JetpackSample.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="Theme.JetpackSample.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
<?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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<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"
// 指定状态栏的theme,例如状态栏中文字是灰还是白
android:theme="@style/Theme.JetpackSample.AppBarOverlay">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
// 指定menu等弹出的效果
app:popupTheme="@style/Theme.JetpackSample.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00f" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:srcCompat="@android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
把Toolbar设置成ActionBar,可以让我们少处理很多点击逻辑。
class MainActivity : BaseActivity() {
private val binding by viewBinding(ActivityMainBinding::inflate)
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
actionBarDrawerToggle = ActionBarDrawerToggle(
this,
binding.drawerLayout,
binding.toolbar,
R.string.open,
R.string.close
)
binding.drawerLayout.addDrawerListener(actionBarDrawerToggle)
actionBarDrawerToggle.syncState()
setSupportActionBar(binding.toolbar)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// navigation icon的点击交给actionbardrawertoggle来处理
if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// 处理其他menu的点击事件
when (item.itemId) {
R.id.action_settings -> Log.e("@@@", "settings")
}
return super.onOptionsItemSelected(item);
}
}
-
改变android.R.id.home返回图标。
-
Drawer拉出、隐藏,带有android.R.id.home动画效果。
-
监听Drawer拉出、隐藏;