Android (争取做到)最全的底部导航栏实现方法
2016-06-06 11:08
531 查看
本文(争取做到)Android 最全的底部导航栏实现方法.
现在写了4个主要方法.
还有一些个人感觉不完全切题的方法也会简单介绍一下.
说明一:还有另一种方式是用RadioGroup的方式,但是那种方式如果以后要包含小红点提醒或者右上角数字角标提醒,就不好灵活的修改了.所以本文忽略那种方法.
说明二:底部导航栏的4个ImageView使用的src, TextView使用的textColor都是seletor
然后看MainActivity.java
这种方法一的方式就是提前用mInflater.inflate4个View丢到PagerAdapter里面,再给ViewPager设置Adapter
然后把点击底部Tab的事件和滑动ViewPager的事件(主要包括图片和文字seletor切换)整合在一起.
activity_main.xml和上文一样.
我们看MainActivity.java
说明一:讲一下FragmentPagerAdapter 和 FragmentStatePagerAdapter 区别
1.FragmentStatePagerAdapter : 适合多个界面,类似于listView原理,离开视线就会被回收 会执行onDestroyView方法 onDestroy方法
2.FragmentPagerAdapter : 适合少量界面, 方便滑动 执行onDestroyView方法 不执行onDestroy方法
3.两者都会预先准备好并缓存上一个和下一个Fragment
说明二:重要说明:有个神方法viewPager.setOffscreenPageLimit(2); //设置向左和向右都缓存limit个页面.
我也是很晚才发现有这个方法.下面4个Tab, 只要你设置这个值为3, 那4个Tab永远都会缓存着了.
变态说明:这里告诉大家一个小技巧.ViewPager是V4包里面的.用到的FragmentPagerAdapter和FragmentStatePagerAdapter也是V4包里面的.
如果我们不想用android.support.v4.app.Fragment, 那就可以自己复制出来一个FragmentPagerAdapter,然后把里面的Fragment改成android.app.Fragment.
连带FragmentManager和FragmentTransaction也要改成android.app包下的
item_tab.xml 这个是下面部分4个Tab中其中一个Tab的布局, 以此来FragmentTabHost会帮忙批量生产出4个Tab
activity_main.xml
MainActivity.java
说明一: 重要说明:有些博主还需要写一个未选中的图片ResId数组和一个选中的图片ResId数组.然后根据点击自己在代码上写把图片切换成选中状态.Navie.
你只要传进去一组seletor图片,把文字颜色也设为seletor.FragmentTabHost叼的地方来了.它会自动把图片这个布局View下的所有子控件切换成selected状态.
所以我代码这些相关的逻辑没写,还是会变色.
说明二: 业务逻辑写在onTabChanged. 一般用到的几个核心方法 已经写在上面了
说明三: TabHost好像不能设置导航栏在底部. 所以只能用FragmentTabHost.
说明四: 切到别的页面,当前这个页面会执行到onDestroyView方法,不会执行onDestroy方法.
大致思路整理一下就是如下.
下面看代码.
activity_main.xml
本人核心封装
FragmentSwitchTool.java
MainActivity.java
说明一: 重要说明:FragmentSwitchTool把所有的操作都封装好在里面了.所以以后只需要写一个布局文件(注意要写成seletor的形式).
在MainActivity中写几行给FragmentSwitchTool的传参就行.
说明二: 过渡动画有点糙,随便写的,可以删掉.
注意这里说的是规范,所以当时并没有实现这个BottomNavigation这里有两篇文章可以看看。
原文: https://material.google.com/components/bottom-navigation.html 译文:https://modao.cc/posts/3068
但是谷歌并没有实现这个控件,所以目前民间有3个比较火的开源库,GitHub - aurelhubert/ahbottomnavigation,GitHub - roughike/BottomBar, Ashok-Varma/BottomNavigation。这3个库都很炫酷,动画很丰富。比如我有个小项目就用到了ahbottomnavigation。
然后在Android Support Library 25 后,Android 终于自己增加了一个控件 android.support.design.widget.BottomNavigationView。用法很简单,你甚至不用去看文档。直接在Android studio 里新建一个 BottomNavigation 的模板 Activity 就行。
然而官方这个相比网上那三个开源库,动画就相对朴素了。
总结:
方法一:创建就会一次性加载完四个页面.适合简单的页面,比如app一开始的导航页.
方法二:给力的方法.适合能左右滑动的页面.可以自己定制缓存策略.配合神方法,也能一开始就加载全部页面.
方法三:最大的好处是, 用的才加载. 一旦加载就不删除. 切换只用hide和show,速度飞快. 当然你也可以自己定制适合自己的缓存策略.
方法四:简单快捷.代码少.但是切换速度理论不够方法三快.
方法五:符合MD设计的,希望自己的APP炫酷一点的.毫无疑问都应该用BottomNavigation规范的控件。
下载地址: http://download.csdn.net/detail/alcoholdi/9565976
现在写了4个主要方法.
还有一些个人感觉不完全切题的方法也会简单介绍一下.
方法一. ViewPager + List<View> + PagerAdapter
先看activity_main.xml<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="45dp" android:background="#0E6DB0" android:gravity="center" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/app_name" android:textColor="#ffffff" android:textSize="20sp" android:textStyle="bold" /> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </android.support.v4.view.ViewPager> <LinearLayout android:layout_width="match_parent" android:layout_height="55dp" android:background="#0E6DB0" android:orientation="horizontal" > <LinearLayout android:id="@+id/llChat" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/ivChat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_chat" /> <TextView android:id="@+id/tvChat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="微信" android:textColor="@drawable/tab_textview" /> </LinearLayout> <LinearLayout android:id="@+id/llFriends" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/ivFriends" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_friends" /> <TextView android:id="@+id/tvFriends" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="朋友" android:textColor="@drawable/tab_textview" /> </LinearLayout> <LinearLayout android:id="@+id/llContacts" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/ivContacts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_contacts" /> <TextView android:id="@+id/tvContacts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="通讯录" android:textColor="@drawable/tab_textview" /> </LinearLayout> <LinearLayout android:id="@+id/llSettings" android:layout_width="0dp" android:layout_height="match_p 4000 arent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/ivSettings" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_setting" /> <TextView android:id="@+id/tvSettings" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="设置" android:textColor="@drawable/tab_textview" /> </LinearLayout> </LinearLayout> </LinearLayout>
说明一:还有另一种方式是用RadioGroup的方式,但是那种方式如果以后要包含小红点提醒或者右上角数字角标提醒,就不好灵活的修改了.所以本文忽略那种方法.
说明二:底部导航栏的4个ImageView使用的src, TextView使用的textColor都是seletor
然后看MainActivity.java
package com.yao.tab01; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { private List<View> views = new ArrayList<View>(); private ViewPager viewPager; private LinearLayout llChat, llFriends, llContacts, llSettings; private ImageView ivChat, ivFriends, ivContacts, ivSettings, ivCurrent; private TextView tvChat, tvFriends, tvContacts, tvSettings, tvCurrent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { viewPager = (ViewPager) findViewById(R.id.viewPager); llChat = (LinearLayout) findViewById(R.id.llChat); llFriends = (LinearLayout) findViewById(R.id.llFriends); llContacts = (LinearLayout) findViewById(R.id.llContacts); llSettings = (LinearLayout) findViewById(R.id.llSettings); llChat.setOnClickListener(this); llFriends.setOnClickListener(this); llContacts.setOnClickListener(this); llSettings.setOnClickListener(this); ivChat = (ImageView) findViewById(R.id.ivChat); ivFriends = (ImageView) findViewById(R.id.ivFriends); ivContacts = (ImageView) findViewById(R.id.ivContacts); ivSettings = (ImageView) findViewById(R.id.ivSettings); tvChat = (TextView) findViewById(R.id.tvChat); tvFriends = (TextView) findViewById(R.id.tvFriends); tvContacts = (TextView) findViewById(R.id.tvContacts); tvSettings = (TextView) findViewById(R.id.tvSettings); ivChat.setSelected(true); tvChat.setSelected(true); ivCurrent = ivChat; tvCurrent = tvChat; viewPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { changeTab(position); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); } private void initData() { LayoutInflater mInflater = LayoutInflater.from(this); View tab01 = mInflater.inflate(R.layout.tab01, null); View tab02 = mInflater.inflate(R.layout.tab02, null); View tab03 = mInflater.inflate(R.layout.tab03, null); View tab04 = mInflater.inflate(R.layout.tab04, null); views.add(tab01); views.add(tab02); views.add(tab03); views.add(tab04); MyPagerAdapter adapter = new MyPagerAdapter(views); viewPager.setAdapter(adapter); } @Override public void onClick(View v) { changeTab(v.getId()); } private void changeTab(int id) { ivCurrent.setSelected(false); tvCurrent.setSelected(false); switch (id) { case R.id.llChat: viewPager.setCurrentItem(0); case 0: ivChat.setSelected(true); ivCurrent = ivChat; tvChat.setSelected(true); tvCurrent = tvChat; break; case R.id.llFriends: viewPager.setCurrentItem(1); case 1: ivFriends.setSelected(true); ivCurrent = ivFriends; tvFriends.setSelected(true); tvCurrent = tvFriends; break; case R.id.llContacts: viewPager.setCurrentItem(2); case 2: ivContacts.setSelected(true); ivCurrent = ivContacts; tvContacts.setSelected(true); tvCurrent = tvContacts; break; case R.id.llSettings: viewPager.setCurrentItem(3); case 3: ivSettings.setSelected(true); ivCurrent = ivSettings; tvSettings.setSelected(true); tvCurrent = tvSettings; break; default: break; } } }
这种方法一的方式就是提前用mInflater.inflate4个View丢到PagerAdapter里面,再给ViewPager设置Adapter
然后把点击底部Tab的事件和滑动ViewPager的事件(主要包括图片和文字seletor切换)整合在一起.
方法二. ViewPager + List<Fragment> + FragmentPagerAdapter或FragmentStatePagerAdapter
这种方法就很常见了activity_main.xml和上文一样.
我们看MainActivity.java
package com.yao.tab02; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.app.Fragment; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { private List<Fragment> fragments = new ArrayList<Fragment>(); private ViewPager viewPager; private LinearLayout llChat, llFriends, llContacts, llSettings; private ImageView ivChat, ivFriends, ivContacts, ivSettings, ivCurrent; private TextView tvChat, tvFriends, tvContacts, tvSettings, tvCurrent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { viewPager = (ViewPager) findViewById(R.id.viewPager); llChat = (LinearLayout) findViewById(R.id.llChat); llFriends = (LinearLayout) findViewById(R.id.llFriends); llContacts = (LinearLayout) findViewById(R.id.llContacts); llSettings = (LinearLayout) findViewById(R.id.llSettings); llChat.setOnClickListener(this); llFriends.setOnClickListener(this); llContacts.setOnClickListener(this); llSettings.setOnClickListener(this); ivChat = (ImageView) findViewById(R.id.ivChat); ivFriends = (ImageView) findViewById(R.id.ivFriends); ivContacts = (ImageView) findViewById(R.id.ivContacts); ivSettings = (ImageView) findViewById(R.id.ivSettings); tvChat = (TextView) findViewById(R.id.tvChat); tvFriends = (TextView) findViewById(R.id.tvFriends); tvContacts = (TextView) findViewById(R.id.tvContacts); tvSettings = (TextView) findViewById(R.id.tvSettings); ivChat.setSelected(true); tvChat.setSelected(true); ivCurrent = ivChat; tvCurrent = tvChat; viewPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { changeTab(position); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); viewPager.setOffscreenPageLimit(2); //设置向左和向右都缓存limit个页面 } private void initData() { Fragment chatFragment = new ChatFragment(); Fragment friendsFragment = new FriendsFragment(); Fragment contactsFragment = new ContactsFragment(); Fragment settingsFragment = new SettingsFragment(); fragments.add(chatFragment); fragments.add(friendsFragment); fragments.add(contactsFragment); fragments.add(settingsFragment); MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getFragmentManager(), fragments); // MyFragmentStatePagerAdapter adapter = new MyFragmentStatePagerAdapter(getFragmentManager(), fragments); viewPager.setAdapter(adapter); } @Override public void onClick(View v) { changeTab(v.getId()); } private void changeTab(int id) { ivCurrent.setSelected(false); tvCurrent.setSelected(false); switch (id) { case R.id.llChat: viewPager.setCurrentItem(0); case 0: ivChat.setSelected(true); ivCurrent = ivChat; tvChat.setSelected(true); tvCurrent = tvChat; break; case R.id.llFriends: viewPager.setCurrentItem(1); case 1: ivFriends.setSelected(true); ivCurrent = ivFriends; tvFriends.setSelected(true); tvCurrent = tvFriends; break; case R.id.llContacts: viewPager.setCurrentItem(2); case 2: ivContacts.setSelected(true); ivCurrent = ivContacts; tvContacts.setSelected(true); tvCurrent = tvContacts; break; case R.id.llSettings: viewPager.setCurrentItem(3); case 3: ivSettings.setSelected(true); ivCurrent = ivSettings; tvSettings.setSelected(true); tvCurrent = tvSettings; break; default: break; } } }
说明一:讲一下FragmentPagerAdapter 和 FragmentStatePagerAdapter 区别
1.FragmentStatePagerAdapter : 适合多个界面,类似于listView原理,离开视线就会被回收 会执行onDestroyView方法 onDestroy方法
2.FragmentPagerAdapter : 适合少量界面, 方便滑动 执行onDestroyView方法 不执行onDestroy方法
3.两者都会预先准备好并缓存上一个和下一个Fragment
说明二:重要说明:有个神方法viewPager.setOffscreenPageLimit(2); //设置向左和向右都缓存limit个页面.
我也是很晚才发现有这个方法.下面4个Tab, 只要你设置这个值为3, 那4个Tab永远都会缓存着了.
变态说明:这里告诉大家一个小技巧.ViewPager是V4包里面的.用到的FragmentPagerAdapter和FragmentStatePagerAdapter也是V4包里面的.
如果我们不想用android.support.v4.app.Fragment, 那就可以自己复制出来一个FragmentPagerAdapter,然后把里面的Fragment改成android.app.Fragment.
连带FragmentManager和FragmentTransaction也要改成android.app包下的
暂时越过方法三的方法四. FragmentTabHost
跳过方法三,先讲方法四.方法四是代码量最少的方法.简单快捷轻便item_tab.xml 这个是下面部分4个Tab中其中一个Tab的布局, 以此来FragmentTabHost会帮忙批量生产出4个Tab
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="vertical" android:padding="5dp" > <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_setting" /> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@drawable/tab_textview" /> </LinearLayout>
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="45dp" android:background="#0E6DB0" android:gravity="center" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/app_name" android:textColor="#ffffff" android:textSize="20sp" android:textStyle="bold" /> </LinearLayout> <FrameLayout android:id="@+id/flContainer" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </FrameLayout> <com.yao.tab04.FragmentTabHost android:id="@+id/tabhost" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#0E6DB0" > </com.yao.tab04.FragmentTabHost> </LinearLayout>
MainActivity.java
package com.yao.tab04; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.Window; import android.widget.ImageView; import android.widget.TabHost.OnTabChangeListener; import android.widget.TabHost.TabSpec; import android.widget.TextView; public class MainActivity extends Activity implements OnTabChangeListener { private FragmentTabHost tabHost; private String[] tabText = { "聊天", "朋友", "通讯录", "设置" }; private int[] imageRes = new int[] { R.drawable.tab_chat, R.drawable.tab_friends, R.drawable.tab_contacts, R.drawable.tab_setting }; private Class[] fragments = new Class[] { ChatFragment.class, FriendsFragment.class, ContactsFragment.class, SettingsFragment.class }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); tabHost = (FragmentTabHost) super.findViewById(R.id.tabhost); tabHost.setup(this, super.getFragmentManager(), R.id.flContainer); tabHost.getTabWidget().setDividerDrawable(null); tabHost.setOnTabChangedListener(this); initTab(); } private void initTab() { for (int i = 0; i < tabText.length; i++) { View view = LayoutInflater.from(this).inflate(R.layout.item_tab, null); ((TextView) view.findViewById(R.id.tv)).setText(tabText[i]); ((ImageView) view.findViewById(R.id.iv)).setImageResource(imageRes[i]); TabSpec tabSpec = tabHost.newTabSpec(tabText[i]).setIndicator(view); tabHost.addTab(tabSpec, fragments[i], null); tabHost.setTag(i); } } //自动把getCurrentTabView下的所有子View的selected状态设为true. 牛逼! @Override public void onTabChanged(String tabId) { //首次打开自动会调用一下 首次自动输出tabId : 聊天 Log.e("yao", "tabId : " + tabId); // TabWidget tabWidget = tabHost.getTabWidget(); //获取整个底部Tab的布局, 可以通过tabWidget.getChildCount和tabWidget.getChildAt来获取某个子View // int pos = tabHost.getCurrentTab(); //获取当前tab的位置 // View view = tabHost.getCurrentTabView(); //获取当前 df59 tab的view } }
说明一: 重要说明:有些博主还需要写一个未选中的图片ResId数组和一个选中的图片ResId数组.然后根据点击自己在代码上写把图片切换成选中状态.Navie.
你只要传进去一组seletor图片,把文字颜色也设为seletor.FragmentTabHost叼的地方来了.它会自动把图片这个布局View下的所有子控件切换成selected状态.
所以我代码这些相关的逻辑没写,还是会变色.
说明二: 业务逻辑写在onTabChanged. 一般用到的几个核心方法 已经写在上面了
说明三: TabHost好像不能设置导航栏在底部. 所以只能用FragmentTabHost.
说明四: 切到别的页面,当前这个页面会执行到onDestroyView方法,不会执行onDestroy方法.
方法三. 用fragmentTransaction的show和hide方法隐藏和显示Fragment
网上这种代码已有,但是大多数写的很乱.大致思路整理一下就是如下.
if (想要的fragment == null) { if (当前显示的fragment != null) { 隐藏当前fragment } 生产想要的fragment } else if (想要的fragment == 当前显示的fragment) { } else { 隐藏当前fragment 显示想要的fragment }然后在中间插入该变化的资源selector代码
下面看代码.
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="45dp" android:background="#0E6DB0" android:gravity="center" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/app_name" android:textColor="#ffffff" android:textSize="20sp" android:textStyle="bold" /> </LinearLayout> <FrameLayout android:id="@+id/flContainer" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </FrameLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="55dp" android:background="#0E6DB0" android:orientation="horizontal" > <LinearLayout android:id="@+id/llChat" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/ivChat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_chat" /> <TextView android:id="@+id/tvChat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="微信" android:textColor="@drawable/tab_textview" /> </LinearLayout> <LinearLayout android:id="@+id/llFriends" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/ivFriends" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_friends" /> <TextView android:id="@+id/tvFriends" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="朋友" android:textColor="@drawable/tab_textview" /> </LinearLayout> <LinearLayout android:id="@+id/llContacts" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/ivContacts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_contacts" /> <TextView android:id="@+id/tvContacts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="通讯录" android:textColor="@drawable/tab_textview" /> </LinearLayout> <LinearLayout android:id="@+id/llSettings" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:id="@+id/ivSettings" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:src="@drawable/tab_setting" /> <TextView android:id="@+id/tvSettings" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="设置" android:textColor="@drawable/tab_textview" /> </LinearLayout> </LinearLayout> </LinearLayout>
本人核心封装
FragmentSwitchTool.java
/** * FileName:FragmentSwitchTool.java * Copyright YaoDiWei All Rights Reserved. */ package com.yao.tab03; import java.util.ArrayList; import java.util.List; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; /** * @author YaoDiWei * @version */ public class FragmentSwitchTool implements OnClickListener { private FragmentManager fragmentManager; private Fragment currentFragment; // private View currentClickableView; private View[] currentSelectedView; private View[] clickableViews; //传入用于被点击的view,比如是一个LinearLayout private List<View[]> selectedViews; //传入用于被更改资源selected状态的view[], 比如一组View[]{TextView, ImageView} private Class<? extends Fragment>[] fragments; private Bundle[] bundles; private int containerId; private boolean showAnimator; public FragmentSwitchTool(FragmentManager fragmentManager, int containerId) { super(); this.fragmentManager = fragmentManager; this.containerId = containerId; } public void setClickableViews(View... clickableViews) { this.clickableViews = clickableViews; for (View view : clickableViews) { view.setOnClickListener(this); } } public void setSelectedViews(List<View[]> selectedViews) { this.selectedViews = selectedViews; } public FragmentSwitchTool addSelectedViews(View... views){ if (selectedViews == null) { selectedViews = new ArrayList<View[]>(); } selectedViews.add(views); return this; } public void setFragments(Class<? extends Fragment>... fragments) { this.fragments = fragments; } public void setBundles(Bundle... bundles) { this.bundles = bundles; } public void changeTag(View v) { FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); Fragment fragment = fragmentManager.findFragmentByTag(String.valueOf(v.getId())); for (int i = 0; i < clickableViews.length; i++) { if (v.getId() == clickableViews[i].getId()) { //过渡动画 if (showAnimator) { int exitIndex = selectedViews.indexOf(currentSelectedView); // Log.e("yao", "enter : " + i + " exit: " + exitIndex); if (i > exitIndex){ fragmentTransaction.setCustomAnimations(R.anim.slide_right_in, R.anim.slide_left_out); } else if (i < exitIndex) { fragmentTransaction.setCustomAnimations(R.anim.slide_left_in, R.anim.slide_right_out); } } //过渡动画 if (fragment == null) { if (currentFragment != null) { fragmentTransaction.hide(currentFragment); for (View view : currentSelectedView) { view.setSelected(false); } } try { fragment = fragments[i].newInstance(); if (bundles != null && bundles[i] != null) { fragment.setArguments(bundles[i]); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } fragmentTransaction.add(containerId, fragment, String.valueOf(clickableViews[i].getId())); } else if (fragment == currentFragment) { } else { fragmentTransaction.hide(currentFragment); for (View view : currentSelectedView) { view.setSelected(false); } fragmentTransaction.show(fragment); } fragmentTransaction.commit(); currentFragment = fragment; for (View view : selectedViews.get(i)) { view.setSelected(true); } currentSelectedView = selectedViews.get(i); break; } } } @Override public void onClick(View v) { changeTag(v); } }
MainActivity.java
package com.yao.tab03; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.Window; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends Activity{ private LinearLayout llChat, llFriends, llContacts, llSettings; private ImageView ivChat, ivFriends, ivContacts, ivSettings; private TextView tvChat, tvFriends, tvContacts, tvSettings; private FragmentSwitchTool tool; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initView(); tool = new FragmentSwitchTool(getFragmentManager(), R.id.flContainer); tool.setClickableViews(llChat, llFriends, llContacts, llSettings); tool.addSelectedViews(new View[]{ivChat, tvChat}).addSelectedViews(new View[]{ivFriends, tvFriends}) .addSelectedViews(new View[]{ivContacts, tvContacts}).addSelectedViews(new View[]{ivSettings, tvSettings}); tool.setFragments(ChatFragment.class, FriendsFragment.class, ContactsFragment.class, SettingsFragment.class); tool.changeTag(llChat); } private void initView() { llChat = (LinearLayout) findViewById(R.id.llChat); llFriends = (LinearLayout) findViewById(R.id.llFriends); llContacts = (LinearLayout) findViewById(R.id.llContacts); llSettings = (LinearLayout) findViewById(R.id.llSettings); ivChat = (ImageView) findViewById(R.id.ivChat); ivFriends = (ImageView) findViewById(R.id.ivFriends); ivContacts = (ImageView) findViewById(R.id.ivContacts); ivSettings = (ImageView) findViewById(R.id.ivSettings); tvChat = (TextView) findViewById(R.id.tvChat); tvFriends = (TextView) findViewById(R.id.tvFriends); tvContacts = (TextView) findViewById(R.id.tvContacts); tvSettings = (TextView) findViewById(R.id.tvSettings); } }
说明一: 重要说明:FragmentSwitchTool把所有的操作都封装好在里面了.所以以后只需要写一个布局文件(注意要写成seletor的形式).
在MainActivity中写几行给FragmentSwitchTool的传参就行.
说明二: 过渡动画有点糙,随便写的,可以删掉.
方法五.
Bottom Navigation是5.0(API level 21)新出的一种符合MD规范的导航栏规范。注意这里说的是规范,所以当时并没有实现这个BottomNavigation这里有两篇文章可以看看。
原文: https://material.google.com/components/bottom-navigation.html 译文:https://modao.cc/posts/3068
但是谷歌并没有实现这个控件,所以目前民间有3个比较火的开源库,GitHub - aurelhubert/ahbottomnavigation,GitHub - roughike/BottomBar, Ashok-Varma/BottomNavigation。这3个库都很炫酷,动画很丰富。比如我有个小项目就用到了ahbottomnavigation。
然后在Android Support Library 25 后,Android 终于自己增加了一个控件 android.support.design.widget.BottomNavigationView。用法很简单,你甚至不用去看文档。直接在Android studio 里新建一个 BottomNavigation 的模板 Activity 就行。
然而官方这个相比网上那三个开源库,动画就相对朴素了。
总结:
方法一:创建就会一次性加载完四个页面.适合简单的页面,比如app一开始的导航页.
方法二:给力的方法.适合能左右滑动的页面.可以自己定制缓存策略.配合神方法,也能一开始就加载全部页面.
方法三:最大的好处是, 用的才加载. 一旦加载就不删除. 切换只用hide和show,速度飞快. 当然你也可以自己定制适合自己的缓存策略.
方法四:简单快捷.代码少.但是切换速度理论不够方法三快.
方法五:符合MD设计的,希望自己的APP炫酷一点的.毫无疑问都应该用BottomNavigation规范的控件。
下载地址: http://download.csdn.net/detail/alcoholdi/9565976
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories