bottom bar底部导航栏(选项卡)实例

时间:2022-07-09 17:09:37

目标:制作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:

bottom bar底部导航栏(选项卡)实例


点第二个tag:

bottom bar底部导航栏(选项卡)实例