软件设计 2017-05-30
BottomNavigationView是Google推出的底部导航栏组件,在没有这些底部导航组件之前,Android开发者多使用的是RadioGroup,在上一个项目开发中我们使用了Google的BottomNaviationView与ViewPager相结合搭建了UI框架,现项目已经完成,总结如下:
使用BottomNaviationView需要添加依赖库:
在app moudle 里面的build.gradle文件中,dependencies节点下面添加如下依赖:
compile 'com.android.support:design:25.3.0'
添加完依赖我们便可以在布局文件中使用了,activity_main.xml文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.qj.simpleuiframe.MainActivity"> <!--状态栏--> <View android:layout_width="match_parent" android:layout_height="24dp" android:background="@color/color661BB5D7"/> <!--标题栏--> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="40dp" android:background="@color/color1BB5D7" android:gravity="center" android:textColor="@color/colorFFFFFF" android:textSize="20sp"/> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <!--底部导航栏--> <android.support.design.widget.BottomNavigationView android:id="@+id/bnv" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/windowBackground" app:itemIconTint="@drawable/tab_text_color_selector" app:itemTextColor="@drawable/tab_text_color_selector" app:menu="@menu/navigation"/> </LinearLayout>
先说说底部导航栏BottomNaviationView:app:menu="@menu/navigation" 这句说明:在我们的res文件夹下面有一个menu文件夹,menu文件夹里面有一个navigation文件,里面是关于我们底部导航栏的信息
我们来看看这个navigation.xml文件
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/tab_one" android:icon="@drawable/tab_one_selector" android:title="@string/tab_one"/> <item android:id="@+id/tab_two" android:icon="@drawable/tab_two_selector" android:title="@string/tab_two"/> <item android:id="@+id/tab_three" android:icon="@drawable/tab_three_selector" android:title="@string/tab_three"/> </menu>
我们看到里面总共有三个导航按钮,我们以第一个为例做一下简单的说明:id和title属性很简单,我们看一下icon属性,我们平时的底部导航按钮都是上图下文形式的(大多情况是这样),下面的文字是由我们的title属性指定的,上面的图片则是由我们这里的icon属性所决定的,我们看一看这个很简单的tab_one_selector选择器:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@mipmap/commend_select" android:state_pressed="true"/> <item android:drawable="@mipmap/commend_select" android:state_selected="true"/> <item android:drawable="@mipmap/commend"/> </selector>
到这app:menu="@menu/navigation" 就说完了下面说一下
app:itemIconTint="@drawable/tab_text_color_selector"app:itemTextColor="@drawable/tab_text_color_selector"
app:itemIconTint是设置底部导航按钮图标颜色的属性
app:itemTextColor是设置底部导航按钮文字颜色的属性
由于大多情况下图标和文件颜色都是相同的(为了统一风格样式),所以它们两个我用的是同一个颜色选择器
说到这BottomNaviationView这个控件就说完了,下面解释一下activity_main.xml文件中的状态栏控件,在布局中写状态栏的原因是因为我们的应用主题是没有ActionBar并且状态栏是透明的,所以状态栏和标题栏需要我们自己来写(也是为了满足用户定义不同样式的状态栏和标题栏的要求)
下面看一下appTheme这一主题:
<!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- 全屏、无标题栏、状态栏透明 --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:windowTranslucentStatus">true</item> </style>
可以看到AppTheme的父主题是没有ActionBar的,而且我们还设置了它的的windowTranslucentStatus为true,即状态栏透明这样我们的Activity就完全全屏了,没了状态栏和标题栏,我们就可以自己定义状态栏和标题栏了!到这里activity_main.xml文件就说完了,下面看一下MainActivity.Java中的代码
public class MainActivity extends FragmentActivity implements BottomNavigationView.OnNavigationItemSelectedListener, ViewPager.OnPageChangeListener { private ViewPager mViewPager; private BottomNavigationView mBottomNavigationView; private TextView mTitle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); initListener(); } private void initView() { mTitle = (TextView) findViewById(R.id.title); mBottomNavigationView = (BottomNavigationView) findViewById(R.id.bnv); mViewPager = (ViewPager) findViewById(R.id.viewpager); } private void initData() { } private void initListener() { mBottomNavigationView.setOnNavigationItemSelectedListener(this); //系统默认选中第一个,但是系统选中第一个不执行onNavigationItemSelected(MenuItem)方法,如果要求刚进入页面就执行clickTabOne()方法,则手动调用选中第一个 mBottomNavigationView.setSelectedItemId(R.id.tab_one);//根据具体情况调用 mViewPager.addOnPageChangeListener(this); //为viewpager设置adapter mViewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager())); } @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { //BottomNaviationView和ViewPager联动,当BottomNaviationView的某个tab按钮被选中了,同时设置ViewPager对应的页面被选中 int itemId = item.getItemId(); switch (itemId) { case R.id.tab_one: clickTabOne(); return true;//返回true,否则tab按钮不变色,未被选中 case R.id.tab_two: clickTabTwo(); return true; case R.id.tab_three: clickTabThree(); return true; default: break; } return false; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { //ViewPager和BottomNaviationView联动,当ViewPager的某个页面被选中了,同时设置BottomNaviationView对应的tab按钮被选中 switch (position) { case 0: mBottomNavigationView.setSelectedItemId(R.id.tab_one); break; case 1: mBottomNavigationView.setSelectedItemId(R.id.tab_two); break; case 2: mBottomNavigationView.setSelectedItemId(R.id.tab_three); break; default: break; } } @Override public void onPageScrollStateChanged(int state) { } private void clickTabOne() { //为防止隔页切换时,滑过中间页面的问题,去除页面切换缓慢滑动的动画效果 mViewPager.setCurrentItem(0, false); mTitle.setText("One"); } private void clickTabTwo() { mViewPager.setCurrentItem(1, false); mTitle.setText("Two"); } private void clickTabThree() { mViewPager.setCurrentItem(2, false); mTitle.setText("Three"); } }
代码中都有详细的注释,这里就不多说了,这里说一下ViewPager设置适配器,代码中创建了ViewPagerAdapter对象
public class ViewPagerAdapter extends FragmentPagerAdapter { //由于页面已经固定,故这里把Adapter需要的fragment提前创建 private Fragment[] mFragments = new Fragment[]{new OneFragment(), new TwoFragment(), new ThreeFragment()}; public ViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return mFragments[position]; } @Override public int getCount() { return 3; } }