FragmentTabHost+Fragment随意配置菜单数量

在工作中,我们或许会遇到不同角色登录时候,因为不同的角色,所以也就有不同的权限,那么他所看到的角色菜单也就完全不一样,效果如下:

FragmentTabHost+Fragment随意配置菜单数量_第1张图片
![QQ截图20160708180418.png](http://upload-images.jianshu.io/upload_images/2310529-dc88de673cd788d3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

不多说,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 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结构体  ***/
  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设置创建Tab内容区域View的相关属性
  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相关的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 CREATOR = new Creator() {  
          public SavedState createFromParcel(Parcel in) {  
              return new SavedState(in); 
           }   
         public SavedState[] newArray(int size) {  
              return new SavedState[size]; 
           }   
     };   
 } 

 //构造方法
   public FragmentTabHost(Context context) { 
       super(context, null);  
      initFragmentTabHost(context, null);
    }   

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

   //初始化Fragment  TabHost 并设置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的出现,TabHost的过时,它相当于替换了TabHost,它会对所添加的fragment进行管理,保存栈信息和恢复栈信息等一切操作,比如我的fragment内部有三个子fragment,我退出该fragment的时候开启的是第二个子fragment,下次我再进入该fragment的时候依然会开启第二个子fragment,且看 FragmentTabHost源码中对保存,相信已经留意到了上面代码中的onRestoreInstanceState()函数和onSaveInstanceState()函数。闲话少说我们继续来看我们主页面MainActivity中的实现:

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 funcEntities;//底部菜单
    private String menuStr="{\"funcList\":[{\"name\":\"报表\",\"code\":\"dky_2\"},{\"name\":\"商城\",\"code\":\"dky_3\"},{\"name\":\"分销\",\"code\":\"dky_5\"},{\"name\":\"任务\",\"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 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; 
   }
}

以上就是主页中的代码,可以根据得到的menuStr来解析判断当前的菜单的数量,当然也要对其底部菜单的数量进行一个限制,因为数量太大之后,初始化的个数相对来说也就越多,在其底部显示比较紧密。
实现底部菜单数量随意配置,当然不止这一种方法,比如自定义底部菜单为自定义Linearlayout,通过菜单数量addView()方法实现,再给View添加点击事件,通过View的index和Fragment绑定,Fragment使用add或者replace实现:
源代码:https://pan.baidu.com/s/1kVGXz6Z
周五了,回家!

你可能感兴趣的:(FragmentTabHost+Fragment随意配置菜单数量)