[AS2.3.3]底部栏实现 (使用FragmentTabHost+Fragment实现)

底部切换栏使用FragmentTabHost+Fragment实现,很早以前写过一篇,这篇算是整合下使用


首先来看下效果


效果.gif

使用如下

        List<BarTab> list;
        BarTab tab;
        Bundle bundle;

        list = new ArrayList<>();

        tab = new BarTab();
        tab.setTitle("首页");
        tab.setCls(TestFragment.class);
        tab.setImageNormal(R.mipmap.home1);
        tab.setImageSelect(R.mipmap.home2);
        bundle = new Bundle();
        bundle.putString("title","首页");
        tab.setBundle(bundle);
        list.add(tab);


        tab = new BarTab();
        tab.setTitle("发现");
        tab.setCls(TestFragment.class);
        tab.setImageNormal(R.mipmap.glod1);
        tab.setImageSelect(R.mipmap.glod2);
        bundle = new Bundle();
        bundle.putString("title","发现");
        tab.setBundle(bundle);
        list.add(tab);

        tab = new BarTab();
        tab.setTitle("用户");
        tab.setCls(TestFragment.class);
        tab.setImageNormal(R.mipmap.user1);
        tab.setImageSelect(R.mipmap.user2);
        bundle = new Bundle();
        bundle.putString("title","用户");
        tab.setBundle(bundle);
        list.add(tab);

        BaseBottomBar<BarTab> bottomBar = new BaseBottomBar<BarTab>(mActivity,
                tabHost,R.id.fl_test,R.layout.item_bar,list) {

            @Override
            protected TextView getBarText(View view) {
                return (TextView) view.findViewById(R.id.tv_bar);
            }

            @Override
            protected ImageView getBarImage(View view) {
                return (ImageView) view.findViewById(R.id.iv_bar);
            }

            @Override
            protected int setSelectColor() {
                return ContextCompat.getColor(mContext,R.color.appMainColor);
            }
        };

        bottomBar.setImageLoader(new ImageLoader() {
            @Override
            public void ImageLoader(Context context, Object o, ImageView view) {
                Glide.with(context).load(o).into(view);
            }
        }).create();

就是创建一个BaseBottomBar对象设置他的布局id和底部栏布局以及数据list就可以了!
必须实现的2个方法是getBarText和getBarImage,用来设置点击之后图片和文字的变化
当使用create()方法就可以创建成功。

代码只有3个类


代码层

首先看下FragmentTabHost的基本使用

谷歌官方例子

Activity中使用

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中使用

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"),
                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);

        return mTabHost;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mTabHost = null;
    }
}

以上是来自网上搜索的

基本使用有了,就开始写一个管理方法,用来简单使用吧!


首先我们先设置主布局
activity_test.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.gjn.msdemo.homepage.TestActivity">

    <FrameLayout
        android:id="@+id/fl_test"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >

    </FrameLayout>

    <android.support.v4.app.FragmentTabHost
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginBottom="5dp"
        android:layout_marginTop="5dp"
        android:id="@+id/fth_test" >

    </android.support.v4.app.FragmentTabHost>

</LinearLayout>

然后我们在设置一个每项的底部菜单
我这边设置了一个常规的一张图片和一个标题


底部Item

item_bar.xml

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv_bar"
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        app:srcCompat="@mipmap/home2" />

    <TextView
        android:id="@+id/tv_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="首页" />
</LinearLayout>

之后我们就要定义Item的属性了
这边我定义了一个属性类
BarTab.java

import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * BarTab
 * Author: gjn.
 * Time: 2018/1/4.
 */

public class BarTab {
    //标题
    private String title;
    //绑定的Fragment
    private Class<?> cls;
    //整个底部View
    private View view;
    //Bundle
    private Bundle bundle;
    //图标正常情况
    private Object imageNormal;
    //图标选中情况
    private Object imageSelect;
    //底部菜单的2个布局view
    private ItemView itemView;

    public static class ItemView{
        private ImageView image;
        private TextView text;

        public ImageView getImage() {
            return image;
        }

        public void setImage(ImageView image) {
            this.image = image;
        }

        public TextView getText() {
            return text;
        }

        public void setText(TextView text) {
            this.text = text;
        }
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Class<?> getCls() {
        return cls;
    }

    public void setCls(Class<?> cls) {
        this.cls = cls;
    }

    public Bundle getBundle() {
        return bundle;
    }

    public void setBundle(Bundle bundle) {
        this.bundle = bundle;
    }

    public View getView() {
        return view;
    }

    public void setView(View view) {
        this.view = view;
    }

    public Object getImageNormal() {
        return imageNormal;
    }

    public void setImageNormal(Object imageNormal) {
        this.imageNormal = imageNormal;
    }

    public Object getImageSelect() {
        return imageSelect;
    }

    public void setImageSelect(Object imageSelect) {
        this.imageSelect = imageSelect;
    }

    public ItemView getItemView() {
        return itemView;
    }

    public void setItemView(ItemView itemView) {
        this.itemView = itemView;
    }
}

我们对每一个底部选项都进行属性设置

最后我们写一个管理工具
BaseBottomBar.java

import android.app.Activity;
import android.graphics.Color;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;

import com.gjn.utilslibrary.utils.ImageLoader;

import java.util.ArrayList;
import java.util.List;

/**
 * BaseBottomBar
 * Author: gjn.
 * Time: 2018/1/4.
 */

public abstract class BaseBottomBar<T extends BarTab> implements TabHost.OnTabChangeListener {
    private Activity mActivity;
    private FragmentTabHost mTabHost;
    private int mContainerId;
    private int mViewId;
    private List<?> mItems;

    private int mNormalColor = -1;
    private int mSelectColor = -1;

    private BottomBarListener bottomBarListener;
    private ImageLoader mImageLoader;

    public BaseBottomBar(Activity activity, FragmentTabHost tabHost,
                            int containerId, int viewid, List<T> items) {
        mActivity = activity;
        mTabHost = tabHost;
        mContainerId = containerId;
        mViewId = viewid;
        mItems = items == null ? new ArrayList<>() : items;
        mNormalColor = setNormalColor();
        mSelectColor = setSelectColor();
    }

    protected int setSelectColor() {
        return Color.BLACK;
    }

    protected int setNormalColor() {
        return Color.BLACK;
    }

    private void reset(T item) {
        mImageLoader.ImageLoader(mActivity, item.getImageNormal(), getImage(item));
        getText(item).setText(item.getTitle());
        getText(item).setTextColor(mNormalColor);
    }

    private void select(T item) {
        mImageLoader.ImageLoader(mActivity, item.getImageSelect(), getImage(item));
        getText(item).setText(item.getTitle());
        getText(item).setTextColor(mSelectColor);
    }

    private ImageView getImage(T item) {
        return item.getItemView().getImage();
    }

    private TextView getText(T item) {
        return item.getItemView().getText();
    }

    public BaseBottomBar setBottomBarListener(BottomBarListener bottomBarListener) {
        this.bottomBarListener = bottomBarListener;
        return this;
    }

    public void setCurrentTab(int i) {
        mTabHost.setCurrentTab(i);
    }

    public List<?> getAllItem() {
        return mItems;
    }

    public View getView(int i) {
        T item = (T) mItems.get(i);
        return item.getView();
    }

    public BarTab.ItemView getItemView(int i) {
        T item = (T) mItems.get(i);
        return item.getItemView();
    }

    public BaseBottomBar setImageLoader(ImageLoader imageLoader) {
        mImageLoader = imageLoader;
        return this;
    }

    public void setItems(List<?> items) {
        mItems = items;
        mTabHost.removeAllViews();
        create();
    }

    public void create() {
        if (mTabHost == null) {
            throw new NullPointerException("TabHost is null!");
        }
        if (mImageLoader == null) {
            throw new NullPointerException("ImageLoader is null.");
        }
        mTabHost.setup(mActivity, ((FragmentActivity) mActivity).getSupportFragmentManager(),
                mContainerId);
        mTabHost.setOnTabChangedListener(this);
        mTabHost.getTabWidget().setDividerDrawable(null);
        for (int i = 0; i < mItems.size(); i++) {
            T item = (T) mItems.get(i);
            //设置每个Item的view和内部布局
            View view = LayoutInflater.from(mActivity).inflate(mViewId, null, false);
            BarTab.ItemView itemView = new BarTab.ItemView();
            itemView.setImage(getBarImage(view));
            itemView.setText(getBarText(view));
            item.setView(view);
            item.setItemView(itemView);
            //未设置选中图片,默认为正常
            if (item.getImageSelect() == null) {
                item.setImageSelect(item.getImageNormal());
            }
            //设置默认图片
            if (i == 0) {
                select(item);
            } else {
                reset(item);
            }
            TabHost.TabSpec tabSpec = mTabHost.newTabSpec(item.getTitle()).setIndicator(view);
            mTabHost.addTab(tabSpec, item.getCls(), item.getBundle());
        }
    }

    @Override
    public void onTabChanged(String tabId) {
        TabWidget widget = mTabHost.getTabWidget();
        for (int i = 0; i < widget.getChildCount(); i++) {
            T item = (T) mItems.get(i);
            if (i == mTabHost.getCurrentTab()) {
                select(item);
                if (bottomBarListener != null) {
                    bottomBarListener.onClick(i, tabId);
                }
            } else {
                reset(item);
            }
        }
    }

    public interface BottomBarListener {
        void onClick(int i, String title);
    }

    protected abstract TextView getBarText(View view);

    protected abstract ImageView getBarImage(View view);
}

里面的ImageLoader只是一个简单的接口,用来使用Glide设置图片的
ImageLoader.java

import android.content.Context;
import android.widget.ImageView;

/**
 * ImageLoader
 * Author: gjn.
 * Time: 2018/1/2.
 */

public interface ImageLoader {
    void ImageLoader(Context context, Object o, ImageView view);
}

总结

对以前的底部栏实现算是重新写下。将方法整合下,可能还是比较繁琐,不过目前算是我能实现的写法整合了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345