前言:
开发中遇到的大多数APP底部都有tab, 但是其实现方式各有不同,各有各的优点,今天,小生就带大家总结总结,如有更好的,还望指教...
先看看效果图
AppBottomTab.gif
先来看看项目的目录截图,因为代码比较稍多了点,截图的目的是为了贴出的分布代码看起来更清楚。
AppBottomTab项目目录.png
说明:
这个目录相信大家看见就很明白了,关于第一种方式,大多数开发者应该都使用过了,这里就不贴代码了。下面看FragmentTabHost方式实现的代码。
frtabhost—>FrTabHostStyleAct.java中的布局代码
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:id="@+id/realtabcontent" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" /> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <View android:layout_width="match_parent" android:layout_height="1px" android:background="@android:color/darker_gray" /> <myapp.com.mjj.appbottomtab.frtabhost.MyFragmentTabHost android:id="@+id/mytabhost" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" /> </FrameLayout> </LinearLayout>
FrTabHostStyleAct.java
public class FrTabHostStyleAct extends AppCompatActivity implements TabHost.OnTabChangeListener, View.OnTouchListener { private MyFragmentTabHost mTabHost; private CharSequence mTitle; // tab的底部文字 private String[] mTitles; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_frtabhoststyleact); initView(); } private void initView() { mTitle = getResources().getString(R.string.main_tab_name_explore); mTitles = getResources().getStringArray(R.array.main_titles_arrays); mTabHost = (MyFragmentTabHost) findViewById(R.id.mytabhost); mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent); if (android.os.Build.VERSION.SDK_INT > 10) { mTabHost.getTabWidget().setShowDividers(0); } initTabs(); mTabHost.setCurrentTab(0); mTabHost.setOnTabChangedListener(this); } private void initTabs() { MainTab[] tabs = MainTab.values(); int size = tabs.length; for (int i = 0; i < size; i++) { MainTab mainTab = tabs[i]; TabHost.TabSpec tab = mTabHost.newTabSpec(getString(mainTab.getResName()) + this.toString()); View indicator = View.inflate(this, R.layout.tab_indicator, null); TextView title = (TextView) indicator.findViewById(R.id.tab_title); ImageView icon = (ImageView) indicator.findViewById(R.id.iv_user_flow_icon); Drawable drawable = this.getResources().getDrawable(mainTab.getResIcon()); icon.setImageDrawable(drawable); title.setText(getString(mainTab.getResName())); tab.setIndicator(indicator); mTabHost.addTab(tab, mainTab.getClz(), null); mTabHost.getTabWidget().getChildAt(i).setOnTouchListener(this); } } @Override public void onTabChanged(String s) { final int size = mTabHost.getTabWidget().getTabCount(); for (int i = 0; i < size; i++) { View v = mTabHost.getTabWidget().getChildAt(i); if (i == mTabHost.getCurrentTab()) { v.setSelected(true); mTitle = mTitles[i == 3 ? i - 1 : i]; } else { v.setSelected(false); } } supportInvalidateOptionsMenu(); } @Override public boolean onTouch(View view, MotionEvent motionEvent) { super.onTouchEvent(motionEvent); boolean consumed = false; if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && view.equals(mTabHost.getCurrentTabView())) { Fragment currentFragment = getCurrentFragment(); if (currentFragment != null && currentFragment instanceof OnTabReselectListener) { OnTabReselectListener listener = (OnTabReselectListener) currentFragment; listener.onTabReselect(); consumed = true; } } return consumed; } private Fragment getCurrentFragment() { return getSupportFragmentManager().findFragmentByTag( mTabHost.getCurrentTabTag()); } }
frtabhost—>MainTab .java
public enum MainTab { NEWS(0, R.string.main_tab_name_explore, R.drawable.radio_homepage, FirstFragment.class), TWEET(1, R.string.main_tab_name_tweet, R.drawable.radio_ordersearch, SecondFragment.class), QUICK(2, R.string.main_tab_name_quick, R.drawable.radio_personal, ThirdFragment.class), EXPLORE(3, R.string.main_tab_name_my, R.drawable.radio_my, FourthFragment.class); private int idx; private int resName; private int resIcon; private Class<?> clz; private MainTab(int idx, int resName, int resIcon, Class<?> clz) { this.idx = idx; this.resName = resName; this.resIcon = resIcon; this.clz = clz; } public int getIdx() { return idx; } public void setIdx(int idx) { this.idx = idx; } public int getResName() { return resName; } public void setResName(int resName) { this.resName = resName; } public int getResIcon() { return resIcon; } public void setResIcon(int resIcon) { this.resIcon = resIcon; } public Class<?> getClz() { return clz; } public void setClz(Class<?> clz) { this.clz = clz; } }
frtabhost—>MyFragmentTabHost .java
public class MyFragmentTabHost extends FragmentTabHost { private String mCurrentTag; private String mNoTabChangedTag; public MyFragmentTabHost(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void onTabChanged(String tag) { if (tag.equals(mNoTabChangedTag)) { setCurrentTabByTag(mCurrentTag); } else { super.onTabChanged(tag); mCurrentTag = tag; } } public void setNoTabChangedTag(String tag) { this.mNoTabChangedTag = tag; } }
至此,我们的第二中方式就已经实现了。
下面介绍第三种实现方式,使用TabLayout实现,对Tablayout不是很熟悉的朋友,可以去看看这篇文章:《TabLayout两种添加tab方式,结合ViewPager+Fragment实现常见界面视图》。
tablayout—>TabLayoutStyleAct.java代码
public class TabLayoutStyleAct extends FragmentActivity { private TabLayout mTabLayout; private int[] tabNames = {R.string.main_tab_name_explore, R.string.main_tab_name_tweet, R.string.main_tab_name_quick, R.string.main_tab_name_my}; private int[] tabIcons = {R.drawable.radio_homepage, R.drawable.radio_ordersearch, R.drawable.radio_personal, R.drawable.radio_my}; private FrameLayout container; private MyFragmentPagerAdaper adapter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); View view = inflate(this, R.layout.activity_tablayout, null); setContentView(view); mTabLayout = (TabLayout) findViewById(R.id.tab_tablayout); for (int i = 0; i < tabNames.length; i++) { View tabView = view.inflate(this, R.layout.tab_indicator, null); TextView textView = (TextView) tabView.findViewById(R.id.tab_title); textView.setText(tabNames[i]); // 利用这种办法设置图标是为了解决默认设置图标和文字出现的距离较大问题 textView.setCompoundDrawablesWithIntrinsicBounds(0, tabIcons[i], 0, 0); mTabLayout.addTab(mTabLayout.newTab().setCustomView(textView)); } container = (FrameLayout) findViewById(R.id.fl_contains); adapter = new MyFragmentPagerAdaper(getSupportFragmentManager()); // 初始化默认显示的fragment Fragment fragment = (Fragment) adapter.instantiateItem(container, 0); adapter.setPrimaryItem(container, 0, fragment); adapter.finishUpdate(container); adapter.destroyItem(container, 0, fragment); // Tablayout选择tab监听 mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { int position = mTabLayout.getSelectedTabPosition();//tab.getPosition(); Fragment fragment = (Fragment) adapter.instantiateItem(container, position); adapter.setPrimaryItem(container, position, fragment); adapter.finishUpdate(container); adapter.destroyItem(container, position, fragment); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); } }
说明:如果会使用TabLayout的朋友知道,一般我们会将TabLayout结合fragment使用时,不是TabLayout在底部的。这里就把TabLayou巧用了,放在了APP的底部,作为切换tab使用,很灵活。
不知道大家有没有注意到,现在实现的这个有没有很眼熟呢?
AppBottomTab项目底部截图.png
作者:code小生