本篇文章是接上一篇文章 Android开发——ViewPage的使用,使用了其中的例子。
谷歌设计TabLayout的本意是用来实现顶部菜单的,但是也可以作为底部菜单来使用,而BottomNavigationView基本上只能用来作为底部菜单使用。本篇文章就是介绍ViewPage和这两种控件的组合使用。
一、ViewPage和TabLayout
1.TabLayout作为顶部菜单
在上一篇文章中我们使用fragment和ViewPage实现侧滑菜单,现在只需要在布局文件中加入TabLayout然后把TabLayout和ViewPage联系在一起就可以了。
首先修改主布局文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="com.example.test.MainActivity">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_marginTop="0dp"
android:background="#1FBCD2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tabIndicatorColor="#ff0000"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabSelectedTextColor="#FFFFFF"
app:tabTextColor="#000000"></android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPage"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="0dp"
android:layout_marginTop="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tabs"
app:layout_constraintVertical_bias="0.0"></android.support.v4.view.ViewPager>
</android.support.constraint.ConstraintLayout>
很好理解,只是在ViewPage上添加了一个TabLayout。
- app:tabBackground:TabLayout的背景颜色
- app:tabIndicatorColor:菜单指示器的颜色
- app:tabSelectedTextColor:菜单选中时的颜色
app:tabTextColor:菜单未选中时的颜色
下面介绍TabLayout的两个重要属性:
app:tabMode:有两个可选选项,分别是fixed和scrollable
- app:tabGravity:有两个可选选项,分别是fill和center
当app:tabMode设置值scrollable表示此TabLayout中当子view超出屏幕边界时候,将提供滑动以便滑出不可见的那些子view。
这里列举两种常见的情况:
- 菜单项很多:app:tabMode设置为scrollable,app:tabGravity设置为center
- 菜单项很少:app:tabMode设置为fixed,app:tabGravity设置为fill
这里给出一张图解释他们的具体区别:
修改MainActivity中的代码:
package com.example.test;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager; //对应的viewPager
private List<TabLayout.Tab> tabList;
private TabLayout tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPage);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabList = new ArrayList<>();
ViewPageFragmentAdapter adapter = new ViewPageFragmentAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1());
adapter.addFragment(new Fragment2());
adapter.addFragment(new Fragment3());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
tabList.add(tabLayout.getTabAt(0));
tabList.add(tabLayout.getTabAt(1));
tabList.add(tabLayout.getTabAt(2));
tabList.get(0).setText("标签一");
tabList.get(1).setText("标签二");
tabList.get(2).setText("标签三");
}
}
首先通过tabLayout的setupWithViewPager()方法与ViewPage设置联系,然后通过List< TabLayout.Tab >添加菜单项并设置标题。
2.TabLayout作为底部菜单
其实TabLayout作为底部菜单就是把TabLayout放在布局的底部,但是底部菜单一般都是图片加文字的组合,TabLayout也可以进行这样的设置。为了方便我们使用之前的布局,在布局底部再添加一个TabLayout。
修改主布局文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="com.example.test.MainActivity">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_marginTop="0dp"
app:tabBackground="@color/colorAccent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tabIndicatorColor="#fff"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabSelectedTextColor="#FFFFFF"
app:tabTextColor="#000000"></android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPage"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="0dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tabs"
android:layout_marginBottom="0dp"
app:layout_constraintBottom_toTopOf="@+id/bottom_tabs"></android.support.v4.view.ViewPager>
<android.support.design.widget.TabLayout
android:id="@+id/bottom_tabs"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_marginBottom="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:tabBackground="@color/colorAccent"
app:tabGravity="fill"
app:tabIndicatorHeight="0dp"
app:tabMode="fixed"
app:tabSelectedTextColor="#FFFFFF"
app:tabTextColor="#000000"></android.support.design.widget.TabLayout>
</android.support.constraint.ConstraintLayout>
只是在底部添加了一个TabLayout,注意底部菜单一般是没有指示条的,所以添加一个属性 app:tabIndicatorHeight=”0dp”将指示条高度设置为0,也就是隐藏。
修改MainActivity中的代码:
package com.example.test;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager; //对应的viewPager
private List<TabLayout.Tab> tabList;
private TabLayout tabLayout;
private List<TabLayout.Tab> tabList2;
private TabLayout tabLayout2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPage);
//顶部菜单
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabList = new ArrayList<>();
ViewPageFragmentAdapter adapter = new ViewPageFragmentAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1());
adapter.addFragment(new Fragment2());
adapter.addFragment(new Fragment3());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
tabList.add(tabLayout.getTabAt(0));
tabList.add(tabLayout.getTabAt(1));
tabList.add(tabLayout.getTabAt(2));
tabList.get(0).setText("标签一");
tabList.get(1).setText("标签二");
tabList.get(2).setText("标签三");
//底部菜单
tabLayout2 = (TabLayout) findViewById(R.id.bottom_tabs);
tabList2 = new ArrayList<>();
tabLayout2.setupWithViewPager(viewPager);
tabList2.add(tabLayout2.getTabAt(0));
tabList2.add(tabLayout2.getTabAt(1));
tabList2.add(tabLayout2.getTabAt(2));
tabList2.get(0).setText("标签一").setIcon(R.mipmap.ic_launcher);
tabList2.get(1).setText("标签二").setIcon(R.mipmap.ic_launcher);
tabList2.get(2).setText("标签三").setIcon(R.mipmap.ic_launcher);
}
}
这里只是把TabLayout复制了一份,同样把他和ViewPage建立联系,注意我们在设置标签后添加了一项setIcon,设置图标,这是顶部菜单和底部菜单的主要区别。
到这里ViewPage和TabLayout的使用就介绍完了。
二、ViewPage和BottomNavigationView
在本例中我们仍然使用以前的ViewPage的布局和适配器。
1.首先新建一个布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.test.MainActivity2">
<android.support.v4.view.ViewPager
android:id="@+id/viewPage"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="0dp"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="0dp"
app:layout_constraintBottom_toTopOf="@+id/navigation"></android.support.v4.view.ViewPager>
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_marginBottom="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.896"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/navigation" />
</android.support.constraint.ConstraintLayout>
布局只有两个控件,底部是一个BottomNavigationView,内容是一个ViewPage。
2.BottomNavigationView的底部导航栏
app:menu=”@menu/navigation”这个属性就是给导航栏设置菜单项,这个和我们在标题栏上放设置菜单项的原理是一样的。在menu文件夹下(如果你的工程没有这个文件夹,就建一个)新建navigation.xml,在里面写要展示的菜单项,先看一下代码:
navigation.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:icon="@drawable/ic_chat_black_24dp"
android:title="@string/title_home" />
<item
android:id="@+id/navigation_dashboard"
android:icon="@drawable/ic_mms_black_24dp"
android:title="@string/title_dashboard" />
<item
android:id="@+id/navigation_notifications"
android:icon="@drawable/ic_notifications_black_24dp"
android:title="@string/title_notifications" />
</menu>
这里设置了三个菜单项,注意我使用的是矢量图,icon代表菜单项图标,title菜单项文字。
3.新建一个Activity
package com.example.test;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity2 extends AppCompatActivity {
private ViewPager viewPager;
private MenuItem menuItem;
private BottomNavigationView bottomNavigationView;
//BottomNavigationView的监听事件
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
//点击菜单项时跳转ViewPage
viewPager.setCurrentItem(0);
return true;
case R.id.navigation_dashboard:
viewPager.setCurrentItem(1);
return true;
case R.id.navigation_notifications:
viewPager.setCurrentItem(2);
return true;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
viewPager = (ViewPager) findViewById(R.id.viewPage);
bottomNavigationView= (BottomNavigationView) findViewById(R.id.navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
ViewPageFragmentAdapter adapter = new ViewPageFragmentAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1());
adapter.addFragment(new Fragment2());
adapter.addFragment(new Fragment3());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
// 将当前的页面对应的底部标签设为选中状态
if (menuItem != null) {
menuItem.setChecked(false);
} else {
bottomNavigationView.getMenu().getItem(0).setChecked(false);
}
menuItem = bottomNavigationView.getMenu().getItem(position);
menuItem.setChecked(true);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
//禁止ViewPager滑动
// viewPager.setOnTouchListener(new View.OnTouchListener() {
// @Override
// public boolean onTouch(View v, MotionEvent event) {
// return true;
// }
// });
}
}
上面的代码很简单,注释已经说的很清楚了,主要就是BottomNavigationView 和ViewPage的监听,当点击BottomNavigationView 时跳转ViewPage页面,当滑动ViewPage时跳转BottomNavigationView 。
这样就完成了一个简单的 BottomNavigationView 控件。该控件有几个地方需要注意的:
底部导航栏高度默认是 56dp。
菜单元素只能是 3~5 个。如果个数少于3个或者多于5个,则会报错。
icon 的选中颜色默认是 @color/colorPrimary。当然你也可以使用 app:itemIconTint=”@android:color/white” 来自定义,这样定以后,所有的 icon 颜色都是这个了。
菜单元素文字的默认颜色是 @color/colorPrimary。你可以使用 app:itemTextColor=”@android:color/white” 自定义。
底部导航栏背景颜色默认是当前样式的背景色(白色/黑色),你可以使用 app:itemBackground=”@android:color/black” 来更改。
关于BottomNavigationView 大于三个时的显示效果的调整等信息参照下面的文章:
http://blog.csdn.net/xiaoyangsavvy/article/details/70213537
http://blog.csdn.net/iwanttohitren/article/details/64537087