Android App之底部tab导航常用实现方案总结

snzzj 7年前
   <h3><strong>前言:</strong></h3>    <p>开发中遇到的大多数APP底部都有tab, 但是其实现方式各有不同,各有各的优点,今天,小生就带大家总结总结,如有更好的,还望指教...</p>    <p>先看看效果图</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/efe0cf17a17cc73407cc35e7d33d75f2.gif"></p>    <p style="text-align:center">AppBottomTab.gif</p>    <p>先来看看项目的目录截图,因为代码比较稍多了点,截图的目的是为了贴出的分布代码看起来更清楚。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/4c6e03922f0cae6fadd44d0272ddc025.png"></p>    <p style="text-align:center">AppBottomTab项目目录.png</p>    <p>说明:</p>    <p>这个目录相信大家看见就很明白了,关于第一种方式,大多数开发者应该都使用过了,这里就不贴代码了。下面看FragmentTabHost方式实现的代码。</p>    <p><strong>frtabhost—>FrTabHostStyleAct.java中的布局代码</strong></p>    <pre>  <code class="language-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></code></pre>    <p><strong>FrTabHostStyleAct.java</strong></p>    <pre>  <code class="language-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());      }    }</code></pre>    <p><strong>frtabhost—>MainTab .java</strong></p>    <pre>  <code class="language-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;      }  }</code></pre>    <p><strong>frtabhost—>MyFragmentTabHost .java</strong></p>    <pre>  <code class="language-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;      }  }</code></pre>    <p>至此,我们的第二中方式就已经实现了。</p>    <p>下面介绍第三种实现方式,使用TabLayout实现。</p>    <p>tablayout—>TabLayoutStyleAct.java代码</p>    <pre>  <code class="language-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) {                }          });      }  }</code></pre>    <p>说明: 如果会使用TabLayout的朋友知道,一般我们会将TabLayout结合fragment使用时,不是TabLayout在底部的。这里就把TabLayou巧用了,放在了APP的底部,作为切换tab使用,很灵活。</p>    <p>不知道大家有没有注意到,现在实现的这个有没有很眼熟呢?</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/f5de03925628889109368245b7168b9b.png"></p>    <p style="text-align:center">AppBottomTab项目底部截图.png</p>    <p>没错,就是我们的简书底部tab,关于APP底部tab添加item会在我的个人微信公众号上面发出,还没有关注的朋友,不放关注一下,欢迎随时沟通。</p>    <p> </p>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/a691f39e70d3</p>    <p> </p>