现在的应用大多需要一个底部导航图来完成人性化的设置,这篇文章就来看一下比较流行的底部导航的实现:
目录:
三.TabLayout+fragment+viewPager
四.FragmentTabHost+ViewPager+fragment
七.TextView+LinearLayout+FrameLayout
fragment布局文件就是放了一个Textview显示:
代码:
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_fragment,null);
TextView textView = view.findViewById(R.id.text);
textView.setText(R.string.alert);
return view;
}
public static Fragment newInstance(){
AlertFragment homeFragment = new AlertFragment();
return homeFragment;
}
其他的fragmentt和此类似
uGoogle 发布了专门用来实现底部导航的控件,那就是BottomNavigationView,BottomNavigationView符合Material 风格,有着炫酷的切换动画,但是5.0以上才可以使用,BottomNavigationView使用较为简单:
新建一个Activity,选择BottomNavigation Activity,自动给你添加控件和代码
而BottomNavigationView 的Tab是通过menu 的方式添加的,所有看一下menu文件:
private TextView mTextMessage;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
return true;
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
case R.id.alert:
mTextMessage.setText(R.string.alert);
return true;
case R.id.email:
mTextMessage.setText(R.string.email);
return true;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_navigation_view_test);
mTextMessage = (TextView) findViewById(R.id.message);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setItemIconTintList(null);
}
BottomNavigationView使用较为简单,不需要你自己定义控件,只需要自己修改他给你定义的menu文件和回调方法
BottomNavigationBar和BottomNavigationView都是Google公司自己退出的,名字还是如此的相似,但是我却没有找出他们的联系和区别,这就让我很迷茫了,有知道的大佬可以告告我
现在说一下它的使用
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.2'
private int imageViewArray[] = {R.drawable.ic_home_black_24dp, R.drawable.ic_dashboard_black_24dp, R.drawable.ic_notifications_black_24dp, R.drawable.email, R.drawable.dialog_alert_icon};
private String[] strings = {"Home", "DashBoard", "Notification", "Email", "Alert"};
FragmentTransaction transaction;
FragmentManager manager;
BottomNavigationBar bar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_navigation_bar_test);
bar = findViewById(R.id.bottombar);
//角标,如同QQ的红点
final TextBadgeItem mBadgeItem = new TextBadgeItem()
.setBorderWidth(4)
.setAnimationDuration(200)
.setBackgroundColorResource(R.color.red)
.setHideOnSelect(false)
.setText("0");
bar.addItem(new BottomNavigationItem(imageViewArray[0], strings[0]).setActiveColorResource(R.color.black).setBadgeItem(mBadgeItem))
.addItem(new BottomNavigationItem(imageViewArray[1], strings[1]).setActiveColorResource(R.color.colorPrimary))
.addItem(new BottomNavigationItem(imageViewArray[2], strings[2]).setActiveColorResource(R.color.orange))
.addItem(new BottomNavigationItem(imageViewArray[3], strings[3]).setActiveColorResource(R.color.purple))
.addItem(new BottomNavigationItem(imageViewArray[4], strings[4]).setActiveColorResource(R.color.red))
.setFirstSelectedPosition(0)
.initialise();
bar.setTabSelectedListener(new BottomNavigationBar.OnTabSelectedListener() {
@Override
public void onTabSelected(int position) {
manager = getSupportFragmentManager();
transaction = manager.beginTransaction();
switch (position){
case 0:
transaction.replace(R.id.framelayout, HomeFragment.newInstance());
mBadgeItem.hide();
break;
case 1:
transaction.replace(R.id.framelayout, DashboardFragment.newInstance());
mBadgeItem.show();
break;
case 2:
transaction.replace(R.id.framelayout, NotificationFragment.newInstance());
break;
case 3:
transaction.replace(R.id.framelayout, EmailFragment.newInstance());
break;
case 4:
transaction.replace(R.id.framelayout,AlertFragment.newInstance());
break;
}
transaction.commit();
}
@Override
public void onTabUnselected(int position) {
}
@Override
public void onTabReselected(int position) {
}
});
//设置初始页面
setDefaultFragment();
}
private void setDefaultFragment() {
manager = getSupportFragmentManager();
transaction = manager.beginTransaction();
transaction.replace(R.id.framelayout, HomeFragment.newInstance());
transaction.commit();
}
只需要将回调方法重写,以及初始化fragment和viewPager
private List fragments;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_navigation_bar_test);
bar = findViewById(R.id.bottombar);
initPager();
final TextBadgeItem mBadgeItem = new TextBadgeItem()
.setBorderWidth(4)
.setAnimationDuration(200)
.setBackgroundColorResource(R.color.red)
.setHideOnSelect(false)
.setText("0");
bar.addItem(new BottomNavigationItem(imageViewArray[0], strings[0]).setActiveColorResource(R.color.black).setBadgeItem(mBadgeItem))
.addItem(new BottomNavigationItem(imageViewArray[1], strings[1]).setActiveColorResource(R.color.colorPrimary))
.addItem(new BottomNavigationItem(imageViewArray[2], strings[2]).setActiveColorResource(R.color.orange))
.addItem(new BottomNavigationItem(imageViewArray[3], strings[3]).setActiveColorResource(R.color.purple))
.addItem(new BottomNavigationItem(imageViewArray[4], strings[4]).setActiveColorResource(R.color.red))
.setFirstSelectedPosition(0)
.initialise();
bar.setTabSelectedListener(new BottomNavigationBar.OnTabSelectedListener() {
@Override
public void onTabSelected(int position) {
viewPager.setCurrentItem(position);
}
@Override
public void onTabUnselected(int position) {
}
@Override
public void onTabReselected(int position) {
}
});
setDefaultFragment();
}
private void initPager() {
viewPager = findViewById(R.id.viewpager);
fragments = new ArrayList();
fragments.add(HomeFragment.newInstance());
fragments.add(DashboardFragment.newInstance());
fragments.add(NotificationFragment.newInstance());
fragments.add(EmailFragment.newInstance());
fragments.add(AlertFragment.newInstance());
viewPager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
viewPager.setCurrentItem(0);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
bar.selectTab(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private List lists;
@Override
public Fragment getItem(int position) {
return lists == null ? null : lists.get(position);
}
@Override
public int getCount() {
return lists == null ? 0 : lists.size();
}
public MyFragmentPagerAdapter(FragmentManager fm, List datas) {
super(fm);
lists = datas;
}
public MyFragmentPagerAdapter() {
super(null);
}
}
要实现这样一个底部导航栏,大家最容易想到的当然就是TabLayout,Tab 切换嘛,TabLayout 就是专门干这个事的,不过TabLayout 默认是带有Indicator的,我们是不需要的,因此需要把它去掉
去掉默认的Indicator直接设置app:tabIndicatorHeight
属性的值为0就行了
private TabLayout tabLayout;
private List fragments;
private ViewPager viewPager;
private FragmentPagerAdapter adapter;
private String[] strings ={"Home","DashBoard","Notification","Email","Alert"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tablayout_test);
initView();
}
private void initView() {
tabLayout = findViewById(R.id.tablayout);
fragments = new ArrayList();
fragments.add(HomeFragment.newInstance());
fragments.add(DashboardFragment.newInstance());
fragments.add(NotificationFragment.newInstance());
fragments.add(EmailFragment.newInstance());
fragments.add(AlertFragment.newInstance());
viewPager = findViewById(R.id.viewpager);
adapter = new TitleFragmentPagerAdapter(getSupportFragmentManager(),fragments,strings);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
onTabItemSelected();
}
private void onTabItemSelected() {
for (int i =0;i mFragmentList = null;
private String[] titles;
public TitleFragmentPagerAdapter(FragmentManager mFragmentManager,
List fragmentList) {
super(mFragmentManager);
mFragmentList = fragmentList;
}
public TitleFragmentPagerAdapter(FragmentManager mFragmentManager,
List fragmentList, String[] titles) {
super(mFragmentManager);
mFragmentList = fragmentList;
this.titles = titles;
}
@Override
public int getCount() {
return mFragmentList.size();
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
if (position < mFragmentList.size()) {
fragment = mFragmentList.get(position);
} else {
fragment = mFragmentList.get(0);
}
return fragment;
}
@Override
public CharSequence getPageTitle(int position) {
if (titles != null && titles.length > 0)
return titles[position];
return null;
}
}
FragmentTabHost 可能是大家实现底部导航栏用得最多的一种方式,特别是在TabLayout 和 BottomNavigation 出来之前,是比较老的实现底部导航栏的方式,同时也是使用最多的一种
private ViewPager mViewPager;
private List fragments;
private FragmentTabHost host;
private int imageViewArray[] = { R.drawable.ic_home_black_24dp, R.drawable.ic_dashboard_black_24dp,R.drawable.ic_notifications_black_24dp,R.drawable.email,R.drawable.dialog_alert_icon};
private String[] strings ={"Home","DashBoard","Notification","Email","Alert"};
private FragmentPagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_tab_host_test);
initview();
}
private void initview(){
mViewPager = findViewById(R.id.viewpager);
fragments = new ArrayList();
fragments.add(HomeFragment.newInstance());
fragments.add(DashboardFragment.newInstance());
fragments.add(NotificationFragment.newInstance());
fragments.add(EmailFragment.newInstance());
fragments.add(AlertFragment.newInstance());
adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),fragments);
mViewPager.setAdapter(adapter);
mViewPager.addOnPageChangeListener(pageChangeListener);
host = findViewById(android.R.id.tabhost);
host.setup(this,getSupportFragmentManager(),R.id.viewpager);
host.getTabWidget().setDividerDrawable(null);
host.setOnTabChangedListener(onTabChangeListener);
int count = strings.length;
for (int i = 0;i lists;
@Override
public Fragment getItem(int position) {
return lists == null?null:lists.get(position);
}
@Override
public int getCount() {
return lists == null?0:lists.size();
}
public MyFragmentPagerAdapter(FragmentManager fm, List datas){
super(fm);
lists = datas;
}
public MyFragmentPagerAdapter(){
super(null);
}
}
TabHost需要你自己定义一个布局文件来显示图片和文字
RadioGroup +RadioButtom 是做单选的 所以用RadioGroup + RadioButton 来实现底部导航栏也是一种方式。但是要去掉他的默认样式,所以自己要定义一个样式:
private ViewPager mViewPager;
private RadioGroup radioGroup;
private List fragments;
private FragmentPagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_radio_group_test);
initview();
}
private void initview() {
mViewPager = findViewById(R.id.viewpager);
radioGroup = findViewById(R.id.radiogroup);
fragments = new ArrayList();
fragments.add(HomeFragment.newInstance());
fragments.add(DashboardFragment.newInstance());
fragments.add(NotificationFragment.newInstance());
fragments.add(EmailFragment.newInstance());
fragments.add(AlertFragment.newInstance());
adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments);
mViewPager.setAdapter(adapter);
mViewPager.addOnPageChangeListener(pageChangeListener);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
for (int i = 0; i < group.getChildCount(); i++) {
if (group.getChildAt(i).getId() == checkedId) {
mViewPager.setCurrentItem(i);
return;
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
mViewPager.removeOnPageChangeListener(pageChangeListener);
}
private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (radioGroup.getChildAt(position) instanceof RadioButton) {
RadioButton radioButton = (RadioButton) radioGroup.getChildAt(position);
radioButton.setChecked(true);
} else {
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
};
private class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private List lists;
@Override
public Fragment getItem(int position) {
return lists == null ? null : lists.get(position);
}
@Override
public int getCount() {
return lists == null ? 0 : lists.size();
}
public MyFragmentPagerAdapter(FragmentManager fm, List datas) {
super(fm);
lists = datas;
}
public MyFragmentPagerAdapter() {
super(null);
}
}
和第5个类似,但是在radiogroup添加一个view占格,然后创建个imageview覆盖view
private RadioGroup radioGroup;
private SparseArray fragments;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_test);
initview();
}
private void initview(){
radioGroup = findViewById(R.id.radiogroup);
fragments = new SparseArray() {};
fragments.append(R.id.radio1, HomeFragment.newInstance());
fragments.append(R.id.radio2, DashboardFragment.newInstance());
fragments.append(R.id.radio3, NotificationFragment.newInstance());
fragments.append(R.id.radio5, AlertFragment.newInstance());
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
fragments.get(checkedId)).commit();
}
});
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container,
fragments.get(R.id.radio1)).commit();
ImageView imageView = findViewById(R.id.imageview);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(IntentTest.this,TabLayoutTest.class));
}
});
}
这个我viewpager没有实现出来,所以就是抄的别人的(小小的吐槽一下)
在布局文件的根节点添加:
android:clipChildren="false"
clipChildren这个属性是在容器里面限制子控件能不能越界绘制,默认是true,也是可以实现底部中间大按钮的,此处就不给代码,诸位可以试试
此方法就是自己一个个定义TextView和Imageview来显示
这篇文章讲可以参考:https://blog.csdn.net/student9128/article/details/53463355
本文总结了实现底部导航栏的6种方式,其中TabLayout 和,BottomNavigationView和BottomNavigationBar 是Android 5.0 以后添加的新控件,符合Material 设计规范,如果是Materail 风格的,可以考虑用这两种实现
还有就是知道BottomNavigationView和BottomNavigationBar 区别和联系的大佬可以告我一下的
这是demo,需要的可以看一下