FragmentTabHostUnderLineDemo【FragmentTabHost带下划线】
版權(quán)聲明:本文為HaiyuKing原創(chuàng)文章,轉(zhuǎn)載請注明出處!
前言
使用FragmentTabHost實現(xiàn)頂部選項卡(帶下劃線效果)展現(xiàn)。
效果圖
代碼分析
1、該Demo中采用的是FragmentTabHost的布局方案之一【命名為常規(guī)布局寫法】;
2、使用自定義的FragmentTabHost;
3、切換回來后,可以保持打開的網(wǎng)頁,而不是顯示首頁。【因為切換時執(zhí)行的是show/hide,而不是attach/detach】
使用步驟
一、項目組織結(jié)構(gòu)圖
注意事項:
1、? 導(dǎo)入類文件后需要change包名以及重新import R文件路徑
2、? Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),如果項目中存在,則復(fù)制里面的內(nèi)容,不要整個覆蓋
二、導(dǎo)入步驟
將自定義的MyFragmentTabHost復(fù)制到項目中
package com.why.project.fragmenttabhostunderlinedemo.views.tab;import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; 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;/*** Created by HaiyuKing* Used 仿照FragmentTabHost并更改doTabChanged方法實現(xiàn)切換Fragment的時候不刷新fragment*/public class MyFragmentTabHost extends TabHostimplements TabHost.OnTabChangeListener {private final ArrayList<MyFragmentTabHost.TabInfo> mTabs = new ArrayList<>();private FrameLayout mRealTabContent;private Context mContext;private FragmentManager mFragmentManager;private int mContainerId;private TabHost.OnTabChangeListener mOnTabChangeListener;private MyFragmentTabHost.TabInfo mLastTab;private boolean mAttached;static final class TabInfo {final@NonNullString tag;final@NonNullClass<?> clss;final@NullableBundle args;Fragment fragment;TabInfo(@NonNull String _tag, @NonNull Class<?> _class, @Nullable Bundle _args) {tag = _tag;clss = _class;args = _args;}}static class DummyTabFactory implements TabHost.TabContentFactory {private final Context mContext;public DummyTabFactory(Context context) {mContext = context;}@Overridepublic 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);}SavedState(Parcel in) {super(in);curTab = in.readString();}@Overridepublic void writeToParcel(Parcel out, int flags) {super.writeToParcel(out, flags);out.writeString(curTab);}@Overridepublic String toString() {return "MyFragmentTabHost.SavedState{"+ Integer.toHexString(System.identityHashCode(this))+ " curTab=" + curTab + "}";}public static final Parcelable.Creator<MyFragmentTabHost.SavedState> CREATOR= new Parcelable.Creator<MyFragmentTabHost.SavedState>() {@Overridepublic MyFragmentTabHost.SavedState createFromParcel(Parcel in) {return new MyFragmentTabHost.SavedState(in);}@Overridepublic MyFragmentTabHost.SavedState[] newArray(int size) {return new MyFragmentTabHost.SavedState[size];}};}public MyFragmentTabHost(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 MyFragmentTabHost(Context context, AttributeSet attrs) {super(context, attrs);initFragmentTabHost(context, attrs);}private void initFragmentTabHost(Context context, AttributeSet attrs) {final 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 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 FrameLayout.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));}}/*** @deprecated Don't call the original TabHost setup, you must instead* call {@link #setup(Context, FragmentManager)} or* {@link #setup(Context, FragmentManager, int)}.*/@Override@Deprecatedpublic 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 ourselves.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);}}}@Overridepublic void setOnTabChangedListener(OnTabChangeListener l) {mOnTabChangeListener = l;}public void addTab(@NonNull TabHost.TabSpec tabSpec, @NonNull Class<?> clss,@Nullable Bundle args) {tabSpec.setContent(new MyFragmentTabHost.DummyTabFactory(mContext));final String tag = tabSpec.getTag();final MyFragmentTabHost.TabInfo info = new MyFragmentTabHost.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()) {final FragmentTransaction ft = mFragmentManager.beginTransaction();ft.detach(info.fragment);ft.commit();}}mTabs.add(info);addTab(tabSpec);}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();final String currentTag = getCurrentTabTag();// Go through all tabs and make sure their fragments match// the correct state.FragmentTransaction ft = null;for (int i = 0, count = mTabs.size(); i < count; i++) {final MyFragmentTabHost.TabInfo tab = mTabs.get(i);tab.fragment = mFragmentManager.findFragmentByTag(tab.tag);if (tab.fragment != null && !tab.fragment.isDetached()) {if (tab.tag.equals(currentTag)) {// 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);}}}// We are now ready to go. Make sure we are switched to the// correct tab.mAttached = true;ft = doTabChanged(currentTag, ft);if (ft != null) {ft.commit();mFragmentManager.executePendingTransactions();}}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();mAttached = false;}@Overrideprotected Parcelable onSaveInstanceState() {Parcelable superState = super.onSaveInstanceState();MyFragmentTabHost.SavedState ss = new MyFragmentTabHost.SavedState(superState);ss.curTab = getCurrentTabTag();return ss;}@Overrideprotected void onRestoreInstanceState(Parcelable state) {if (!(state instanceof MyFragmentTabHost.SavedState)) {super.onRestoreInstanceState(state);return;}MyFragmentTabHost.SavedState ss = (MyFragmentTabHost.SavedState) state;super.onRestoreInstanceState(ss.getSuperState());setCurrentTabByTag(ss.curTab);}@Overridepublic void onTabChanged(String tabId) {if (mAttached) {final FragmentTransaction ft = doTabChanged(tabId, null);if (ft != null) {ft.commit();}}if (mOnTabChangeListener != null) {mOnTabChangeListener.onTabChanged(tabId);}}@Nullableprivate FragmentTransaction doTabChanged(@Nullable String tag,@Nullable FragmentTransaction ft) {final MyFragmentTabHost.TabInfo newTab = getTabInfoForTag(tag);if (mLastTab != newTab) {if (ft == null) {ft = mFragmentManager.beginTransaction();}if (mLastTab != null) {if (mLastTab.fragment != null) { // ft.detach(mLastTab.fragment);ft.hide(mLastTab.fragment);//http://blog.csdn.net/w1054993544/article/details/37658183 }}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);//http://blog.csdn.net/w1054993544/article/details/37658183 }}mLastTab = newTab;}return ft;}@Nullableprivate MyFragmentTabHost.TabInfo getTabInfoForTag(String tabId) {for (int i = 0, count = mTabs.size(); i < count; i++) {final MyFragmentTabHost.TabInfo tab = mTabs.get(i);if (tab.tag.equals(tabId)) {return tab;}}return null;} } MyFragmentTabHost?代碼是復(fù)制的系統(tǒng)的FragmentTabHost,只有一小部分和系統(tǒng)不一樣的代碼:
將tab_top_underline_item.xml文件復(fù)制到項目中
<?xml version="1.0" encoding="utf-8"?> <!-- 帶有下劃線的頂部選項卡子項的布局文件(選擇圖片界面) --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/toptabLayout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:paddingTop="@dimen/tab_top_underline_padding"android:paddingLeft="@dimen/tab_top_underline_padding"android:paddingRight="@dimen/tab_top_underline_padding"><!-- 標(biāo)題 --><TextViewandroid:id="@+id/top_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text=""android:textSize="@dimen/tab_top_underline_title_size"android:textColor="@color/tab_text_normal_top"android:layout_alignParentTop="true"android:layout_centerHorizontal="true" /><!-- 下劃線--><!-- android:background="@color/tab_underline_selected_top" --><Viewandroid:id="@+id/top_underline"android:layout_width="match_parent"android:layout_height="@dimen/tab_top_underline_height"android:background="@color/tab_underline_normal_top"android:layout_below="@id/top_title"android:layout_centerHorizontal="true"android:layout_marginTop="@dimen/tab_top_underline_padding"/></RelativeLayout> tab_top_underline_item在colors.xml文件中添加以下代碼:【后續(xù)可根據(jù)實際情況更改背景顏色、文字顏色值】
<?xml version="1.0" encoding="utf-8"?> <resources><color name="colorPrimary">#3F51B5</color><color name="colorPrimaryDark">#303F9F</color><color name="colorAccent">#FF4081</color><!-- *********************************頂部選項卡區(qū)域********************************* --><!-- 頂部選項卡下劃線背景色 --><color name="tab_underline_normal_top">#00ffffff</color><color name="tab_underline_selected_top">#FF7700</color><!-- 頂部選項卡文本顏色 --><color name="tab_text_normal_top">#191919</color><color name="tab_text_selected_top">#FF7700</color></resources>在dimens.xml文件中添加以下代碼:【后續(xù)可根據(jù)實際情況更改底部選項卡區(qū)域的高度值、文字大小值】
<resources><!-- Default screen margins, per the Android Design guidelines. --><dimen name="activity_horizontal_margin">16dp</dimen><dimen name="activity_vertical_margin">16dp</dimen><!-- *********************************頂部選項卡區(qū)域********************************* --><!-- 選項卡的內(nèi)邊距 --><dimen name="tab_top_underline_padding">10dp</dimen><!-- 選項卡標(biāo)題的文字大小 --><dimen name="tab_top_underline_title_size">18sp</dimen><!-- 選項卡標(biāo)題的下劃線高度 --><dimen name="tab_top_underline_height">3dp</dimen></resources>至此,選項卡子項的布局所需的文件已集成到項目中了。
在AndroidManifest.xml文件中添加網(wǎng)絡(luò)請求的權(quán)限【demo中用到的】
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.why.project.fragmenttabhostunderlinedemo"><!-- ======================授權(quán)訪問網(wǎng)絡(luò)(HttpUtil)========================== --><!-- 允許程序打開網(wǎng)絡(luò)套接字 --><uses-permission android:name="android.permission.INTERNET"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity></application></manifest>三、使用方法
在Activity布局文件中引用MyFragmentTabHost【注意:TabWidget的android:layout_width="match_parent"】
<?xml version="1.0" encoding="utf-8"?> <!-- 頂部選項卡區(qū)域 --> <com.why.project.fragmenttabhostunderlinedemo.views.tab.MyFragmentTabHostxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/tab_top_underline_ftabhost_layout"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 必須要有LinearLayout,因為FragmentTabHost屬于FrameLayout幀布局 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!-- 選項卡區(qū)域 --><!--注意:原來的配置:android:layout_height="?attr/actionBarSize"--><TabWidgetandroid:id="@android:id/tabs"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="top|center_horizontal"/><!-- 分割線 --><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="#cfcfcf"></View><!-- 碎片切換區(qū)域,且其id必須為@android:id/tabcontent --><FrameLayoutandroid:id="@android:id/tabcontent"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/></LinearLayout></com.why.project.fragmenttabhostunderlinedemo.views.tab.MyFragmentTabHost>創(chuàng)建需要用到的fragment類和布局文件【后續(xù)可根據(jù)實際情況更改命名,并且需要重新import R文件】
??
fragment_web.xml文件布局如下
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><!-- webview --><WebViewandroid:id="@+id/web_view"android:layout_width="match_parent"android:layout_height="match_parent"></WebView></LinearLayout>WebViewFragment
package com.why.project.fragmenttabhostunderlinedemo.fragment;import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; import android.webkit.WebViewClient;import com.why.project.fragmenttabhostunderlinedemo.R;/*** @Created HaiyuKing* @Used 首頁界面——碎片界面*/ public class WebViewFragment extends BaseFragment{private static final String TAG = "WebViewFragment";/**View實例*/private View myView;private WebView web_view;/**傳遞過來的參數(shù)*/private String bundle_param;//重寫public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {//使用FragmentTabHost時,Fragment之間切換時每次都會調(diào)用onCreateView方法,導(dǎo)致每次Fragment的布局都重繪,無法保持Fragment原有狀態(tài)。//http://www.cnblogs.com/changkai244/p/4110173.htmlif(myView==null){myView = inflater.inflate(R.layout.fragment_web, container, false);//接收傳參Bundle bundle = this.getArguments();bundle_param = bundle.getString("param");}//緩存的rootView需要判斷是否已經(jīng)被加過parent, 如果有parent需要從parent刪除,要不然會發(fā)生這個rootview已經(jīng)有parent的錯誤。ViewGroup parent = (ViewGroup) myView.getParent();if (parent != null) {parent.removeView(myView);}return myView;}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onActivityCreated(savedInstanceState);//初始化控件以及設(shè)置 initView();//初始化數(shù)據(jù) initData();//初始化控件的點擊事件 initEvent();}@Overridepublic void onResume() {super.onResume();}@Overridepublic void onPause() {super.onPause();}@Overridepublic void onDestroy() {super.onDestroy();}/*** 初始化控件*/private void initView() {web_view = (WebView) myView.findViewById(R.id.web_view);//設(shè)置支持js腳本 // web_view.getSettings().setJavaScriptEnabled(true);web_view.setWebViewClient(new WebViewClient() {/*** 重寫此方法表明點擊網(wǎng)頁內(nèi)的鏈接由自己處理,而不是新開Android的系統(tǒng)browser中響應(yīng)該鏈接。*/@Overridepublic boolean shouldOverrideUrlLoading(WebView webView, String url) {//webView.loadUrl(url);return false;}});}/*** 初始化數(shù)據(jù)*/public void initData() {Log.e("tag","{initData}bundle_param="+bundle_param);web_view.loadUrl(bundle_param);//加載網(wǎng)頁 }/*** 初始化點擊事件* */private void initEvent(){}}在Activity中使用如下【繼承FragmentActivity或者其子類】
package com.why.project.fragmenttabhostunderlinedemo;import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.TabHost; import android.widget.TextView; import android.widget.Toast;import com.why.project.fragmenttabhostunderlinedemo.fragment.WebViewFragment; import com.why.project.fragmenttabhostunderlinedemo.views.tab.MyFragmentTabHost;import java.util.ArrayList;public class MainActivity extends AppCompatActivity {private MyFragmentTabHost mTopUnderlineFTabHostLayout;//選項卡子類集合private ArrayList<TabItem> tabItemList = new ArrayList<TabItem>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initTabList();initFTabHostLayout();setFTabHostData();initEvents();}/*** 初始化選項卡數(shù)據(jù)集合*/private void initTabList() {//底部選項卡對應(yīng)的Fragment類使用的是同一個Fragment,那么需要考慮切換Fragment時避免重復(fù)加載UI的問題】tabItemList.add(new TabItem(this,"百度",WebViewFragment.class));tabItemList.add(new TabItem(this,"博客園",WebViewFragment.class));tabItemList.add(new TabItem(this,"CSDN",WebViewFragment.class));}/*** 初始化FragmentTabHost*/private void initFTabHostLayout() {//實例化mTopUnderlineFTabHostLayout = (MyFragmentTabHost) findViewById(R.id.tab_top_underline_ftabhost_layout);mTopUnderlineFTabHostLayout.setup(this, getSupportFragmentManager(), android.R.id.tabcontent);//最后一個參數(shù)是碎片切換區(qū)域的ID值// 去掉分割線mTopUnderlineFTabHostLayout.getTabWidget().setDividerDrawable(null);}/*** 設(shè)置選項卡的內(nèi)容*/private void setFTabHostData() {//Tab存在于TabWidget內(nèi),而TabWidget是存在于TabHost內(nèi)。與此同時,在TabHost內(nèi)無需在寫一個TabWidget,系統(tǒng)已經(jīng)內(nèi)置了一個TabWidgetfor (int i = 0; i < tabItemList.size(); i++) {//實例化一個TabSpec,設(shè)置tab的名稱和視圖TabHost.TabSpec spec = mTopUnderlineFTabHostLayout.newTabSpec(tabItemList.get(i).getTabTitle()).setIndicator(tabItemList.get(i).getTabView());// 添加Fragment//初始化傳參:http://bbs.csdn.net/topics/391059505Bundle bundle = new Bundle();if(i == 0 ){bundle.putString("param", "http://www.baidu.com");}else if(i == tabItemList.size() - 1){bundle.putString("param", "http://blog.csdn.net");}else{bundle.putString("param", "http://www.cnblogs.com");}mTopUnderlineFTabHostLayout.addTab(spec, tabItemList.get(i).getTabFragment(), bundle);}//默認選中第一項mTopUnderlineFTabHostLayout.setCurrentTab(0);tabItemList.get(0).setChecked(true);}private void initEvents() {//選項卡的切換事件監(jiān)聽mTopUnderlineFTabHostLayout.setOnTabChangedListener(new TabHost.OnTabChangeListener() {@Overridepublic void onTabChanged(String tabId) {//重置Tab樣式for (int i = 0; i < tabItemList.size(); i++) {TabItem tabitem = tabItemList.get(i);if (tabId.equals(tabitem.getTabTitle())) {tabitem.setChecked(true);} else {tabitem.setChecked(false);}}Toast.makeText(MainActivity.this, tabId, Toast.LENGTH_SHORT).show();}});}/*** 選項卡子項類*/class TabItem{private Context mContext;private TextView top_title;private View top_underline;//底部選項卡對應(yīng)的文字private String tabTitle;//底部選項卡對應(yīng)的Fragment類private Class<? extends Fragment> tabFragment;public TabItem(Context mContext, String tabTitle, Class tabFragment){this.mContext = mContext;this.tabTitle = tabTitle;this.tabFragment = tabFragment;}public Class<? extends Fragment> getTabFragment() {return tabFragment;}public String getTabTitle() {return tabTitle;}/*** 獲取底部選項卡的布局實例并初始化設(shè)置*/private View getTabView() {//============引用選項卡的各個選項的布局文件=================View toptabitemView = View.inflate(mContext,R.layout.tab_top_underline_item, null);//===========設(shè)置選項卡的文字==========top_title = (TextView) toptabitemView.findViewById(R.id.top_title);//設(shè)置選項卡的文字 top_title.setText(tabTitle);//===========設(shè)置選項卡控件的下劃線==========top_underline = (View) toptabitemView.findViewById(R.id.top_underline);return toptabitemView;}/*** 更新文字顏色*/public void setChecked(boolean isChecked) {if(tabTitle != null){if(isChecked){//修改文字顏色 top_title.setTextColor(getResources().getColor(R.color.tab_text_selected_top));//修改下劃線的顏色 top_underline.setBackgroundColor(getResources().getColor(R.color.tab_underline_selected_top));}else{//修改文字顏色 top_title.setTextColor(getResources().getColor(R.color.tab_text_normal_top));//修改下劃線的顏色 top_underline.setBackgroundColor(getResources().getColor(R.color.tab_underline_normal_top));}}}} }混淆配置
無
參考資料
Android的FragmentTabHost使用(頂部或底部菜單欄)
FragmentTabHost使用方法
Android_ FragmentTabHost切換Fragment時避免重復(fù)加載UI
使用FragmentTabHost+TabLayout+ViewPager實現(xiàn)雙層嵌套Tab
如何自定義FragmentTabHost中某一個Tab的點擊效果
FragmentTabHost布局的使用及優(yōu)化方式
改變FragmentTabHost選中的文字顏色
fragmenttabhost 傳參問題
FragmentTabHost+fragment中獲得fragment的對象
fragment中的attach/detach方法說明(網(wǎng)上拷貝,只為作筆記)
FragmentTabHost切換Fragment,與ViewPager切換Fragment時重新onCreateView的問題
Android選項卡動態(tài)滑動效果
項目demo下載地址
https://github.com/haiyuKing/FragmentTabHostUnderLineDemo
轉(zhuǎn)載于:https://www.cnblogs.com/whycxb/p/7788060.html
總結(jié)
以上是生活随笔為你收集整理的FragmentTabHostUnderLineDemo【FragmentTabHost带下划线】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 团队作业——随堂小测
- 下一篇: AFN中请求序列化的设置