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


     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)添加 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);

    完整代码: 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

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

  • 相关阅读:
    luogu P2639 [USACO09OCT]Bessie的体重问题Bessie's We…
    1001. 害死人不偿命的(3n+1)猜想 (15)
    1003. 我要通过!(20)
    1002. 写出这个数 (20)
    《C语言程序设计(第四版)》阅读心得(一)
    1006. 换个格式输出整数 (15)
    背包问题之多重背包
    背包问题之完全背包
    背包问题之0-1背包
    动态规划例题
  • 原文地址:https://www.cnblogs.com/wukong1688/p/10753339.html
Copyright © 2020-2023  润新知