前言:
开发中遇到的大多数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没错,就是我们的简书底部tab,关于APP底部tab添加item会在我的个人微信公众号上面发出,关注获取demo。
个人微信公众号.jpg
注:个人创建了简书专题——《Android开发资源经验分享》,欢迎投稿,共同学习。
网友评论