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=""/> <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="" />
</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

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

[Android] Android 使用 FragmentTabHost + Fragment 实现 微信 底部菜单的更多相关文章

  1. 安卓开发笔记——Fragment+FragmentTabHost组件(实现新浪微博底部菜单)

    记得之前写过2篇关于底部菜单的实现,由于使用的是过时的TabHost类,虽然一样可以实现我们想要的效果,但作为学习,还是需要来了解下这个新引入类FragmentTabHost 之前2篇文章的链接: 安 ...

  2. Android自己定义TabActivity(实现仿新浪微博底部菜单更新UI)

    现在Android上非常多应用都採用底部菜单控制更新的UI这样的框架,比如新浪微博 点击底部菜单的选项能够更新界面.底部菜单能够使用TabHost来实现,只是用过TabHost的人都知道自己定义Tab ...

  3. Android Fragment实现微信底部导航

    1.XML布局 (1)主界面 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout x ...

  4. <Android 基础(三十三)> TabHost ~ 仿微信底部菜单

    简介 Container for a tabbed window view. This object holds two children: a set of tab labels that the ...

  5. 转-Fragment+FragmentTabHost组件(实现新浪微博底部菜单)

    http://www.cnblogs.com/lichenwei/p/3985121.html 记得之前写过2篇关于底部菜单的实现,由于使用的是过时的TabHost类,虽然一样可以实现我们想要的效果, ...

  6. Android中软键盘弹出时底部菜单上移问题

    当在Android的layout设计里面如果输入框过多,则在输入弹出软键盘的时候,下面的输入框会有一部分被软件盘挡住,从而不能获取焦点输入. 解决办法: 方法一:在你的activity中的oncrea ...

  7. Android高仿qq及微信底部菜单的几种实现方式

    最近项目没那么忙,想着开发app的话,有很多都是重复,既然是重复的,那就没有必要每次都去写,所以就想着写一个app通用的基本框架,这里说的框架不是什么MVC,MVP,MVVM这种,而是app开发的通用 ...

  8. [Android] Android 支持下拉刷新、上拉加载更多 的 XRecyclerview

    XRecyclerView一个实现了下拉刷新,滚动到底部加载更多以及添加header功能的的RecyclerView.使用方式和RecyclerView完全一致,不需要额外的layout,不需要写特殊 ...

  9. Android典型界面设计——FragmentTabHost+Fragment实现底部tab切换

    一.问题描述 在上次博文中,我们使用RadioGroup+ViewPage+Fragmen实现了顶部滑动导航(查看文章:http://www.cnblogs.com/jerehedu/p/460759 ...

随机推荐

  1. ASP.NET没有魔法——目录(完结)

    ASP.NET没有魔法——开篇-用VS创建一个ASP.NET Web程序 ASP.NET没有魔法——为什么使用ASP.NET ASP.NET没有魔法——第一个ASP.NET应用<MyBlog&g ...

  2. mysql 基础sql语句

    1.mysqladmin语句:  # 查看mysql版本 mysqladmin version  # 更改root用户密码 mysqladmin -u root -p原密码 password '新密码 ...

  3. Linux新增和删除环境变量

    vi ~/.bashrc 添加 export 变量名=值 使环境变量生效 source ~/.bashrc

  4. Python异常处理总结

    一.何谓异常处理 在我们调试程序时,经常不可避免地出现意料之外的情况,导致程序不得不停止运行,然后提示大堆提示信息,大多是这种情况都是由异常引起的.异常的出现一方面是因为写代码时粗心导致的语法错误,这 ...

  5. TypeError: argument 1 must be an integer, not _subprocess_handle/OSError: [WinError 87]

    Error Msg: Traceback (most recent call last): File "c:\python27\lib\site-packages\celery\worker ...

  6. Python--day12(三元表达式、函数对象、名称空间与作用域、函数嵌套定义)

    今日主要内容 1.  函数默认值细节(*) 2.  数据类型补充:三元表达式.列表推导式.字典推导式 (***) 3.  函数对象:函数名的各种应用场景 (*****) 4.  名称空间与作用域:解释 ...

  7. iOS 关于监听手机截图,UIView生成UIImage, UIImage裁剪与压缩的总结

    一.  关于监听手机截图 1. 背景: 发现商品的售价页总是被人转发截图,为了方便用户添加截图分享的小功能 首先要注册用户截屏操作的通知 - (void)viewDidLoad { [super vi ...

  8. codeforces#1136E. Nastya Hasn't Written a Legend(二分+线段树)

    题目链接: http://codeforces.com/contest/1136/problem/E 题意: 初始有a数组和k数组 有两种操作,一,求l到r的区间和,二,$a_i\pm x$ 并且会有 ...

  9. C#关于TreeView树在节点数较多时总是会出现闪烁的问题方法记录

    首先介绍下背景吧,问题如题,这个问题应该说困扰我大半年了(不是说我没有请教大佬,不是说我没有上网查过,之前在搜索时,总是没有解决此问题~~),直到最近一次在在优化代码时,再次上网查找,在发现搜索词条” ...

  10. PY3_线程红绿灯

    # Author:jum_# event 事件监测 红灯停绿灯行 线程标志位# 事件主要提供了三个方法wait.clear.set# clear:将“Flag”设置为False#set:将“Flag” ...