[Android] Android 使用 FragmentTabHost + Fragment 实现 微信 底部菜单

家住魔仙堡 提交于 2020-03-09 06:10:27

 Android 使用 FragmentTabHost + Fragment 实现 微信 底部菜单

 

利用FragmentTabHost实现底部菜单,在该底部菜单中,包括了4个TabSpec,每个TabSpec中包含了一个View,而View中包含了一个ImageView和一个TextView。

 

一、先演示下效果:

 

 二、TabHost基本介绍

TabWidget : 该组件就是TabHost标签页中上部 或者 下部的按钮, 可以点击按钮切换选项卡;

TabSpec : 代表了选项卡界面, 添加一个TabSpec即可添加到TabHost中;

-- 创建选项卡 : newTabSpec(String tag), 创建一个选项卡;

-- 添加选项卡 : addTab(tabSpec);

 

三、使用步骤

1、定义布局 : 在XML文件中使用 FragmentTabHost 组件, 并在其中定义一个FrameLayout选项卡内容;

<?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=".ui.activity.MainActivity">

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

    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff">

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0" />
    </android.support.v4.app.FragmentTabHost>
</LinearLayout>

 

需要注意的是,FragmentTabHost的id是需要使用安卓自带的id,“@android:id/tabhost”,而FragmentTabHost中的FrameLayout也需要使用安卓自带的id,tabcontent。另外一点是,这个文件中有两个FrameLayout,因为实现的是底部菜单,所以在FragmentTabHost中的FrameLayout是设置为0的,而FragmentTabHost真正需要显示的内容是在上面的FrameLayout中进行显示的。

2、定义 Indicator中的View 文件main_tab_indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv_tab_icon"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_marginTop="5dp"
        android:src="@drawable/main_tab_btn_news" />

    <TextView
        android:id="@+id/tv_tab_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="首页"
        android:textColor="@color/main_tab_text_color"
        android:textSize="10sp" />

</LinearLayout>

 

一张图片,一个文本

 

3、定义Tab MainTabItem.java

package com.jack.appnews.widget;

public class MainTabItem {
    private int Image;
    private int Text;
    private Class Fragment;

    public MainTabItem(int image, int text, Class fragment) {
        Image = image;
        Text = text;
        Fragment = fragment;
    }

    public int getImage() {
        return Image;
    }

    public void setImage(int image) {
        Image = image;
    }

    public int getText() {
        return Text;
    }

    public void setText(int text) {
        Text = text;
    }

    public Class getFragment() {
        return Fragment;
    }

    public void setFragment(Class fragment) {
        Fragment = fragment;
    }
}

 

4、在MainActivity中编写逻辑

 核心逻辑如下 (代码中有说明,共5步)

//1)实例化4个Tab类的对象mTabs.add(new MainTabItem(R.drawable.main_tab_btn_news, R.string.main_tab_news, NewsListFragment.class));mTabs.add(new MainTabItem(R.drawable.main_tab_btn_video, R.string.main_tab_video, VideoListFragment.class));mTabs.add(new MainTabItem(R.drawable.main_tab_btn_image, R.string.main_tab_image, ImageListFragment.class));mTabs.add(new MainTabItem(R.drawable.main_tab_btn_mine, R.string.main_tab_mine, MineFragment.class));//2)调用 setup 方法mTabHost.setup(this, getSupportFragmentManager(), R.id.real_content);//3)添加 Tabfor (MainTabItem tab : mTabs) {    TabHost.TabSpec tabSpec = mTabHost.newTabSpec(String.valueOf(tab.getText())).setIndicator(getTabItemView(tab));    mTabHost.addTab(tabSpec, tab.getFragment(), null);}//4)去除掉底部菜单图表之间的分割线if (android.os.Build.VERSION.SDK_INT > 10) {    mTabHost.getTabWidget().setShowDividers(0);}//5)事件绑定mTabHost.setOnTabChangedListener(this);

 

完整代码: MainActivity.java

package com.jack.appnews.ui.activity;

import android.support.v4.app.FragmentTabHost;
import android.view.View;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TextView;

import com.jack.appnews.R;
import com.jack.appnews.ui.BaseActivity;
import com.jack.appnews.ui.fragment.ImageListFragment;
import com.jack.appnews.ui.fragment.MineFragment;
import com.jack.appnews.ui.fragment.NewsListFragment;
import com.jack.appnews.ui.fragment.VideoListFragment;
import com.jack.appnews.widget.MainTabItem;

import java.util.ArrayList;

import butterknife.BindView;

public class MainActivity extends BaseActivity implements TabHost.OnTabChangeListener {
    @BindView(android.R.id.tabhost)
    FragmentTabHost mTabHost;
    private long exitTime = 0;

    private ArrayList<MainTabItem> mTabs = new ArrayList<>(4);

    @Override
    protected int inflateLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initViews() {
        initTabHost();
    }

    protected void initTabHost() {
        //1)实例化4个Tab类的对象
        mTabs.add(new MainTabItem(R.drawable.main_tab_btn_news, R.string.main_tab_news, NewsListFragment.class));
        mTabs.add(new MainTabItem(R.drawable.main_tab_btn_video, R.string.main_tab_video, VideoListFragment.class));
        mTabs.add(new MainTabItem(R.drawable.main_tab_btn_image, R.string.main_tab_image, ImageListFragment.class));
        mTabs.add(new MainTabItem(R.drawable.main_tab_btn_mine, R.string.main_tab_mine, MineFragment.class));

        //2)调用 setup 方法
        mTabHost.setup(this, getSupportFragmentManager(), R.id.real_content);

        //3)添加 Tab
        for (MainTabItem tab : mTabs) {
            TabHost.TabSpec tabSpec = mTabHost.newTabSpec(String.valueOf(tab.getText())).setIndicator(getTabItemView(tab));
            mTabHost.addTab(tabSpec, tab.getFragment(), null);
        }

        //4)去除掉底部菜单图表之间的分割线
        if (android.os.Build.VERSION.SDK_INT > 10) {
            mTabHost.getTabWidget().setShowDividers(0);
        }

        //5)事件绑定
        mTabHost.setOnTabChangedListener(this);
    }

    /**
     * 设置Indicator中的View
     *
     * @param tab
     * @return
     */
    private View getTabItemView(MainTabItem tab) {
        View view = getLayoutInflater().inflate(R.layout.main_tab_indicator, null);
        ImageView Tab_img = (ImageView) view.findViewById(R.id.iv_tab_icon);
        TextView Tab_txt = (TextView) view.findViewById(R.id.tv_tab_text);

        Tab_img.setBackgroundResource(tab.getImage());
        Tab_txt.setText(tab.getText());
        return view;
    }

    @Override
    public void onTabChanged(String tabId) {
        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);
            } else {
                v.setSelected(false);
            }
        }
        supportInvalidateOptionsMenu();
    }

    @Override
    public void onBackPressed() {
        if ((System.currentTimeMillis() - exitTime) > 2000) {
            exitTime = System.currentTimeMillis();
        } else {
            finish();
            System.exit(0);
        }
    }

}

 

四、源代码地址

Talk is cheap. Show me the code

话不多说,代码在这里下载!

 

https://github.com/wukong1688/Android-BaseTabHost

 

 这是我用FragmentTabHost + ViewPager + XRecycleList   实现的  标签切换 + 列表上滑加载+列表下滑刷新

其中 列表上滑加载+列表下滑刷新  可参考下一篇文章:

Android 支持下拉刷新、上拉加载更多 的 XRecyclerview

 

如果觉得有帮助,欢迎在 Github 为我 star!

 

五、参考文章

https://www.jianshu.com/p/491386d6435c

https://www.cnblogs.com/langfei8818/p/6349354.html

 

本博客地址: wukong1688

本文原文地址:https://www.cnblogs.com/wukong1688/p/10753339.html

转载请著名出处!谢谢~~

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!