美文网首页Android Android经验和架构Android
Android开发之ViewPager+Fragment+Fra

Android开发之ViewPager+Fragment+Fra

作者: YungFan | 来源:发表于2016-03-31 12:49 被阅读2425次
    在Android开发中,底部菜单是经常要使用的,如微信、微博、支付宝等,实现底部菜单有好几种方式,大致分为:
    • 通过TabWidget实现
    • 隐藏TabWidget,通过RadioGroup和RadioButton实现底部菜单栏
    • 通过FragmentTabHost实现
    • 通过5.0以后的TabLayout实现
    • 通过最近推出的 Bottom navigation

    本文的主题是 ViewPager+Fragment+FragmentTabHost 实现底部菜单
    1、构造4个Fragment,每个布局类似如下
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" 
        android:gravity="center">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="fragment1" 
            android:textSize="20dp"/>
    
    </LinearLayout>
    
    2、Activity布局
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
         <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            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="fill_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/black" >
        </android.support.v4.app.FragmentTabHost>
    
    </LinearLayout>
    

    上面是一个ViewPager,用于装载Fragment进行滑动;下面放一个FragmentTabHost,用于存放底部菜单的具体内容,它的颜色就是黑色的,菜单的文字为白色,这样好区分。

    3、底部菜单布局,一般都是图片在上,文字在下,美工一般都会把图片提前准备好
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical" >
    
        <ImageView
            android:id="@+id/tab_imageview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
        <TextView
            android:id="@+id/tab_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@android:color/white" />
    
    </LinearLayout>
    
    4、Activity代码
    //注意是继承 FragmentActivity
    public class MainActivity extends FragmentActivity
    {
    
        // FragmentTabHost
        private FragmentTabHost mTabHost;
        // layoutInflater
        private LayoutInflater layoutInflater;
        // imageViewArray数组,用于显示底部菜单
        private int imageViewArray[] = { R.drawable.mywork, R.drawable.mypatient,
                R.drawable.infusion, R.drawable.personal };
        // textViewArray数组
        private String textViewArray[] = { "工作", "回家", "互动", "我的" };
        // Fragment数组
        private List<Fragment> list = new ArrayList<Fragment>();
        // ViewPager
        private ViewPager vp;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main_tab_layout);
    
            initView();
        }
    
        /**
         * 控件初始化
         */
        private void initView()
        {
            vp = (ViewPager) findViewById(R.id.pager);
    
            layoutInflater = LayoutInflater.from(this);
            mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
            mTabHost.setup(this, getSupportFragmentManager(), R.id.pager);
    
            Fragment1 fragment1 = new Fragment1();
            Fragment2 fragment2 = new Fragment2();
            Fragment3 fragment3 = new Fragment3();
            Fragment4 fragment4 = new Fragment4();
            list.add(fragment1);
            list.add(fragment2);
            list.add(fragment3);
            list.add(fragment4);
    
            int count = textViewArray.length;
    
            // 添加菜单内容
            for (int i = 0; i < count; i++)
            {
                // 一个菜单就是一个TabSpec,然后添加到FragmentTabHost中
                TabSpec tabSpec = mTabHost.newTabSpec(textViewArray[i])
                        .setIndicator(getTabItemView(i));
                mTabHost.addTab(tabSpec, list.get(i).getClass(), null);
                // 默认让第一个选中
                mTabHost.getTabWidget().getChildAt(0)
                        .setBackgroundResource(R.drawable.selector_tab_background);
            }
    
            // ViewPager添加Adapter,这里用FragmentPagerAdapter
            vp.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager())
            {
    
                @Override
                public int getCount()
                {
    
                    return list.size();
                }
    
                @Override
                public android.support.v4.app.Fragment getItem(int arg0)
                {
                    return list.get(arg0);
                }
            });
    
        }
    
        private View getTabItemView(int i)
        {
            View view = layoutInflater.inflate(R.layout.tab_content, null);
            ImageView mImageView = (ImageView) view
                    .findViewById(R.id.tab_imageview);
            TextView mTextView = (TextView) view.findViewById(R.id.tab_textview);
            mImageView.setBackgroundResource(imageViewArray[i]);
            mTextView.setText(textViewArray[i]);
            return view;
        }
    
    }
    

    上面的 selector_tab_background.xml文件如下,只是改变了一下背景色来示意选中

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:state_selected="true" android:drawable="@color/purple"/>
        <item android:state_focused="true" android:drawable="@color/purple"/>
        <item android:state_pressed="true" android:drawable="@color/purple"/>
        <item android:drawable="@android:color/black"/>
    
    </selector>
    

    这样写了以后,只能实现底部有菜单,上面能滑动,但是底部菜单和上面的ViewPager并没有关联起来,怎么关联呢?首先,上面滑动的时候,需要监听滑动到哪里了,然后下面的菜单跟着联动;同理,如果点击了下面的菜单,上面的ViewPager应该滑动到对应的Fragment

    5、关联ViewPager与底部菜单
    • ViewPager实现OnPageChangeListener监听器,目的是让ViewPager滑动的时候能够带着底部菜单联动
        vp.setOnPageChangeListener(new OnPageChangeListener()
            {
    
                @Override
                public void onPageScrollStateChanged(int arg0)
                {
    
                }
    
                @Override
                public void onPageScrolled(int arg0, float arg1, int arg2)
                {
    
                }
    
                @Override
                public void onPageSelected(int arg0)
                {
                    // 选中菜单
                    mTabHost.setCurrentTab(arg0);
                    // 设置对应菜单高亮
                    mTabHost.getTabWidget()
                            .getChildAt(arg0)
                            .setBackgroundResource(
                                    R.drawable.selector_tab_background);
                }
            });
    
    • FragmentTabHost实现setOnTabChangedListener,目的是当点击了下面的菜单时,上面的ViewPager应该滑动到对应的Fragment
    mTabHost.setOnTabChangedListener(new OnTabChangeListener()
            {
    
                @Override
                public void onTabChanged(String tabId)
                {
                    // 获取点击的菜单的位置
                    int position = mTabHost.getCurrentTab();
                    // ViewPager滑动到对应的位置
                    vp.setCurrentItem(position);
                }
            });
    

    至此,这个双向关联的底部菜单就已经完成了。如果要求内容不需要滑动,如微信、支付宝那种,只有底部点击切换Fragment的功能,那么只需要将Activity布局中的ViewPager换成一个FrameLayout占位,然后在程序替换Fragment即可~~

    相关文章

      网友评论

      • MiBoy:你这个会造成fragment 多次加载吧
      • wangduo0820:是不是还要定义四个Fragment1 2 3 4的类啊?
        YungFan:@wangduo0820 是的 有几个界面就几个
      • d4bfdc1ada42:看不懂FrameLayout的width,height,weight为什么都设置为0
        d4bfdc1ada42:@简简_单单 弄出来了,没事了
        d4bfdc1ada42:@YungFan 我也改过来了,为什么底部栏还是没出来
        YungFan:@简简_单单 那个可以去掉 我去改一下 免得有误导
      • 被咯苏州:Bottom navigation 我去查了资料,好像只有官方文档稍微提了下,但具体怎么实现没有找到,请问您知道哪里有怎么实现的资料吗?
        被咯苏州: @YungFan 请问您有链接吗? 还是我该怎么找到 再探底部菜单?
        YungFan:@被咯苏州 确实没有,只有规范,请看今天发表的 再探底部菜单 一文
      • 源小白:有app相关截图更明了呢
        YungFan:@源小白 由于图标太丑,就没贴了 :smile:
      • jas0nHu:刚好需要这个 不过 suport lob23.2好像自带底部菜单
        YungFan:@F1ReKing 是的 再探底部菜单一文中我也说明了
        GeekBug:@jas0nHu TabLayout要自定制 比较难实现
        YungFan:@jas0nHu 你说的应该是TabLayout的实现方式,文中提了一下,很容易实现,但是那个不太好定制!

      本文标题:Android开发之ViewPager+Fragment+Fra

      本文链接:https://www.haomeiwen.com/subject/ydxelttx.html