Android 使用FragmentTabHost实现底部菜单功能

Android 使用FragmentTabHost实现底部菜单功能,第1张

概述前言现在大部分App底部都有一个菜单,实现这个功能也有好多办法:-TabHost+Fragment

前言@H_419_5@

现在大部分App底部都有一个菜单,实现这个功能也有好多办法:@H_419_5@

- TabHost+Fragment
- RadioGroup+Fragment
- FragmentTabHost+Fragment
- 5.0以后有个新控件,BottomNavigator@H_419_5@

这篇主要介绍下FragmentTabHost配合Fragment使用@H_419_5@

运行效果图@H_419_5@

@H_419_5@@H_419_5@

效果图分析@H_419_5@

@H_419_5@@H_419_5@

FragmentTabHost简单介绍@H_419_5@

首先我们看下官方文档的介绍@H_419_5@

@H_419_5@@H_419_5@

OK,接着官方还给出了一份使用的代码,我们也来看下@H_419_5@

Activity中使用@H_419_5@

import com.example.androID.supportv4.R;import androID.os.Bundle;import androID.support.v4.app.FragmentActivity;import androID.support.v4.app.FragmentTabHost;/** * This demonstrates how you can implement switching between the tabs of a * TabHost through fragments,using FragmentTabHost. */public class FragmentTabs extends FragmentActivity { private FragmentTabHost mTabHost; @OverrIDe protected voID onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentVIEw(R.layout.fragment_tabs);  mTabHost = (FragmentTabHost)findVIEwByID(androID.R.ID.tabhost);  mTabHost.setup(this,getSupportFragmentManager(),R.ID.realtabcontent);  mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),FragmentStackSupport.CountingFragment.class,null);  mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"),LoaderCursorSupport.CursorLoaderListFragment.class,null);  mTabHost.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"),LoaderCustomSupport.AppListFragment.class,null);  mTabHost.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"),LoaderThrottleSupport.ThrottledLoaderListFragment.class,null); }}

Fragment中使用@H_419_5@

import com.example.androID.supportv4.R;import androID.os.Bundle;import androID.support.v4.app.Fragment;import androID.support.v4.app.FragmentTabHost;import androID.vIEw.LayoutInflater;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;public class FragmentTabsFragmentSupport extends Fragment { private FragmentTabHost mTabHost; @OverrIDe public VIEw onCreateVIEw(LayoutInflater inflater,VIEwGroup container,Bundle savedInstanceState) {  mTabHost = new FragmentTabHost(getActivity());  mTabHost.setup(getActivity(),getChildFragmentManager(),R.ID.fragment1);  mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),null);  return mTabHost; } @OverrIDe public voID onDestroyVIEw() {  super.onDestroyVIEw();  mTabHost = null; }}

FragmentTabHost 布局问题@H_419_5@

官方在给出例子的时候,并没有贴出对应的布局文件,这个布局文件有一些要求,所以我就把我自己写的贴出来吧,方便大家观看@H_419_5@

<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:app="http://schemas.androID.com/apk/res-auto" xmlns:tools="http://schemas.androID.com/tools" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:orIEntation="vertical" tools:context="com.study.buttomtabdemo.MainActivity"> <FrameLayout  androID:ID="@+ID/flayout_content"  androID:layout_wIDth="match_parent"  androID:layout_height="0dp"  androID:layout_weight="1"/> <com.study.buttomtabdemo.Widget.FragmentTabHost  androID:ID="@androID:ID/tabhost"  androID:layout_wIDth="match_parent"  androID:layout_height="wrap_content"  androID:background="#ffffff">  <FrameLayout   androID:ID="@androID:ID/tabcontent"   androID:layout_wIDth="0dp"   androID:layout_height="0dp"   androID:layout_weight="0"/> </com.study.buttomtabdemo.Widget.FragmentTabHost></linearLayout>

这里要注意以下几点:@H_419_5@

1.我自己自定义了一个FragmentTabHost,因为原来的FragmentTabHost每次切换Fragment事都会走一遍onCreateVIEw()和onResume()方法;@H_419_5@

2.ID必须是androID:ID=”@androID:ID/tabhost”这个;@H_419_5@

3.里面的FrameLayout的ID必须是androID:ID=”@androID:ID/tabcontent”@H_419_5@

FragmentTabHost 使用@H_419_5@

下面就到了具体使用的过程了@H_419_5@

1.定义Tab类@H_419_5@

因为它属于Tab的一个组合吧,里面包含好多个Tab,所以我们先定义一个Tab类@H_419_5@

/** * 主页TAB对应实体 * Created by HFS on 2017/5/7. */public class Tab { private int Title; // 文字 private int icon; // 图标 private Class fragment; // 对应fragment public Tab(Class fragment,int Title,int icon ) {  this.Title = Title;  this.icon = icon;  this.fragment = fragment; } public int getTitle() {  return Title; } public voID setTitle(int Title) {  this.Title = Title; } public int getIcon() {  return icon; } public voID setIcon(int icon) {  this.icon = icon; } public Class getFragment() {  return fragment; } public voID setFragment(Class fragment) {  this.fragment = fragment; }}

这里面要对应相应的Fragment,所以需要一个Fragment对象@H_419_5@

2.初始化Tab集合@H_419_5@

有几个Tab就往Tab集合添加几个Tab   @H_419_5@

 Tab tab_home = new Tab(HomeFragment.class,R.string.home,R.drawable.selector_icon_home);  Tab tab_hot = new Tab(HotFragment.class,R.string.hot,R.drawable.selector_icon_hot);  Tab tab_category = new   Tab(categoryFragment.class,R.string.catagory,R.drawable.selector_icon_category);  Tab tab_cart = new Tab(CartFragment.class,R.string.cart,R.drawable.selector_icon_cart);  Tab tab_mine = new Tab(mineFragment.class,R.string.mine,R.drawable.selector_icon_mine);  mTabs.add(tab_home);  mTabs.add(tab_hot);  mTabs.add(tab_category);  mTabs.add(tab_cart);  mTabs.add(tab_mine);

3.setUp@H_419_5@

找到该控件之后,就要调用对应的这个方法@H_419_5@

 mInflater = LayoutInflater.from(this);  mTabhost = (FragmentTabHost) this.findVIEwByID(androID.R.ID.tabhost);  mTabhost.setup(this,R.ID.flayout_content);

4.添加TabSpec@H_419_5@

到这一步就要添加TabSpec了,有几个Tab,就添加几个TabSpec        @H_419_5@

 for (Tab tab : mTabs){   TabHost.TabSpec tabSpec = mTabhost.newTabSpec(getString(tab.getTitle()));   tabSpec.setIndicator(buildindicator(tab));   mTabhost.addTab(tabSpec,tab.getFragment(),null);  }  //构建Indicator  private VIEw buildindicator(Tab tab){   VIEw vIEw =mInflater.inflate(R.layout.tab_indicator,null);   ImageVIEw img = (ImageVIEw) vIEw.findVIEwByID(R.ID.icon_tab);   TextVIEw text = (TextVIEw) vIEw.findVIEwByID(R.ID.txt_indicator);   img.setBackgroundResource(tab.getIcon());   text.setText(tab.getTitle());  return vIEw; }

5.设置默认显示第一个@H_419_5@

mTabhost.setCurrentTab(0);

6.设置没有分割线@H_419_5@

mTabhost.getTabWidget().setShowdivIDers(linearLayout.SHOW_divIDER_NONE);

自定义FragmentTabHost类@H_419_5@

package com.study.buttomtabdemo.Widget;/** * Created by monkey * on 2014/9/24 * 功能描述:修改过的FragmentTabHost,保存fragment实例不销毁 *//* * copyright (C) 2012 The AndroID Open Source Project * * licensed under the Apache license,Version 2.0 (the "license"); * you may not use this file except in compliance with the license. * You may obtain a copy of the license at * *  http://www.apache.org/licenses/liCENSE-2.0 * * Unless required by applicable law or agreed to in writing,software * distributed under the license is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implIEd. * See the license for the specific language governing permissions and * limitations under the license. */  import java.util.ArrayList;  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;/** * Special TabHost that allows the use of {@link Fragment} objects for its tab * content. When placing this in a vIEw hIErarchy,after inflating the hIErarchy * you must call {@link #setup(Context,FragmentManager,int)} to complete the * initialization of the tab host. * * <p> * Here is a simple example of using a FragmentTabHost in an Activity: * * {@sample * development/samples/Support4Demos/src/com/example/androID/supportv4/app/ * FragmentTabs.java complete} * * <p> * This can also be used insIDe of a fragment through fragment nesting: * * {@sample * development/samples/Support4Demos/src/com/example/androID/supportv4/app/ * FragmentTabsFragmentSupport.java complete} */public class FragmentTabHost extends TabHost implements  TabHost.OnTabchangelistener { private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); private FrameLayout mRealTabContent; private Context mContext; private FragmentManager mFragmentManager; private int mContainerID; private OnTabchangelistener mOnTabchangelistener; private TabInfo mLastTab; private boolean mAttached; 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;  } } 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;  } } 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];   }  }; } public FragmentTabHost(Context context) {  // Note that we call through to the version that takes an AttributeSet,// because the simple Context construct can result in a broken object!  super(context,null);  initFragmentTabHost(context,null); } public FragmentTabHost(Context context,AttributeSet attrs) {  super(context,attrs);  initFragmentTabHost(context,attrs); } private voID initFragmentTabHost(Context context,AttributeSet attrs) {  TypedArray a = context.obtainStyledAttributes(attrs,new int[] { androID.R.attr.inflatedID },0);  mContainerID = a.getResourceID(0,0);  a.recycle();  super.setonTabChangedListener(this); } private voID ensureHIErarchy(Context context) {  // If owner hasn't made its own vIEw hIErarchy,then as a convenIEnce  // we will construct a standard one here.  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));   mRealTabContent = fl = new FrameLayout(context);   mRealTabContent.setID(mContainerID);   ll.addVIEw(fl,new linearLayout.LayoutParams(     linearLayout.LayoutParams.MATCH_PARENT,1));  } } /**  * @deprecated Don't call the original TabHost setup,you must instead call  *    {@link #setup(Context,FragmentManager)} or  *    {@link #setup(Context,int)}.  */ @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); // Ensure vIEws required by super.setup()  super.setup();  mContext = context;  mFragmentManager = manager;  ensureContent(); } public voID setup(Context context,FragmentManager manager,int containerID) {  ensureHIErarchy(context); // Ensure vIEws required by super.setup()  super.setup();  mContext = context;  mFragmentManager = manager;  mContainerID = containerID;  ensureContent();  mRealTabContent.setID(containerID);  // We must have an ID to be able to save/restore our state. If  // the owner hasn't set one at this point,we will set it ourself.  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; } 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) {   // If we are already attached to the window,then check to make   // sure this tab's fragment is inactive if it exists. This shouldn't   // normally happen.   info.fragment = mFragmentManager.findFragmentByTag(tag);   if (info.fragment != null && !info.fragment.isDetached()) {    FragmentTransaction ft = mFragmentManager.beginTransaction();//    ft.detach(info.fragment);    ft.hIDe(info.fragment);    ft.commit();   }  }  mTabs.add(info);  addTab(tabSpec); } @OverrIDe protected voID onAttachedToWindow() {  super.onAttachedToWindow();  String currentTab = getCurrentTabTag();  // Go through all tabs and make sure their fragments match  // the correct state.  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 && !tab.fragment.isDetached()) {   if (tab.fragment != null) {    if (tab.tag.equals(currentTab)) {     // The fragment for this tab is already there and     // active,and it is what we really want to have     // as the current tab. nothing to do.     mLastTab = tab;    } else {     // This fragment was restored in the active state,// but is not the current tab. Deactivate it.     if (ft == null) {      ft = mFragmentManager.beginTransaction();     }//     ft.detach(tab.fragment);     ft.hIDe(tab.fragment);    }   }  }  // We are Now ready to go. Make sure we are switched to the  // correct tab.  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);  } } 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.detach(mLastTab.fragment);     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.attach(newTab.fragment);     ft.show(newTab.fragment);    }   }   mLastTab = newTab;  }  return ft; }}

总结@H_419_5@

以上所述是小编给大家介绍的AndroID 使用FragmentTabHost实现底部菜单功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!@H_419_5@ 总结

以上是内存溢出为你收集整理的Android 使用FragmentTabHost实现底部菜单功能全部内容,希望文章能够帮你解决Android 使用FragmentTabHost实现底部菜单功能所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1143199.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存