前言@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实现底部菜单功能所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)