zoukankan      html  css  js  c++  java
  • 【Android UI设计与开发】5.底部菜单栏(二)使用Fragment实现底部菜单栏

    既然 Fragment 取代了TabActivity,当然 TabActivity 的能实现的菜单栏,Fragment 当然也能实现。主要其实就是通过菜单栏的点击事件切换 Fragment 的显示和隐藏。

    来看看栗子吧:

    1.效果图来了:

    2.代码具体实现

    2.1 自定义底部菜单栏实现方式

    (1)对应的 Fragment 编辑代码和布局实现在前面的 Fragment介绍和简单实现  中已经有提及,代码中没复杂的地方,此处略过,具体可看实例代码。

    (2)菜单栏实现,这里使用代码实现的,其实也可以用布局文件实现,代码如下:

    package com.yanis.yc_ui_fragment_menu;
    
    import android.content.Context;
    import android.graphics.Color;
    import android.util.AttributeSet;
    import android.util.TypedValue;
    import android.view.Gravity;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    /**
     * 
     * @author YeChao
     * @功能描述:自定义底部工具栏
     *
     */
    public class ViewIndicator extends LinearLayout implements OnClickListener {
        private int mDefaultIndicator = 0; // 默认的选定View
    
        private static int mCurIndicator; // 当前选定View
    
        private static View[] mIndicators; // View集合
    
        private OnIndicateListener mOnIndicateListener; // 对应的监听器
        // 对应的图标Tag
        private static final String TAG_ICON_0 = "icon_tag_0";
        private static final String TAG_ICON_1 = "icon_tag_1";
        private static final String TAG_ICON_2 = "icon_tag_2";
        private static final String TAG_ICON_3 = "icon_tag_3";
        private static final String TAG_ICON_4 = "icon_tag_4";
        // 对应的文字Tag
        private static final String TAG_TEXT_0 = "text_tag_0";
        private static final String TAG_TEXT_1 = "text_tag_1";
        private static final String TAG_TEXT_2 = "text_tag_2";
        private static final String TAG_TEXT_3 = "text_tag_3";
        private static final String TAG_TEXT_4 = "text_tag_4";
        // 未选中状态
        private static final int COLOR_UNSELECT = Color.argb(100, 0xff, 0xff, 0xff);
        // 选中状态
        private static final int COLOR_SELECT = Color.WHITE;
    
        // 构造函数
        public ViewIndicator(Context context) {
            super(context);
        }
    
        public ViewIndicator(Context context, AttributeSet attrs) {
            super(context, attrs);
            mCurIndicator = mDefaultIndicator;
            setOrientation(LinearLayout.HORIZONTAL);// 水平布局
            init();
        }
    
        /**
         * 菜单视图布局
         * 
         * @param iconResID
         *            图片资源ID
         * @param stringResID
         *            文字资源ID
         * @param stringColor
         *            颜色资源ID
         * @param iconTag
         *            图片标签
         * @param textTag
         *            文字标签
         * @return
         */
        private View createIndicator(int iconResID, int stringResID,
                int stringColor, String iconTag, String textTag) {
            // 实例一个LinearLayout
            LinearLayout view = new LinearLayout(getContext());
            view.setOrientation(LinearLayout.VERTICAL);// 垂直布局
            // 设置宽高和权重
            view.setLayoutParams(new LinearLayout.LayoutParams(
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1));
            view.setGravity(Gravity.CENTER_HORIZONTAL);
            view.setBackgroundResource(R.drawable.main_tab_item_bg_normal);
            // 实例一个ImageView
            ImageView iconView = new ImageView(getContext());
            // 设置与该ImageView视图相关联的标记
            iconView.setTag(iconTag);
            // 设置宽高和权重
            iconView.setLayoutParams(new LinearLayout.LayoutParams(
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1));
            iconView.setImageResource(iconResID);// 设置图片资源
            // 实例一个TextView
            TextView textView = new TextView(getContext());
            // 设置与该TextView视图相关联的标记
            textView.setTag(textTag);
            // 设置宽高和权重
            textView.setLayoutParams(new LinearLayout.LayoutParams(
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1));
            // 设置文字颜色
            textView.setTextColor(stringColor);
            // 设置文字大小
            textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
            // 设置文字资源
            textView.setText(stringResID);
            // 添加视图到布局中
            view.addView(iconView);
            view.addView(textView);
            // 返回布局视图
            return view;
    
        }
    
        /**
         * 初始化视图
         */
        private void init() {
            mIndicators = new View[5];// 5个View
            // 第一个为默认选中的
            // 主页main_tab_item_bg_normal
            mIndicators[0] = createIndicator(R.drawable.main_tab_item_home_focus,
                    R.string.tab_item_home, COLOR_SELECT, TAG_ICON_0, TAG_TEXT_0);
            mIndicators[0].setBackgroundResource(R.drawable.main_tab_item_bg);
            mIndicators[0].setTag(Integer.valueOf(0));
            mIndicators[0].setOnClickListener(this);
            addView(mIndicators[0]);
            // 分类
            mIndicators[1] = createIndicator(
                    R.drawable.main_tab_item_category_normal,
                    R.string.tab_item_category, COLOR_UNSELECT, TAG_ICON_1,
                    TAG_TEXT_1);
            mIndicators[1].setBackgroundResource(R.drawable.main_tab_item_bg);
            mIndicators[1].setTag(Integer.valueOf(1));
            mIndicators[1].setOnClickListener(this);
            addView(mIndicators[1]);
            // 下载
            mIndicators[2] = createIndicator(R.drawable.main_tab_item_down_normal,
                    R.string.tab_item_down, COLOR_UNSELECT, TAG_ICON_2, TAG_TEXT_2);
            mIndicators[2].setBackgroundResource(R.drawable.main_tab_item_bg);
            mIndicators[2].setTag(Integer.valueOf(2));
            mIndicators[2].setOnClickListener(this);
            addView(mIndicators[2]);
            // 我的
            mIndicators[3] = createIndicator(R.drawable.main_tab_item_user_normal,
                    R.string.tab_item_user, COLOR_UNSELECT, TAG_ICON_3, TAG_TEXT_3);
            mIndicators[3].setBackgroundResource(R.drawable.main_tab_item_bg);
            mIndicators[3].setTag(Integer.valueOf(3));
            mIndicators[3].setOnClickListener(this);
            addView(mIndicators[3]);
            // 设置
            mIndicators[4] = createIndicator(
                    R.drawable.main_tab_item_setting_normal,
                    R.string.tab_item_setting, COLOR_UNSELECT, TAG_ICON_4,
                    TAG_TEXT_4);
            mIndicators[4].setBackgroundResource(R.drawable.main_tab_item_bg);
            mIndicators[4].setTag(Integer.valueOf(4));
            mIndicators[4].setOnClickListener(this);
            addView(mIndicators[4]);
        }
    
        public static void setIndicator(int which) {
            // /////////////////清除之前的状态/////////////////////////////////
            // mIndicators[mCurIndicator].setBackgroundResource(R.drawable.main_tab_item_bg_normal);
            ImageView prevIcon;
            TextView prevText;
            switch (mCurIndicator) {
            case 0:
                prevIcon = (ImageView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_ICON_0);
                prevIcon.setImageResource(R.drawable.main_tab_item_home);
                prevText = (TextView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_TEXT_0);
                prevText.setTextColor(COLOR_UNSELECT);
                break;
            case 1:
                prevIcon = (ImageView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_ICON_1);
                prevIcon.setImageResource(R.drawable.main_tab_item_category);
                prevText = (TextView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_TEXT_1);
                prevText.setTextColor(COLOR_UNSELECT);
                break;
            case 2:
                prevIcon = (ImageView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_ICON_2);
                prevIcon.setImageResource(R.drawable.main_tab_item_down);
                prevText = (TextView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_TEXT_2);
                prevText.setTextColor(COLOR_UNSELECT);
                break;
            case 3:
                prevIcon = (ImageView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_ICON_3);
                prevIcon.setImageResource(R.drawable.main_tab_item_user);
                prevText = (TextView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_TEXT_3);
                prevText.setTextColor(COLOR_UNSELECT);
                break;
            case 4:
                prevIcon = (ImageView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_ICON_4);
                prevIcon.setImageResource(R.drawable.main_tab_item_setting);
                prevText = (TextView) mIndicators[mCurIndicator]
                        .findViewWithTag(TAG_TEXT_4);
                prevText.setTextColor(COLOR_UNSELECT);
                break;
            }
            // /////////////////更新前状态/////////////////////////////////
            // mIndicators[which].setBackgroundResource(R.drawable.main_tab_item_bg_focus);
            ImageView currIcon;
            TextView currText;
            /**
             * 设置选中状态
             */
            switch (which) {
            case 0:
                currIcon = (ImageView) mIndicators[which]
                        .findViewWithTag(TAG_ICON_0);
                currIcon.setImageResource(R.drawable.main_tab_item_home_focus);
                currText = (TextView) mIndicators[which]
                        .findViewWithTag(TAG_TEXT_0);
                currText.setTextColor(COLOR_SELECT);
                break;
            case 1:
                currIcon = (ImageView) mIndicators[which]
                        .findViewWithTag(TAG_ICON_1);
                currIcon.setImageResource(R.drawable.main_tab_item_category_focus);
                currText = (TextView) mIndicators[which]
                        .findViewWithTag(TAG_TEXT_1);
                currText.setTextColor(COLOR_SELECT);
                break;
            case 2:
                currIcon = (ImageView) mIndicators[which]
                        .findViewWithTag(TAG_ICON_2);
                currIcon.setImageResource(R.drawable.main_tab_item_down_focus);
                currText = (TextView) mIndicators[which]
                        .findViewWithTag(TAG_TEXT_2);
                currText.setTextColor(COLOR_SELECT);
                break;
            case 3:
                currIcon = (ImageView) mIndicators[which]
                        .findViewWithTag(TAG_ICON_3);
                currIcon.setImageResource(R.drawable.main_tab_item_user_focus);
                currText = (TextView) mIndicators[which]
                        .findViewWithTag(TAG_TEXT_3);
                currText.setTextColor(COLOR_SELECT);
                break;
            case 4:
                currIcon = (ImageView) mIndicators[which]
                        .findViewWithTag(TAG_ICON_4);
                currIcon.setImageResource(R.drawable.main_tab_item_setting_focus);
                currText = (TextView) mIndicators[which]
                        .findViewWithTag(TAG_TEXT_4);
                currText.setTextColor(COLOR_SELECT);
                break;
            }
    
            mCurIndicator = which;
        }
    
        public interface OnIndicateListener {
            public void onIndicate(View v, int which);
        }
    
        public void setOnIndicateListener(OnIndicateListener listener) {
            mOnIndicateListener = listener;
        }
    
        @Override
        public void onClick(View v) {
            if (mOnIndicateListener != null) {
                int tag = (Integer) v.getTag();
                switch (tag) {
                case 0:
                    if (mCurIndicator != 0) {
                        mOnIndicateListener.onIndicate(v, 0);
                        setIndicator(0);
                    }
                    break;
                case 1:
                    if (mCurIndicator != 1) {
                        mOnIndicateListener.onIndicate(v, 1);
                        setIndicator(1);
                    }
                    break;
                case 2:
                    if (mCurIndicator != 2) {
                        mOnIndicateListener.onIndicate(v, 2);
                        setIndicator(2);
                    }
                    break;
                case 3:
                    if (mCurIndicator != 3) {
                        mOnIndicateListener.onIndicate(v, 3);
                        setIndicator(3);
                    }
                    break;
                case 4:
                    if (mCurIndicator != 4) {
                        mOnIndicateListener.onIndicate(v, 4);
                        setIndicator(4);
                    }
                    break;
                default:
                    break;
                }
            }
        }
    }
    ViewIndicator

    (3)最后就是主界面代码,切换 Fragment 的显示和隐藏以及菜单栏的选中状态

    package com.yanis.yc_ui_fragment_menu;
    
    import com.yanis.yc_ui_fragment_menu.ViewIndicator.OnIndicateListener;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.view.View;
    
    public class MainActivity extends FragmentActivity {
         public static Fragment[] mFragments;  
         
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            setFragmentIndicator(0);  
        }
        
         /** 
         * 初始化fragment 
         */  
        private void setFragmentIndicator(int whichIsDefault) { 
            //实例化 Fragment 集合
             mFragments = new Fragment[5];  
             mFragments[0] = getSupportFragmentManager().findFragmentById(R.id.fragment_home);  
             mFragments[1] = getSupportFragmentManager().findFragmentById(R.id.fragment_category);  
             mFragments[2] = getSupportFragmentManager().findFragmentById(R.id.fragment_down);  
             mFragments[3] = getSupportFragmentManager().findFragmentById(R.id.fragment_user);  
             mFragments[4] = getSupportFragmentManager().findFragmentById(R.id.fragment_setting);  
             //显示默认的Fragment
             getSupportFragmentManager().beginTransaction().hide(mFragments[0])  
                     .hide(mFragments[1]).hide(mFragments[2]).hide(mFragments[3]).hide(mFragments[4]).show(mFragments[whichIsDefault]).commit(); 
             //绑定自定义的菜单栏组件
            ViewIndicator mIndicator = (ViewIndicator) findViewById(R.id.indicator);  
            ViewIndicator.setIndicator(whichIsDefault);  
            mIndicator.setOnIndicateListener(new OnIndicateListener() {  
                @Override  
                public void onIndicate(View v, int which) {  
                    //显示指定的Fragment
                      getSupportFragmentManager().beginTransaction()  
                      .hide(mFragments[0]).hide(mFragments[1])  
                      .hide(mFragments[2]).hide(mFragments[3]).hide(mFragments[4]).show(mFragments[which]).commit(); 
                }  
            });  
        }  
    }

    源代码地址:https://github.com/YeXiaoChao/Yc_ui_fragment_menu


    2.2 使用 Fragment+FragmentTabHost 来实现底部菜单栏方式

    效果是一样的,只是在上面的基础上使用 FragmentTabHost 来实现底部菜单栏,直接通过 FragmentTabHost 来切换 Fragment 的显示 ,而不是自定义的布局。

    (1)修改主布局代码,加入了FragmentTabHost 组件

    <?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" >
    
        <FrameLayout
            android:id="@+id/realtabcontent"
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            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="@drawable/main_tab_item_bg">
    
            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="0" />            
        </android.support.v4.app.FragmentTabHost>
    
    </LinearLayout>

    (2)单独为Tab按钮选项布局

    <?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/imageview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:focusable="false"
            android:padding="3dp" 
            android:src="@drawable/main_tab_item_home">
        </ImageView>
    
        <TextView
            android:id="@+id/textview"       
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:textSize="12sp"
            android:textColor="#ffffff">
        </TextView>
    
    </LinearLayout>

    (3) fragment布局界面和之前一样,就不再赘述

    (4) Tab选项的自定义按钮中图片资源文件,列出其中一个按钮,指定了按钮的选中状态和不选中状态不同的图片显示

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

    (5) Tab选项按钮背景资源文件,指定了点击的效果

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <!-- pressed -->
        <item android:drawable="@drawable/main_tab_item_bg_focus" android:state_enabled="true" android:state_pressed="true"/>
    
        <!-- focused -->
        <item android:drawable="@drawable/main_tab_item_bg_focus" android:state_enabled="true" android:state_focused="true"/>
    
        <!-- normal -->
        <item android:drawable="@drawable/main_tab_item_bg_normal" android:state_enabled="true"/>
    
    </selector>

    (6) 最后就是主界面代码的改变

    package com.yanis.yc_ui_fragment_tabhost;
    
    import android.os.Bundle;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentTabHost;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.TabHost.TabSpec;
    import android.widget.TextView;
    
    /**
     * 
     * @author yechao
     * @功能说明 自定义TabHost
     *
     */
    public class MainActivity extends FragmentActivity {
        // 定义FragmentTabHost对象
        private FragmentTabHost mTabHost;
    
        // 定义一个布局
        private LayoutInflater layoutInflater;
    
        // 定义数组来存放Fragment界面
        private Class fragmentArray[] = { FragmentHome.class,
                FragmentCategory.class, FragmentDown.class, FragmentUser.class,
                FragmentSetting.class };
    
        // 定义数组来存放按钮图片
        private int mImageViewArray[] = { R.drawable.main_tab_item_home,
                R.drawable.main_tab_item_category, R.drawable.main_tab_item_down,
                R.drawable.main_tab_item_user, R.drawable.main_tab_item_setting };
    
        // Tab选项卡的文字
        private String mTextviewArray[] = { "主页", "分类", "下载", "我的", "设置" };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initView();
        }
    
        /**
         * 初始化组件
         */
        private void initView() {
            // 实例化布局对象
            layoutInflater = LayoutInflater.from(this);
    
            // 实例化TabHost对象,得到TabHost
            mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
            mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
    
            // 得到fragment的个数
            int count = fragmentArray.length;
    
            for (int i = 0; i < count; i++) {
                // 为每一个Tab按钮设置图标、文字和内容
                TabSpec tabSpec = mTabHost.newTabSpec(mTextviewArray[i])
                        .setIndicator(getTabItemView(i));
                // 将Tab按钮添加进Tab选项卡中
                mTabHost.addTab(tabSpec, fragmentArray[i], null);
                // 设置Tab按钮的背景
                mTabHost.getTabWidget().getChildAt(i)
                        .setBackgroundResource(R.drawable.main_tab_item_bg);
            }
        }
    
        /**
         * 给Tab按钮设置图标和文字
         */
        private View getTabItemView(int index) {
            View view = layoutInflater.inflate(R.layout.tab_item_view, null);
    
            ImageView imageView = (ImageView) view.findViewById(R.id.imageview);
            imageView.setImageResource(mImageViewArray[index]);
    
            TextView textView = (TextView) view.findViewById(R.id.textview);
            textView.setText(mTextviewArray[index]);
    
            return view;
        }
    }

    源代码地址:https://github.com/YeXiaoChao/Yc_ui_fragment_tabhost

  • 相关阅读:
    数据采集,微软控件分页问题的处理
    固定表头和列头
    字符串转时间类型
    js url加密解密
    Chosen—jquery选择框插件
    拉动滚动条加载数据
    webservse导出excel和word
    文本框与autocomplete结合使用
    jQuery的Select操作集合
    (转)常用算法大全-贪婪算法
  • 原文地址:https://www.cnblogs.com/yc-755909659/p/4286672.html
Copyright © 2011-2022 走看看