Android项目开发实战之使用Fragment和FragmentTabHost搭建底部菜单(一)

学习在于实用,只有把自己学到的东西真正的融入到我们的开发中,并且使用的得心应手,那才是真正的掌握。而想把技术使用的得心应手并不是一蹴而就的,需要不断的巩固自己的知识体系,需要大量的实战练习,当然还不能缺少你的专研和耐心。

但是很多小伙伴们并不一定学过的知识都掌握了,而且相信很多伙伴们即使学习一种技术也还是停留在读过,看过,学习过,并没有真正的实战过,所以当时学习的技术觉得自己真正的学会了,搞懂了,而且信心满满的觉得自己可以不必在练习了,这是不对的,因为一时的学习并没有立马转变成为你的技能,而是需要多次的巩固,再次的练习,继而能够拓展出新花样,那才证明你真正的掌握了。

所以创建了这个系列的博文,该博文主要是以一个完整的项目作为实战,以项目的进展作为向导,分析每个功能的实现,以及针对这个功能的我思我想,当然博主也是个小菜鸟,真实的意图是想通过这个小项目来记录自己的学习过程,并且,恳求各位大神,在每个功能实现的过程中,请在评论中贡献您的想法,或是觉得我所使用的方法或逻辑并不是恰当的、最好的,那么请把想法写进评论中,既作为您对该功能实现的看法,也可以提供我思路,给我们一起提升的机会,在这拜谢各位大大。

博主一直以来很喜欢动漫,可以说是酷爱了,所以这次就想以一个动漫的APP做为项目的开发,并请了一位非设计专业同事看了几部其他动漫APP利用闲暇时间,给整理出来一些共同点且是大多功能以后大家都会遇到的东西,简易的画个了原图,非常感谢这位同事,下面上图看看我们的原形需求。

这里写图片描述

相信大家一看就会明白,APP确实还是挺简单的,但是所需要的功能以后大家可能都会碰到,那时你会怎么设计呢?怎么找出共同点呢?

好,原图已上,让我们来看看整体设计吧,首先大家可以看到整个APP有很多相似之处,比如说顶端有两个选择项,中间是不同的布局,下面又是相同的底部菜单。所以我们可能自然而然的就想到,统一的底部菜单 + 中间FrameLayout布局 + toolBar就可以搞定了,是不是很简单呢。

今天我们就先来实现APP底部菜单栏的UI显示,底部菜单UI展现,以我们的需求可以通过好几种方式实现,比如使用:TabHost + ActivityGroup(已过时),Fragment + RadioGroup,Fragment + FragmentTabHost等几种选择,由于ActivityGroup已过时,TabHost 也逐渐被Fragment 所取代,所以项目我们选择Fragment + FragmentTabHost来实现我们的底部菜单。

Fragment 和 FragmentTabHost 都是android.support.v4.app包下的类,所以我们再使用是首先要先导入正确的包,而在XML文件中我们需要如下使用:

<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="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">
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1"/>
    </android.support.v4.app.FragmentTabHost>

</LinearLayout>

我们定义垂直方向的LinearLayout布局,FrameLayout用来显示我们的只要内容,FragmentTabHost用来在底部显示菜单。

ok,布局文件已配置好了,下面可考虑怎么加载到Acitivity中,在这之前,我习惯先创建一个Application,里面封装一个全局的Context变量,如:

public class MyApplication extends Application{
    private static Context mContext;//全局获取context
    @Override
    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
    }
    /**
     * 获取全局context
     */
    public static Context getContext(){
        return mContext;
    }
}

还有先定义一个BaseActivity作为其他Activity的父类,并且把获取全部的资源方法封装进去。

public class BaseActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    public static Context getContext(){
        return SanHuiAppsAnimationApplication.getContext();
    }
    public static int getLayoutId(Context context, String paramString) {
        return context.getResources().getIdentifier(paramString, "layout", context.getPackageName());
    }

    public static int getStringId(Context context, String paramString) {
        return context.getResources().getIdentifier(paramString, "string", context.getPackageName());
    }

    public static int getDrawableId(Context context, String paramString) {
        return context.getResources().getIdentifier(paramString, "drawable", context.getPackageName());
    }

    public static int getStyleId(Context context, String paramString) {
        return context.getResources().getIdentifier(paramString, "style", context.getPackageName());
    }

    public static int getId(Context context, String paramString) {
        return context.getResources().getIdentifier(paramString, "id", context.getPackageName());
    }

    public static int getMenuId(Context context, String paramString) {
        return context.getResources().getIdentifier(paramString, "menu", context.getPackageName());
    }

    public static int getColorId(Context context, String paramString) {
        return context.getResources().getIdentifier(paramString, "color", context.getPackageName());
    }

    public static int getLayoutId(String paramString) {
        return getLayoutId(getContext(), paramString);
    }

    public static int getStringId(String paramString) {
        return getStringId(getContext(), paramString);
    }

    public static int getDrawableId(String paramString) {
        return getDrawableId(getContext(), paramString);
    }

    public static int getStyleId(String paramString) {
        return getStyleId(getContext(), paramString);
    }

    public static int getId(String paramString) {
        return getId(getContext(), paramString);
    }

    public static int getMenuId(String paramString) {
        return getMenuId(getContext(), paramString);
    }

    public static int getColorId(String paramString) {
        return getColorId(getContext(), paramString);
    }

    public static int getAnimId(String paramString) {
        return getContext().getResources().getIdentifier(paramString, "anim", getContext().getPackageName());
    }

    public static int getAttrId(String paramString) {
        return getContext().getResources().getIdentifier(paramString, "attr", getContext().getPackageName());
    }

    public static int getInterpolator(String name) {
        return getContext().getResources().getIdentifier(name, "interpolator", getContext().getPackageName());
    }

    public static int getDimenId(String paramString) {
        return getContext().getResources().getIdentifier(paramString, "dimen", getContext().getPackageName());
    }

}

好,准备工作已完成,,现在来看看怎么把我们的刚才的main.xml添加到MainActivity中,并实现底部菜单的切换。

public class MainActivity extends FragmentActivity{
    private FragmentTabHost mFragmentTabHost;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(BaseActivity.getLayoutId("activity_main"));
        mFragmentTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
        //初始化FragmentTabHost
        mFragmentTabHost.setup(this,getSupportFragmentManager(),BaseActivity.getId("realtabcontent"));
        addTabView("Collection", BaseActivity.getDrawableId("main_tab_item_collection"), CollectionFragment.class);
        addTabView("Animation", BaseActivity.getDrawableId("main_tab_item_animation"), AnimationFragment.class);
        addTabView("Game", BaseActivity.getDrawableId("main_tab_item_game"), GameFragment.class);
        addTabView("Mine", BaseActivity.getDrawableId("main_tab_item_mine"), MineFragment.class);
    }

    public void addTabView(String viewTag, int iconId, Class<?> cls) {
        View viewTabWidget = getTabWidget(iconId);
        TabHost.TabSpec tabSpec = mFragmentTabHost.newTabSpec(viewTag);
        tabSpec.setIndicator(viewTabWidget);
        mFragmentTabHost.addTab(tabSpec,cls,null);
    }
    public View getTabWidget(int iconId) {
        View viewTabWidget = LayoutInflater.from(this).inflate(BaseActivity.getLayoutId("activity_main_tabwidget"), null);
        ImageView view = (ImageView) viewTabWidget.findViewById(BaseActivity.getId("tab_label"));
        view.setImageResource(iconId);
        return viewTabWidget;
    }
}

其实很简单,首先,是通过获取资源文件并绑定FragmentTabHost,其中值得注意的是:
mFragmentTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);这个是从android.R.id.tabhost获取,main.xml也是这么给出的id,不要搞混了。

然后,通过得到所支持的FragmentManager来初始化FragmentTabHost,并绑定用于显示正文的Fragment。

再次,我们通过addTabView()方法把底部菜单所需要的View展示出来,这里使用的是TabHost.TabSpec,它需要一个标示几个参数,一个是tag标示,一个是用于底部菜单显示的view等,可以自己选择设置。这里的菜单View我是用xml文件selector选择器来自动选择的,因为四个底部菜单所用一样,这里就只贴出一个供参考:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/main_tab_collection" android:state_selected="false"/>
    <item android:drawable="@mipmap/main_tab_collection_h" android:state_selected="true"/>
</selector>

最后,我们通过mFragmentTabHost.addTab(tabSpec,cls,null);把底部菜单和与之相关联的Fragment关联起来,从而达到在我们点击底部菜单时显示与之相对应的正文内容。

ok,底部菜单这块已基本实现,下面来看看效果吧。

这里写图片描述

好了,大家也看到了效果,那么就请大家在评论区发表下意见,或许你的实现方式更好呢,共同学习才能更快进步,谢谢大家。

更多资讯请关注微信平台,有博客更新会及时通知。爱学习爱技术。

这里写图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值