FragmentTabHost+Fragment隨意配置菜單數(shù)量

在工作中敲霍,我們或許會(huì)遇到不同角色登錄時(shí)候备禀,因?yàn)椴煌慕巧砸簿陀胁煌臋?quán)限,那么他所看到的角色菜單也就完全不一樣伍纫,效果如下:

![QQ截圖20160708180418.png](http://upload-images.jianshu.io/upload_images/2310529-dc88de673cd788d3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

不多說(shuō)松却,Code如下:

package com.micro.Uncertain;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TabWidget;
import java.util.ArrayList;

public class FragmentTabHost extends TabHost implements TabHost.OnTabChangeListener {    
    private final ArrayList<TabInfo> mTabs = new ArrayList<>(); //Tab集合
    private FrameLayout mRealTabContent;
    private Context mContext;  
    private FragmentManager mFragmentManager; 
    private int mContainerId;
    private OnTabChangeListener mOnTabChangeListener;
    private TabInfo mLastTab;
    private boolean mAttached;

  /***  TabInfo結(jié)構(gòu)體  ***/
  static final class TabInfo {        
       private final String tag;
       private final Class<?> clss;
       private final Bundle args; 
       private Fragment fragment;
      TabInfo(String _tag, Class<?> _class, Bundle _args) { 
           tag = _tag; 
           clss = _class;
           args = _args;
        } 
   }  

  //可在createTabContent設(shè)置創(chuàng)建Tab內(nèi)容區(qū)域View的相關(guān)屬性
  static class DummyTabFactory implements TabContentFactory { 
       private final Context mContext;
       public DummyTabFactory(Context context) {
            mContext = context;   
     }       

   @Override        
   public View createTabContent(String tag) { 
           View v = new View(mContext);
            v.setMinimumWidth(0); 
           v.setMinimumHeight(0); 
           return v; 
       }   
 }   

  //保存View相關(guān)的State
 static class SavedState extends BaseSavedState { 
       String curTab; 
       SavedState(Parcelable superState) { 
           super(superState);
        }  

      private SavedState(Parcel in) {  
          super(in); 
           curTab = in.readString();
        }    

    @Override       
   public void writeToParcel(Parcel out, int flags) { 
           super.writeToParcel(out, flags);
            out.writeString(curTab);  
      }   

     @Override      
  public String toString() {  
          return "FragmentTabHost.SavedState{"+ Integer.toHexString(System.identityHashCode(this))  
         + " curTab=" + curTab + "}";  
      }      

  public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {  
          public SavedState createFromParcel(Parcel in) {  
              return new SavedState(in); 
           }   
         public SavedState[] newArray(int size) {  
              return new SavedState[size]; 
           }   
     };   
 } 

 //構(gòu)造方法
   public FragmentTabHost(Context context) { 
       super(context, null);  
      initFragmentTabHost(context, null);
    }   

   public FragmentTabHost(Context context, AttributeSet attrs) { 
       super(context, attrs);  
      initFragmentTabHost(context, attrs); 
   }  

   //初始化Fragment  TabHost 并設(shè)置TabChangeListener
    private void initFragmentTabHost(Context context, AttributeSet attrs) {  
      TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.inflatedId}, 0, 0); 
      mContainerId = a.getResourceId(0, 0); 
       a.recycle(); 
       super.setOnTabChangedListener(this); 
   }   

 private void ensureHierarchy(Context context) { 
       if (findViewById(android.R.id.tabs) == null) {  
          LinearLayout ll = new LinearLayout(context);
          ll.setOrientation(LinearLayout.VERTICAL); 
          addView(ll, new LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)); 

          TabWidget tw = new TabWidget(context); 
           tw.setId(android.R.id.tabs);   
          tw.setOrientation(TabWidget.HORIZONTAL);  
          ll.addView(tw, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT, 0));      

          FrameLayout fl = new FrameLayout(context);  
          fl.setId(android.R.id.tabcontent);   
          ll.addView(fl, new LinearLayout.LayoutParams(0, 0, 0));  
          mRealTabContent = fl = new FrameLayout(context); 
          mRealTabContent.setId(mContainerId); 
          ll.addView(fl, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1)); 
       }
    } 

   @Override  
   @Deprecated
    public void setup() {   
     throw new IllegalStateException( "Must call setup() that takes a Context and FragmentManager");  
  }   

 public void setup(Context context, FragmentManager manager) {   
       ensureHierarchy(context); 
       super.setup();  
       mContext = context; 
       mFragmentManager = manager; 
       ensureContent();  
  }    

public void setup(Context context, FragmentManager manager, int containerId) { 
       ensureHierarchy(context);  
       super.setup();   
       mContext = context;   
       mFragmentManager = manager; 
       mContainerId = containerId; 
       ensureContent();    
      mRealTabContent.setId(containerId);  
      if (getId() == View.NO_ID) {  
          setId(android.R.id.tabhost); 
       }   
 }   

 private void ensureContent() {  
      if (mRealTabContent == null) { 
           mRealTabContent = (FrameLayout) findViewById(mContainerId);  
          if (mRealTabContent == null) {
                throw new IllegalStateException( "No tab content FrameLayout found for id "+ mContainerId);     
       }  
      }  
  }

    @Override    
public void setOnTabChangedListener(OnTabChangeListener l) {  
      mOnTabChangeListener = l;  
  }    

//添加Tab
public void addTab(TabSpec tabSpec, Class<?> clss, Bundle args) {
        tabSpec.setContent(new DummyTabFactory(mContext));   
     String tag = tabSpec.getTag();   
     TabInfo info = new TabInfo(tag, clss, args); 
       if (mAttached) { 
           info.fragment = mFragmentManager.findFragmentByTag(tag);  
          if (info.fragment != null && !info.fragment.isDetached()) {   
             FragmentTransaction ft = mFragmentManager.beginTransaction();
                ft.hide(info.fragment);    
            ft.commit();       
     } 
       } 
       mTabs.add(info); 
       addTab(tabSpec);  
  }   

 @Override  
  protected void onAttachedToWindow() {
        super.onAttachedToWindow(); 
       String currentTab = getCurrentTabTag(); 
       FragmentTransaction ft = null; 
       for (int i = 0; i < mTabs.size(); i++) {
            TabInfo tab = mTabs.get(i); 
             tab.fragment = mFragmentManager.findFragmentByTag(tab.tag);  
                if (tab.fragment != null) {    
                   if (tab.tag.equals(currentTab)) {    
                    mLastTab = tab;      
               } else {       
                   if (ft == null) { 
                       ft = mFragmentManager.beginTransaction();    
                }        
               ft.hide(tab.fragment); 
               }          
       }   
     }   
       mAttached = true;  
       ft = doTabChanged(currentTab, ft);
       if (ft != null) {        
          ft.commitAllowingStateLoss();   
          mFragmentManager.executePendingTransactions();  
      } 
   }    

   @Override    
   protected void onDetachedFromWindow() {   
     super.onDetachedFromWindow(); 
       mAttached = false;
    }   

 @Override  
  protected Parcelable onSaveInstanceState() { 
       Parcelable superState = super.onSaveInstanceState();  
      SavedState ss = new SavedState(superState);  
      ss.curTab = getCurrentTabTag();  
      return ss;
    }   

  @Override    
  protected void onRestoreInstanceState(Parcelable state) { 
       SavedState ss = (SavedState) state; 
       super.onRestoreInstanceState(ss.getSuperState());
        setCurrentTabByTag(ss.curTab); 
   }   

  @Override    
  public void onTabChanged(String tabId) {   
     if (mAttached) {    
        FragmentTransaction ft = doTabChanged(tabId, null); 
           if (ft != null) {  
              ft.commit();   
         }     
   }    
    if (mOnTabChangeListener != null) {  
          mOnTabChangeListener.onTabChanged(tabId);   
     }    
}  

 //Tab變化
  private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) {  
      TabInfo newTab = null;   
      for (int i = 0; i < mTabs.size(); i++) {   
         TabInfo tab = mTabs.get(i);  
          if (tab.tag.equals(tabId)) {   
             newTab = tab;   
         }    
    }    
    if (newTab == null) {    
          throw new IllegalStateException("No tab known for tag " + tabId);  
       }     
   if (mLastTab != newTab) {     
       if (ft == null) {      
            ft = mFragmentManager.beginTransaction();  
          }      
      if (mLastTab != null) {    
            if (mLastTab.fragment != null) {    
                 ft.hide(mLastTab.fragment);   
             }         
      }          
  if (newTab != null) {  
              if (newTab.fragment == null) {    
                 newTab.fragment = Fragment.instantiate(mContext, newTab.clss.getName(), newTab.args); 
                 ft.add(mContainerId, newTab.fragment, newTab.tag);  
              } else {    
                ft.show(newTab.fragment);  
              }       
     }           
        mLastTab = newTab;  
      }    
    return ft;  
  }
}

相信從上面的代碼也可以大致了解了FragmentTabHost池充。由于Fragment的出現(xiàn)躯保,TabHost的過(guò)時(shí),它相當(dāng)于替換了TabHost贩猎,它會(huì)對(duì)所添加的fragment進(jìn)行管理熊户,保存棧信息和恢復(fù)棧信息等一切操作,比如我的fragment內(nèi)部有三個(gè)子fragment吭服,我退出該fragment的時(shí)候開(kāi)啟的是第二個(gè)子fragment嚷堡,下次我再進(jìn)入該fragment的時(shí)候依然會(huì)開(kāi)啟第二個(gè)子fragment,且看 FragmentTabHost源碼中對(duì)保存艇棕,相信已經(jīng)留意到了上面代碼中的onRestoreInstanceState()函數(shù)和onSaveInstanceState()函數(shù)蝌戒。閑話少說(shuō)我們繼續(xù)來(lái)看我們主頁(yè)面MainActivity中的實(shí)現(xiàn):

package com.micro.Uncertain;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TextView;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
    private static final int MAX_BOTTOM = 5; 
    private FragmentTabHost tabhost;
    private List<FuncEntity> funcEntities;//底部菜單
    private String menuStr="{\"funcList\":[{\"name\":\"報(bào)表\",\"code\":\"dky_2\"},{\"name\":\"商城\",\"code\":\"dky_3\"},{\"name\":\"分銷(xiāo)\",\"code\":\"dky_5\"},{\"name\":\"任務(wù)\",\"code\":\"dky_4\"}]}"; 

   @Override   
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main); 
        tabhost = (FragmentTabHost) findViewById(android.R.id.tabhost);
        tabhost.setup(this, getSupportFragmentManager(), R.id.fl_content); 
        UserLoginEntity entity = new Gson().fromJson(menuStr, UserLoginEntity.class); 
        if (entity!=null)  
          {       
            funcEntities=entity.funcList;    
        }    
         initBottomTab(); 
    }   

  /**     * 初始化底部菜單     */   
      private void initBottomTab() { 
       List<TabEntity> entities = new ArrayList<>(); 
       TabEntity tabEntity = null; 
       for (int i = 0; i < funcEntities.size(); i++) {  
          if (i >= MAX_BOTTOM) {
                break; 
        }  
        FuncEntity entity = funcEntities.get(i);  
          switch (entity.code) { 
               case Constants.DKY_1: 
                   tabEntity = new TabEntity(StoreFragment.class, R.drawable.bottom_sotre_selector, getString(R.string.store));
                    break;
                case Constants.DKY_2:
                    tabEntity = new TabEntity(ReportFragement.class, R.drawable.bottom_report_selector, getString(R.string.report_form)); 
                   break; 
               case Constants.DKY_3:  
                  tabEntity = new TabEntity(MallFragment.class, R.drawable.bottom_mall_selector, getString(R.string.mall));   
                 break;       
                case Constants.DKY_4:
                    tabEntity = new TabEntity(TaskFragment.class, R.drawable.bottom_task_selector, getString(R.string.task)); 
                   break;   
                 case Constants.DKY_5:   
                 tabEntity = new TabEntity(DistributionFragment.class, R.drawable.bottom_distirbution_selector, getString(R.string.distribution)); 
                   break;              
                  case Constants.DKY_6:  
                  tabEntity = new TabEntity(PurchaseFragment.class, R.drawable.bottom_purchase_selector, getString(R.string.purchase));  
                  break; 
           }     
         entities.add(tabEntity);
        }      
 
   for (TabEntity entity : entities) { 
           TabHost.TabSpec tabSpec = tabhost.newTabSpec(entity.getBottomContent()); 
           tabSpec.setIndicator(initIndicator(entity));
            tabhost.addTab(tabSpec, entity.getFragment(), null);
        }        
       tabhost.getTabWidget().setShowDividers(LinearLayout.SHOW_DIVIDER_NONE); 
       setCurrentIndex("0"); 
   } 
 
  /**     
  * 選擇index    
  *    
  * @param index
  */

    private void setCurrentIndex(String index) { 
       for (int i = 0, size = funcEntities.size() > MAX_BOTTOM ? MAX_BOTTOM : funcEntities.size(); i < size; i++) {     
       if (funcEntities.get(i).code.equals(index)) {
                tabhost.setCurrentTab(i);
                break;    
           }
        } 
   } 

   /**
     * 初始化底部bottom    
     * 
     * @param entity 
     * @return 
    */  
  private View initIndicator(TabEntity entity) {  
      View view = getLayoutInflater().inflate(R.layout.tab_view, null);
        ImageView tab_image = (ImageView) view.findViewById(R.id.tab_image);  
       TextView tab_text = (TextView) view.findViewById(R.id.tab_text);  
       tab_image.setBackgroundResource(entity.getIcon()); 
        tab_text.setText(entity.getBottomContent());  
       return view; 
   }
}

以上就是主頁(yè)中的代碼,可以根據(jù)得到的menuStr來(lái)解析判斷當(dāng)前的菜單的數(shù)量沼琉,當(dāng)然也要對(duì)其底部菜單的數(shù)量進(jìn)行一個(gè)限制北苟,因?yàn)閿?shù)量太大之后,初始化的個(gè)數(shù)相對(duì)來(lái)說(shuō)也就越多打瘪,在其底部顯示比較緊密友鼻。
實(shí)現(xiàn)底部菜單數(shù)量隨意配置,當(dāng)然不止這一種方法瑟慈,比如自定義底部菜單為自定義Linearlayout,通過(guò)菜單數(shù)量addView()方法實(shí)現(xiàn)桃移,再給View添加點(diǎn)擊事件屋匕,通過(guò)View的index和Fragment綁定葛碧,F(xiàn)ragment使用add或者replace實(shí)現(xiàn):
源代碼:https://pan.baidu.com/s/1kVGXz6Z
周五了,回家过吻!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末进泼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纤虽,更是在濱河造成了極大的恐慌乳绕,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逼纸,死亡現(xiàn)場(chǎng)離奇詭異洋措,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)杰刽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)菠发,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)王滤,“玉大人,你說(shuō)我怎么就攤上這事滓鸠⊙阆纾” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵糜俗,是天一觀的道長(zhǎng)踱稍。 經(jīng)常有香客問(wèn)我,道長(zhǎng)悠抹,這世上最難降的妖魔是什么珠月? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮楔敌,結(jié)果婚禮上桥温,老公的妹妹穿的比我還像新娘。我一直安慰自己梁丘,他們只是感情好侵浸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著氛谜,像睡著了一般掏觉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上值漫,一...
    開(kāi)封第一講書(shū)人閱讀 51,698評(píng)論 1 305
  • 那天澳腹,我揣著相機(jī)與錄音,去河邊找鬼杨何。 笑死酱塔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的危虱。 我是一名探鬼主播羊娃,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼埃跷!你這毒婦竟也來(lái)了蕊玷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤弥雹,失蹤者是張志新(化名)和其女友劉穎垃帅,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體剪勿,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贸诚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酱固。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡二鳄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出媒怯,到底是詐尸還是另有隱情订讼,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布扇苞,位于F島的核電站欺殿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鳖敷。R本人自食惡果不足惜脖苏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望定踱。 院中可真熱鬧棍潘,春花似錦、人聲如沸崖媚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)畅哑。三九已至肴楷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荠呐,已是汗流浹背赛蔫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留泥张,地道東北人呵恢。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像媚创,于是被迫代替她去往敵國(guó)和親渗钉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,171評(píng)論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,766評(píng)論 22 665
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)筝野、插件晌姚、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,106評(píng)論 4 62
  • 關(guān)于目前最新的NBA交易傳聞焕议,這其中就有涉及到猛龍,這支潛力東決強(qiáng)隊(duì)被普遍認(rèn)為需要補(bǔ)強(qiáng)一名內(nèi)線悍將弧关。據(jù)外媒報(bào)道盅安,目...
    zoneball閱讀 258評(píng)論 1 0
  • 女人天生就在情感方面比男人更敏感唤锉,思考的比男人更多,經(jīng)常會(huì)產(chǎn)生這樣的想法:也不知道這些男人在想什么别瞭!渡邊淳一先生的...
    呂賀薇薇閱讀 42,794評(píng)論 0 5