一、BottomAppBar
BottomAppBar默认与FloatingActionButton配合,可以通过相应的属性实现对FloatingActionButton位置的控制。
使用例子:
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottomAppBar"
style="@style/Widget.MaterialComponents.BottomAppBar.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:fabAlignmentMode="center"
app:fabCradleMargin="6dp"
app:fabCradleRoundedCornerRadius="10dp"
app:elevation="6dp"
app:fabCradleVerticalOffset="0dp"
app:menu="@menu/menu_bottom_app_bar"
android:layout_gravity="bottom"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@+id/bottomAppBar"
app:layout_anchorGravity="center_horizontal"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
对BottomAppBar的属性分析:
- app:fabAlignmentMode:设置fab在BottomAppBar的位置
- app:fabCradleMargin:设置fab与BottomAppBar之间的间距
- app:fabCradleRoundedCornerRadius:设置BottomAppBar与fab之间的缺口的圆角程度,如果为0dp,则是一个尖角。其实就是BottomAppBar上边线与凹陷部分的过渡平滑程度。
- app:fabCradleVerticalOffset:设置fab与BottomAppBar的偏移量,值越大,fab越往上摆放,值越小,fab越向下摆放
- app:menu:BottomAppBar配合menu,在BottomAppBar上显示menu内容
在FloatingActionButton上,还需要设置两个属性:
- app:layout_anchor:设置锚点,以哪个控件为参考,这里需要设置BottomAppBar,将BottomAppBar作为参考,放在BottomAppBar的中间
- app:layout_anchorGravity="center_horizontal":设置fab的位置
BottomAppBar结合RecyclerView等滚动控件:
给RecyclerView设置
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
然后给BottomAppBar设置
app:hideOnScroll="true"
这样当RecyclerView向上滑动的时候,隐藏BottomAppBar。
设置三角形点的缺口
BottomAppBar mBottomAppBar = findViewById(R.id.bottom_app_bar);
float size = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, getResources().getDisplayMetrics());
TriangleEdgeTreatment triangleEdgeTreatment = new TriangleEdgeTreatment(size, true);
ShapePathModel shapePathModel = new ShapePathModel();
shapePathModel.setTopEdge(triangleEdgeTreatment);
MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable(shapePathModel);
materialShapeDrawable.setTint(0XFFDDDDDD);
mBottomAppBar.setBackground(materialShapeDrawable);
参考
https://www.jianshu.com/p/20dbe17d8c91
二、BottomNavigationView
1.使用例子:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
style="@style/Widget.Design.BottomNavigationView"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
android:background="@color/colorPrimary"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
app:itemIconTint="@color/bottom_nav"
app:itemTextColor="@color/bottom_nav"
app:labelVisibilityMode="labeled"
app:menu="@menu/menu_bottom_navigation_bar"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
BottomNavigationView是通过设置menu显示。
在使用BottomNavigationView的时候,一般就显示3个,当需要超过3个的时候,是默认不显示其他不选中的item的文本的,只显示选中的item的文本。
- app:itemIconTint="@color/bottom_nav":设置导航栏中图片的颜色,这里使用selector的颜色选择器,可以设置选中的时候和未选中的时候的颜色
- app:itemTextColor="@color/bottom_nav":设置导航栏中文本的颜色,设置选中和未选中的颜色
- itemBackground: 设置导航栏的背景颜色
bottom_nav的代码如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/color_512da8" android:state_checked="true" />
<item android:color="@android:color/holo_green_light" android:state_checked="false" />
</selector>
2.BottomNavigationView+navigation+NavHostFragment
在使用BottomNavigationView+navigation的时候需要注意一点,即给BottomNavigationView设置的menu中的item的id需要与navigation.xml中对应的切换的id一致。
(1)BottomNavigationView的menu布局
<?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/OneFragment"
android:icon="@drawable/ic_baseline_search_64"
app:showAsAction="ifRoom"
android:title="@string/action_search"/>
<item
android:id="@+id/TwoFragment"
android:icon="@drawable/ic_baseline_settings_64"
android:title="@string/settings"
app:showAsAction="ifRoom" />
<item
android:id="@+id/ThreeFragment"
android:icon="@drawable/ic_baseline_search_64"
app:showAsAction="ifRoom"
android:title="@string/action_search"/>
<item
android:id="@+id/FourFragment"
android:icon="@drawable/ic_baseline_settings_64"
android:title="@string/settings"
app:showAsAction="ifRoom" />
</menu>
(2)设置给fragment的app:navGraph="@navigation/main_navigation"
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/main_navigation"
app:startDestination="@+id/OneFragment">
<fragment
android:id="@+id/OneFragment"
android:name="com.nene.materialdesign.bottomNavigationView.fragment.OneFragment"
android:label="fragment_one"
tools:layout="@layout/fragment_one" />
<fragment
android:id="@+id/TwoFragment"
android:name="com.nene.materialdesign.bottomNavigationView.fragment.TwoFragment"
android:label="fragment_two"
tools:layout="@layout/fragment_two" />
<fragment
android:id="@+id/ThreeFragment"
android:name="com.nene.materialdesign.bottomNavigationView.fragment.ThreeFragment"
android:label="fragment_three"
tools:layout="@layout/fragment_three" />
<fragment
android:id="@+id/FourFragment"
android:name="com.nene.materialdesign.bottomNavigationView.fragment.FourFragment"
android:label="fragment_four"
tools:layout="@layout/fragment_four" />
</navigation>
对比menu.xml和main_navigation.xml,这里需要将对应的menu中的item的id与navigation中的fragment标签的id一一对应。否则在通过点击BottomNavigationView的时候,并不能通过BottomNavigationView与navigation的绑定而切换对应的Fragment。
(3)BottomNavigationView与Navigation的绑定
// 定义AppBarConfiguration
val appBarConfiguration = AppBarConfiguration.Builder(
R.id.OneFragment,
R.id.TwoFragment,
R.id.ThreeFragment,
R.id.FourFragment
).build()
// 初始化NavController控制器
val navController: NavController = Navigation.findNavController(this, R.id.my_nav_host_fragment)
// 绑定ActionBar与NavController
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)
// 绑定BottomNavigationView与NavController
NavigationUI.setupWithNavController(binding.bottomNavigationView, navController)
(4)使用Navigation的时候需要注意
在使用Navigation.findNavController(view).navigate()跳转到其他页面的时候,是只支持在navigation.xml中的fragment标签中添加<action>子标签的才可以。
比如:
Navigation.findNavController(banner).navigate(R.id.action_tab_to_browser, bundle)
举例说明:
下面的这个例子。给id为tabFragment的fragment添加了action标签,所以在tabFragment对应的Fragment以及这个Fragment中的其他Fragment还有这些action对应的Activity,都可以使用Navigation.findNavController跳转对应的页面。
比如:这个TabFragment中有一个ViewPager,这个ViewPager中有4个Fragment,比如是MainFragment、BlogFragment、ProjectFragment、ProfileFragment,那么TabFragment、MainFragment、BlogFragment、ProjectFragment、ProfileFragment、browserActivity、loginActivity、shareActivity、collectActivity、searchActivity这些页面都可以使用Navigation.findNavController().navigate(action标签的id)跳转到对应的action标签页面。
比如:MainFragment可以跳转到loginActivity。比如browserActivity可以跳转到searchActivity
但是其他没有action的fragment,则不可以使用Navigation.findNavController().navigate(action标签的id)跳转到对应的页面。
Navigation.findNavController().navigate(action标签的id)这里的action标签的id不能是其他的fragment的id,也不能是其他fragment中的action的id,必须是自己的。
然后想要使用也只能是自己或者自己的子Fragment或者自己的action才能使用对应的actionId跳转到对应的页面
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/navigation"
app:startDestination="@+id/tabFragment">
<!--
给NavigationActivity添加Fragment,然后给TabFragment添加对应的action
TabFragment里有多个Fragment,在这些Fragment中也可以使用TabFragment的navigation的action行为
这里的action也可以是Fragment,那么也可以直接开启Fragment,比如
-->
<fragment
android:id="@+id/tabFragment"
android:name="com.nene.mvvmwanandroid.ui.fragment.TabFragment"
android:label="fragment_tab"
tools:layout="@layout/activity_bottom_navigation" >
<!-- 这里定义的action,是在TabFragment可以通过navigation这里定义的action的id跳转到对应的页面 -->
<action
android:id="@+id/action_tab_to_browser"
app:destination="@+id/browserActivity" />
<action
android:id="@+id/action_tab_to_login"
app:destination="@+id/loginActivity" />
<action
android:id="@+id/action_tab_to_share"
app:destination="@+id/shareActivity" />
<action
android:id="@+id/action_tab_to_collect"
app:destination="@+id/collectActivity" />
<action
android:id="@+id/action_tab_to_search"
app:destination="@+id/searchActivity" />
</fragment>
<activity
android:id="@+id/loginActivity"
android:name="com.nene.mvvmwanandroid.ui.activity.LoginActivity"
android:label="activity_share"
tools:layout="@layout/activity_login">
</activity>
<activity
android:id="@+id/shareActivity"
android:name="com.nene.mvvmwanandroid.ui.activity.ShareActivity"
android:label="activity_share"
tools:layout="@layout/activity_share">
</activity>
<activity
android:id="@+id/browserActivity"
android:name="com.nene.mvvmwanandroid.ui.activity.BrowserActivity"
android:label="activity_share"
tools:layout="@layout/activity_browser">
<!-- 从tabFragment调整到BrowserActivity中传递参数 -->
<argument
android:name="url"
app:argType="string"
android:defaultValue="www.android.com" />
<argument
android:name="id"
app:argType="integer"
android:defaultValue="-1" />
<argument
android:name="title"
app:argType="string"
android:defaultValue="title" />
</activity>
<activity
android:id="@+id/collectActivity"
android:name="com.nene.mvvmwanandroid.ui.activity.CollectActivity"
android:label="activity_share"
tools:layout="@layout/activity_collect">
</activity>
<activity
android:id="@+id/searchActivity"
android:name="com.nene.mvvmwanandroid.ui.activity.SearchActivity"
android:label="activity_share"
tools:layout="@layout/activity_search">
</activity>
</navigation>
网友评论