目标:制作bottom bar底部导航栏(选项卡),导航后的内容在同一个Fragment空间显示。(没有用什么特别的控件,都是应用普通控件实现)
例子:
主XML - index.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <FrameLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </FrameLayout> <com.testApp5.NavigateBottomBar android:id="@+id/uiNavigateBottomBar" android:layout_width="match_parent" android:layout_height="60dp" /> </LinearLayout>
导航XML - bottom_bar.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal" android:background="@drawable/test" > <LinearLayout android:id="@+id/message_layout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_centerVertical="true" android:layout_marginTop="5dp" android:layout_weight="1" android:orientation="vertical" > <ImageView android:id="@+id/message_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:src="@drawable/test1" /> <TextView android:id="@+id/message_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="消息" android:textColor="#82858b" /> </LinearLayout> <LinearLayout android:id="@+id/contacts_layout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_centerVertical="true" android:layout_marginTop="5dp" android:layout_weight="1" android:orientation="vertical" > <ImageView android:id="@+id/contacts_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:src="@drawable/test1" /> <TextView android:id="@+id/contacts_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="联系人" android:textColor="#82858b" /> </LinearLayout> <LinearLayout android:id="@+id/news_layout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_centerVertical="true" android:layout_marginTop="5dp" android:layout_weight="1" android:orientation="vertical" > <ImageView android:id="@+id/news_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:src="@drawable/test1" /> <TextView android:id="@+id/news_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="动态" android:textColor="#82858b" /> </LinearLayout> <LinearLayout android:id="@+id/setting_layout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_centerVertical="true" android:layout_marginTop="5dp" android:layout_weight="1" android:orientation="vertical" > <ImageView android:id="@+id/setting_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:src="@drawable/test1" /> <TextView android:id="@+id/setting_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="设置" android:textColor="#82858b" /> </LinearLayout> </LinearLayout>
主Activity - IndexActiviy.java
import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.graphics.Color; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.ImageView; import android.widget.TextView; public class IndexActivity extends Activity { private View layoutIndex; // index layout @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 初始化布局元素 // requestWindowFeature(Window.FEATURE_NO_TITLE); initViews(); } /** * 在这里获取到每个需要用到的控件的实例,并给它们设置好必要的点击事件。 */ private void initViews() { layoutIndex = LayoutInflater.from(getApplicationContext()).inflate(R.layout.index, null); setContentView(layoutIndex); // NavigateBottomBar NavigateBottomBar uiNavigateBottomBar = (NavigateBottomBar)findViewById(R.id.uiNavigateBottomBar); uiNavigateBottomBar.setActivity(this); // 第一次启动时选中第一个tab View messageLayout = (View)findViewById(R.id.message_layout); messageLayout.performClick(); } }
导航条 - NavigateBottomBar.java
其中,最主要的是两个方法:setTabSelectStyle 和 setTabSelectFragment,前者设置选项卡点击后不同的行为,后者则设置fragment 内容。
import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Context; import android.graphics.Color; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class NavigateBottomBar extends LinearLayout implements OnClickListener { public NavigateBottomBar(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater layoutInflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); layoutInflater.inflate(R.layout.bottom_bar, this); // 初始化布局元素 initViews(); } private View homeLayout; // 消息界面布局 private View tongueLayout; // 联系人界面布局 private View searchLayout; // 动态界面布局 private View aboutLayout; // 设置界面布局 private ImageView homeImage; // 消息图标 private ImageView tongueImage; // 联系人图标 private ImageView searchImage; // 动态图标 private ImageView aboutImage; // 设置图标 private TextView homeText; // 消息标题 private TextView tongueText; // 联系人标题 private TextView searchText; // 动态标题 private TextView aboutText; // 设置标题 private UnderBuilding homeFragment; // 用于展示消息的Fragment private TongueFragment tongueFragment; // 用于展示联系人的Fragment private UnderBuilding searchFragment; // 用于展示动态的Fragment private UnderBuilding aboutFragment; // 用于展示设置的Fragment private FragmentTransaction transaction; // 用于对Transaction进行管理 private Activity activity; /** * 在这里获取到每个需要用到的控件的实例,并给它们设置好必要的点击事件。 */ private void initViews() { homeLayout = findViewById(R.id.message_layout); tongueLayout = findViewById(R.id.contacts_layout); searchLayout = findViewById(R.id.news_layout); aboutLayout = findViewById(R.id.setting_layout); homeImage = (ImageView) findViewById(R.id.message_image); tongueImage = (ImageView) findViewById(R.id.contacts_image); searchImage = (ImageView) findViewById(R.id.news_image); aboutImage = (ImageView) findViewById(R.id.setting_image); homeText = (TextView) findViewById(R.id.message_text); tongueText = (TextView) findViewById(R.id.contacts_text); searchText = (TextView) findViewById(R.id.news_text); aboutText = (TextView) findViewById(R.id.setting_text); homeLayout.setOnClickListener(this); tongueLayout.setOnClickListener(this); searchLayout.setOnClickListener(this); aboutLayout.setOnClickListener(this); } @Override public void onClick(View v) { // 开启一个Fragment事务 if (getActivity().getFragmentManager() != null) { transaction = getActivity().getFragmentManager().beginTransaction(); if (transaction != null) { switch (v.getId()) { case R.id.message_layout: // 当点击了消息tab时,选中第1个tab setTabSelectStyle(0); setTabSelectFragment(0); break; case R.id.contacts_layout: // 当点击了联系人tab时,选中第2个tab setTabSelectStyle(1); setTabSelectFragment(1); break; case R.id.news_layout: // 当点击了动态tab时,选中第3个tab setTabSelectStyle(2); setTabSelectFragment(2); break; case R.id.setting_layout: // 当点击了设置tab时,选中第4个tab setTabSelectStyle(3); setTabSelectFragment(3); break; default: break; } transaction.commit(); } } } /** * 根据传入的index参数来设置选中的tab页。 * * @param index * 每个tab页对应的下标。0表示消息,1表示联系人,2表示动态,3表示设置。 */ private void setTabSelectStyle(int index) { // 每次选中之前先清楚掉上次的选中状态 clearTabSelectStyle(); // 开启一个Fragment事务 switch (index) { case 0: // 当点击了消息tab时,改变控件的图片和文字颜色 homeImage.setImageResource(R.drawable.test1); homeText.setTextColor(Color.WHITE); break; case 1: // 当点击了联系人tab时,改变控件的图片和文字颜色 tongueImage.setImageResource(R.drawable.test1); tongueText.setTextColor(Color.WHITE); break; case 2: // 当点击了动态tab时,改变控件的图片和文字颜色 searchImage.setImageResource(R.drawable.test1); searchText.setTextColor(Color.WHITE); break; case 3: default: // 当点击了设置tab时,改变控件的图片和文字颜色 aboutImage.setImageResource(R.drawable.test1); aboutText.setTextColor(Color.WHITE); break; } } /** * 清除掉所有的选中状态。 */ private void clearTabSelectStyle() { homeImage.setImageResource(R.drawable.test); homeText.setTextColor(Color.parseColor("#82858b")); tongueImage.setImageResource(R.drawable.test); tongueText.setTextColor(Color.parseColor("#82858b")); searchImage.setImageResource(R.drawable.test); searchText.setTextColor(Color.parseColor("#82858b")); aboutImage.setImageResource(R.drawable.test); aboutText.setTextColor(Color.parseColor("#82858b")); } private void setTabSelectFragment(int index) { // 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况 hideTabFragments(transaction); switch (index) { case 0: if (homeFragment == null) { // 如果UnderBuilding为空,则创建一个并添加到界面上 homeFragment = new UnderBuilding(); transaction.add(R.id.content, homeFragment); } else { // 如果UnderBuilding不为空,则直接将它显示出来 transaction.show(homeFragment); } break; case 1: if (tongueFragment == null) { final String TONGUE = "tongueFragment"; // 如果UnderBuilding为空,则创建一个并添加到界面上 tongueFragment = new TongueFragment(); transaction.add(R.id.content, tongueFragment, TONGUE); } else { // 如果UnderBuilding不为空,则直接将它显示出来 transaction.show(tongueFragment); } break; case 2: if (searchFragment == null) { // 如果UnderBuilding为空,则创建一个并添加到界面上 searchFragment = new UnderBuilding(); transaction.add(R.id.content, searchFragment); } else { // 如果UnderBuilding不为空,则直接将它显示出来 transaction.show(searchFragment); } break; case 3: default: if (aboutFragment == null) { // 如果UnderBuilding为空,则创建一个并添加到界面上 aboutFragment = new UnderBuilding(); transaction.add(R.id.content, aboutFragment); } else { // 如果UnderBuilding不为空,则直接将它显示出来 transaction.show(aboutFragment); } break; } } /** * 将所有的Fragment都置为隐藏状态。 * * @param transaction * 用于对Fragment执行操作的事务 */ private void hideTabFragments(FragmentTransaction transaction) { final String TONGUE_RESULT = "tongueResultFragment"; if (homeFragment != null) { transaction.hide(homeFragment); } if (tongueFragment != null) { transaction.hide(tongueFragment); } if (searchFragment != null) { transaction.hide(searchFragment); } if (aboutFragment != null) { transaction.hide(aboutFragment); } Fragment tongueResultFragment = getActivity().getFragmentManager().findFragmentByTag(TONGUE_RESULT); if (tongueResultFragment != null && tongueResultFragment instanceof TongueResultFragment) { transaction.remove(tongueResultFragment); } } public Activity getActivity() { return activity; } public void setActivity(Activity activity) { this.activity = activity; } }
一些辅助类:
import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class UnderBuilding extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate(R.layout.under_building, container, false); return layout; } }
under_building.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:padding="10dp" android:text="建设中。。。" android:textSize="20sp" /> </LinearLayout> </RelativeLayout>
效果图,点第一个tag:
点第二个tag: