首先工程來(lái)自github上的Android工程 FragmentNavigator窟绷,新手有興趣可以去下載運(yùn)行。
看了工程所有的代碼接奈,我來(lái)總結(jié)一下主要的實(shí)現(xiàn)步驟:
主要使用以下兩個(gè)類 FragmentNavigator踢涌、BottomNavigatorView來(lái)實(shí)現(xiàn)下方tabBar控制器切換(Android通常叫做Fragment,因本人做iOS的)
private FragmentNavigator?mNavigator;
private BottomNavigatorView?bottomNavigatorView;//底部tab區(qū)域視圖
1序宦、其中FragmentNavigator是封裝的類睁壁,定義了showFragment
方法? ,BottomNavigatorView繼承于LinearLayoutCompat(其中LinearLayoutCompat是對(duì)LinearLayout擴(kuò)展和兼容
)
2、MainActivity實(shí)現(xiàn)了BottomNavigatorView
類的OnBottomNavigatorViewItemClickListener
接口潘明,BottomNavigatorView
類實(shí)現(xiàn)了如下構(gòu)造方法
public BottomNavigatorView(Context context, AttributeSet attrs,int defStyleAttr) {
? ? super(context, attrs, defStyleAttr);
? ? setOrientation(HORIZONTAL);
? ? inflate(context, R.layout.layout_bottom_navigator,this);
? ? for (int i =0; i < getChildCount(); i++) {
? ? ? ? View view = getChildAt(i);
? ? ? ? final int finalI = i;
? ? ? ? view.setOnClickListener(new OnClickListener() {
? ? ? ? ? ? @Override //點(diǎn)擊tab會(huì)調(diào)用
? ? ? ? ? ? public void onClick(View v) {//tab事件首先在這里觸發(fā)的P屑痢!G怠厚宰!
? ? ? ? ? ? ? ? System.out.println("setOnClickListener1");
? ? ? ? ? ? ? ? //調(diào)用了接口方法,onBottomNavigatorViewItemClick方法在MainActivity類中實(shí)現(xiàn)
? ? ? ? ? ? ? ? mOnBottomNavigatorViewItemClickListener.onBottomNavigatorViewItemClick(finalI, v);
? ? ? ? ? ? }
? ? ? ? });
? ? }
}
MainActivity類中
@Override? //實(shí)現(xiàn)了接口方法
public void onBottomNavigatorViewItemClick(int position, View view) {
? ? System.out.println("我響應(yīng)了接口方法");
? ? setCurrentTab(position);
}
private void setCurrentTab(int position) {
? ? mNavigator.showFragment(position);//用來(lái)實(shí)現(xiàn)切換動(dòng)畫(huà)
? ? bottomNavigatorView.select(position);//用來(lái)選中tab位置遂填,改變tab文字與圖標(biāo)顏色
}
其中showFragment方法是FragmentNavigator
類封裝的铲觉,select方法是BottomNavigatorView
類封裝的
public void showFragment(int position,boolean reset,boolean allowingStateLoss) {
? ? this.mCurrentPosition = position;
? ? FragmentTransaction transaction =mFragmentManager.beginTransaction();
? ? int count =mAdapter.getCount();
? ? for (int i =0; i < count; i++) {
? ? ? ? if (position == i) {
? ? ? ? ? ? if (reset) {
? ? ? ? ? ? ? ? remove(position, transaction);
? ? ? ? ? ? ? ? add(position, transaction);
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? show(i, transaction);
? ? ? ? ? ? }
? ? ? ? }else {
? ? ? ? ? ? hide(i, transaction);
? ? ? ? }
? ? }
? ? if (allowingStateLoss) {
? ? ? ? transaction.commitAllowingStateLoss();
? ? }else {
? ? ? ? transaction.commit();
? ? }
}
//點(diǎn)擊tab會(huì)調(diào)用
? ? public void select(int position) {
? ? ? ? System.out.println("position:"+position);
? ? ? ? for (int i =0; i < getChildCount(); i++) {
? ? ? ? ? ? View child = getChildAt(i);
? ? ? ? ? ? if (i == position) {
? ? ? ? ? ? ? ? selectChild(child,true);
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? selectChild(child,false);
? ? ? ? ? ? }
? ? ? ? }
? ? }
3、在MainActivity類中構(gòu)造方法中
@Override
protected void onCreate(Bundle savedInstanceState) {
? ? super.onCreate(savedInstanceState);
? ? setContentView(R.layout.activity_main);
? ? mNavigator =new FragmentNavigator(getSupportFragmentManager(),new FragmentAdapter(), R.id.container);
? ? mNavigator.setDefaultPosition(DEFAULT_POSITION);//設(shè)置tab的默認(rèn)位置
? ? mNavigator.onCreate(savedInstanceState);
? ? bottomNavigatorView = (BottomNavigatorView) findViewById(R.id.bottomNavigatorView);
? ? if (bottomNavigatorView != null) {
? ? ? ? bottomNavigatorView.setOnBottomNavigatorViewItemClickListener(this);//把實(shí)例對(duì)象傳給了BottomNavigatorView
類中的接口OnBottomNavigatorViewItemClickListener
? ? }
? ? setCurrentTab(mNavigator.getCurrentPosition());
?? //注冊(cè)廣播
? ? BroadcastManager.register(this,mLoginStatusChangeReceiver, Action.LOGIN, Action.LOGOUT);
}
其中做了三件很重要的事情:
1吓坚、設(shè)置tab的默認(rèn)位置
2撵幽、創(chuàng)建BottomNavigatorView類,并把當(dāng)前實(shí)例傳給BottomNavigatorView的接口OnBottomNavigatorViewItemClickListener礁击,
3盐杂、注冊(cè)廣播(類似iOS開(kāi)發(fā)中的NSNotificationCenter),register可以傳字符串?dāng)?shù)組哆窿,用于登錄后頁(yè)面的切換跳轉(zhuǎn)况褪,數(shù)據(jù)的存儲(chǔ)。
接口interface定義onBottomNavigatorViewItemClick方法:
public interface OnBottomNavigatorViewItemClickListener {
? ? void onBottomNavigatorViewItemClick(int position, View view);
}
其中Java的interface類似iOS中的協(xié)議Protocol(代理Delegete)
4更耻、廣播的創(chuàng)建與接收测垛,BroadcastReceiver是一個(gè)abstract
抽象類
private BroadcastReceivermLoginStatusChangeReceiver =new BroadcastReceiver() {
? ? @Override//接受廣播回調(diào)
? ? public void onReceive(Context context, Intent intent) {
? ? ? ? String action = intent.getAction();
? ? ? ? if (!TextUtils.isEmpty(action)) {
? ? ? ? ? ? int position = intent.getIntExtra("EXTRA_POSITION", -1);
? ? ? ? ? ? if (action.equals(Action.LOGIN)) {
? ? ? ? ? ? ? ? onUserLogin(position);
? ? ? ? ? ? }else if (action.equals(Action.LOGOUT)) {
? ? ? ? ? ? ? ? onUserLogout(position);
? ? ? ? ? ? }
? ? ? ? }
? ? }
};
控制器銷毀時(shí)要移除廣播的注冊(cè)unregister
@Override
protected void onDestroy() {
? ? BroadcastManager.unregister(this,mLoginStatusChangeReceiver);
? ? super.onDestroy();
}
如何在XML文件中引入Java類名 <com.aspsine.fragmentnavigator.demo.ui.widget.BottomNavigatorView
<?xml version="1.0" encoding="utf-8"?>
<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"
? ? tools:context=".ui.activity.MainActivity">
? ? <FrameLayout
? ? ? ? android:id="@+id/container"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="0dp"
? ? ? ? android:layout_weight="1" />
? ? <com.aspsine.fragmentnavigator.demo.ui.widget.BottomNavigatorView
? ? ? ? android:id="@+id/bottomNavigatorView"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="56dp"
? ? ? ? android:clipToPadding="false"
? ? ? ? android:background="@android:color/white"
? ? ? ? android:elevation="8dp" />
</LinearLayout>
另外提醒:作者封裝了兩個(gè)類在library文件夾中:FragmentNavigator、接口?FragmentNavigatorAdapter