美文网首页Android应用开发连载android技术专栏程序员
羊皮书APP(Android版)开发系列(十七)Android

羊皮书APP(Android版)开发系列(十七)Android

作者: JeenWang | 来源:发表于2016-03-30 10:41 被阅读3306次

    app的底部菜单栏是非常常见的,微信/qq/支付宝/糯米等都有这样的底部菜单栏,在我们日常的开发过程中也是会经常用到的,下面就是一种实现方式,供大家参考。

    首先看下效果图:

    未标题-1.png

    自定义底部导航布局BottomNavigationView,代码如下:

    package cn.studyou.navigationviewlibrary;
    
    import android.animation.Animator;
    import android.animation.AnimatorListenerAdapter;
    import android.content.Context;
    import android.os.Build;
    import android.support.v4.content.ContextCompat;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.util.TypedValue;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewAnimationUtils;
    import android.view.ViewGroup;
    import android.widget.FrameLayout;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class BottomNavigationView extends RelativeLayout {
    
        private OnBottomNavigationItemClickListener onBottomNavigationItemClickListener;
        private Context context;
        private final int NAVIGATION_HEIGHT = (int) getResources().getDimension(R.dimen.bottom_navigation_height);
        private int SHADOW_HEIGHT;
        private int currentItem = 0;
        private View backgroundColorTemp;
        private boolean withText = true;
        private boolean coloredBackground = true;
        private int itemActiveColorWithoutColoredBackground = -1;
        private int itemInactiveColor;
        private FrameLayout container;
        private boolean disableShadow = false;
        private List<BottomNavigationItem> bottomNavigationItems = new ArrayList<>();
        private List<View> viewList = new ArrayList<>();
        private ViewPager mViewPager;
    
    
        public BottomNavigationView(Context context) {
            super(context);
            this.context = context;
        }
    
    
        public BottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.context = context;
        }
    
        public BottomNavigationView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context = context;
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            ViewGroup.LayoutParams params = getLayoutParams();
            if (coloredBackground) {
                itemActiveColorWithoutColoredBackground = ContextCompat.getColor(context, R.color.colorActive);
                itemInactiveColor = ContextCompat.getColor(context, R.color.colorInactive);
                SHADOW_HEIGHT = (int) getResources().getDimension(R.dimen.bottom_navigation_shadow_height);
            } else {
                if (itemActiveColorWithoutColoredBackground == -1)
                    itemActiveColorWithoutColoredBackground = ContextCompat.getColor(context, R.color.itemActiveColorWithoutColoredBackground);
                itemInactiveColor = ContextCompat.getColor(context, R.color.withoutColoredBackground);
                SHADOW_HEIGHT = (int) getResources().getDimension(R.dimen.bottom_navigation_shadow_height_without_colored_background);
            }
            params.width = ViewGroup.LayoutParams.MATCH_PARENT;
            params.height = disableShadow ? NAVIGATION_HEIGHT : NAVIGATION_HEIGHT + SHADOW_HEIGHT;
            //setOrientation(LinearLayout.VERTICAL);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                setElevation(getResources().getDimension(R.dimen.bottom_navigation_elevation));
            }
            setLayoutParams(params);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            if (bottomNavigationItems.size() == 0) {
                throw new NullPointerException("You need at least one item");
            }
            int white = ContextCompat.getColor(context, R.color.white);
            backgroundColorTemp = new View(context);
            viewList.clear();
            int itemWidth = getWidth() / bottomNavigationItems.size();
            int itemHeight = LayoutParams.MATCH_PARENT;
            container = new FrameLayout(context);
            View shadow = new View(context);
            LinearLayout items = new LinearLayout(context);
            items.setOrientation(LinearLayout.HORIZONTAL);
            LayoutParams containerParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, NAVIGATION_HEIGHT);
            LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, NAVIGATION_HEIGHT);
            LayoutParams shadowParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, SHADOW_HEIGHT);
            containerParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            shadowParams.addRule(RelativeLayout.ABOVE, container.getId());
            shadow.setBackgroundResource(R.drawable.shadow);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                LayoutParams backgroundLayoutParams = new LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, NAVIGATION_HEIGHT);
                backgroundLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                container.addView(backgroundColorTemp, backgroundLayoutParams);
            }
            addView(shadow, shadowParams);
            addView(container, containerParams);
            container.addView(items, params);
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
            for (int i = 0; i < bottomNavigationItems.size(); i++) {
                final int index = i;
                if (!coloredBackground)
                    bottomNavigationItems.get(i).setColor(white);
                int textActivePaddingTop = (int) context.getResources().getDimension(R.dimen.bottom_navigation_padding_top_active);
                int viewInactivePaddingTop = (int) context.getResources().getDimension(R.dimen.bottom_navigation_padding_top_inactive);
                int viewInactivePaddingTopWithoutText = (int) context.getResources().getDimension(R.dimen.bottom_navigation_padding_top_inactive_without_text);
                final View view = inflater.inflate(R.layout.bottom_navigation, this, false);
                ImageView icon = (ImageView) view.findViewById(R.id.bottom_navigation_item_icon);
                TextView title = (TextView) view.findViewById(R.id.bottom_navigation_item_title);
                title.setTextColor(itemInactiveColor);
                viewList.add(view);
                if (i == currentItem) {
                    container.setBackgroundColor(bottomNavigationItems.get(index).getColor());
                    title.setTextColor(currentItem == i ?
                            itemActiveColorWithoutColoredBackground :
                            itemInactiveColor);
                }
                view.setPadding(view.getPaddingLeft(), i == 0 ? textActivePaddingTop : withText ? viewInactivePaddingTop : viewInactivePaddingTopWithoutText, view.getPaddingRight(),
                        view.getPaddingBottom());
                icon.setImageResource(bottomNavigationItems.get(i).getImageResource());
                icon.setColorFilter(i == 0 ? itemActiveColorWithoutColoredBackground : itemInactiveColor);
                if (i == 0) {
                    icon.setScaleX((float) 1.1);
                    icon.setScaleY((float) 1.1);
                }
                title.setTextSize(TypedValue.COMPLEX_UNIT_PX, currentItem == i ?
                        context.getResources().getDimension(R.dimen.bottom_navigation_text_size_active) :
                        withText ? context.getResources().getDimension(R.dimen.bottom_navigation_text_size_inactive) : 0);
                title.setText(bottomNavigationItems.get(i).getTitle());
                LayoutParams itemParams = new LayoutParams(itemWidth, itemHeight);
                items.addView(view, itemParams);
                view.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        onBottomNavigationItemClick(index);
                    }
                });
            }
    
        }
    
        /**
         * Add item for BottomNavigation
         *
         * @param item item to add
         */
        public void addTab(BottomNavigationItem item) {
            bottomNavigationItems.add(item);
        }
    
        public void isWithText(boolean withText) {
            this.withText = withText;
        }
    
        public void setItemActiveColorWithoutColoredBackground(int itemActiveColorWithoutColoredBackground) {
            this.itemActiveColorWithoutColoredBackground = itemActiveColorWithoutColoredBackground;
        }
    
        /**
         * With this BottomNavigation background will be white
         *
         * @param coloredBackground disable or enable background color
         */
        public void isColoredBackground(boolean coloredBackground) {
            this.coloredBackground = coloredBackground;
        }
    
        /**
         * Disable shadow of BottomNavigationView
         */
        public void disableShadow() {
            disableShadow = true;
        }
    
        private void onBottomNavigationItemClick(final int itemIndex) {
            if (currentItem == itemIndex) {
                return;
            }
    
            int viewActivePaddingTop = (int) context.getResources().getDimension(R.dimen.bottom_navigation_padding_top_active);
            int viewInactivePaddingTop = (int) context.getResources().getDimension(R.dimen.bottom_navigation_padding_top_inactive);
            int viewInactivePaddingTopWithoutText = (int) context.getResources().getDimension(R.dimen.bottom_navigation_padding_top_inactive_without_text);
            float textActiveSize = context.getResources().getDimension(R.dimen.bottom_navigation_text_size_active);
            float textInactiveSize = context.getResources().getDimension(R.dimen.bottom_navigation_text_size_inactive);
            for (int i = 0; i < viewList.size(); i++) {
                if (i == itemIndex) {
                    View view = viewList.get(itemIndex).findViewById(R.id.bottom_navigation_container);
                    final TextView title = (TextView) view.findViewById(R.id.bottom_navigation_item_title);
                    final ImageView icon = (ImageView) view.findViewById(R.id.bottom_navigation_item_icon);
                    BottomNavigationUtils.changeTextColor(title, itemInactiveColor, itemActiveColorWithoutColoredBackground);
                    BottomNavigationUtils.changeTextSize(title, withText ? textInactiveSize : 0, textActiveSize);
                    BottomNavigationUtils.imageColorChange(icon, itemInactiveColor, itemActiveColorWithoutColoredBackground);
                    BottomNavigationUtils.changeTopPadding(view, withText ? viewInactivePaddingTop : viewInactivePaddingTopWithoutText, viewActivePaddingTop);
                    icon.animate()
                            .setDuration(150)
                            .scaleX((float) 1.1)
                            .scaleY((float) 1.1)
                            .start();
                    int centerX = (int) viewList.get(itemIndex).getX() + viewList.get(itemIndex).getWidth() / 2;
                    int centerY = viewList.get(itemIndex).getHeight() / 2;
                    int finalRadius = Math.max(getWidth(), getHeight());
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        backgroundColorTemp.setBackgroundColor(bottomNavigationItems.get(itemIndex).getColor());
                        Animator changeBackgroundColor = ViewAnimationUtils.createCircularReveal(backgroundColorTemp, centerX, centerY, 0, finalRadius);
                        changeBackgroundColor.addListener(new AnimatorListenerAdapter() {
                            @Override
                            public void onAnimationEnd(Animator animation) {
                                super.onAnimationEnd(animation);
                                container.setBackgroundColor(bottomNavigationItems.get(itemIndex).getColor());
                            }
                        });
                        changeBackgroundColor.start();
                    } else {
                        BottomNavigationUtils.backgroundColorChange
                                (container, bottomNavigationItems.get(currentItem).getColor(), bottomNavigationItems.get(itemIndex).getColor());
                    }
                } else if (i == currentItem) {
                    View view = viewList.get(i).findViewById(R.id.bottom_navigation_container);
                    final TextView title = (TextView) view.findViewById(R.id.bottom_navigation_item_title);
                    final ImageView icon = (ImageView) view.findViewById(R.id.bottom_navigation_item_icon);
                    BottomNavigationUtils.imageColorChange(icon, itemActiveColorWithoutColoredBackground, itemInactiveColor);
                    BottomNavigationUtils.changeTopPadding(view, viewActivePaddingTop, withText ? viewInactivePaddingTop : viewInactivePaddingTopWithoutText);
                    BottomNavigationUtils.changeTextColor(title, itemActiveColorWithoutColoredBackground, itemInactiveColor);
                    BottomNavigationUtils.changeTextSize(title, textActiveSize, withText ? textInactiveSize : 0);
                    icon.animate()
                            .setDuration(150)
                            .scaleX(1)
                            .scaleY(1)
                            .start();
                }
            }
    
            if (mViewPager != null)
                mViewPager.setCurrentItem(itemIndex);
    
            if (onBottomNavigationItemClickListener != null)
                onBottomNavigationItemClickListener.onNavigationItemClick(itemIndex);
            currentItem = itemIndex;
        }
    
        /**
         * Creates a connection between this navigation view and a ViewPager
         *
         * @param pager          pager to connect to
         * @param colorResources color resources for every item in the ViewPager adapter
         * @param imageResources images resources for every item in the ViewPager adapter
         */
    
        public void setViewPager(ViewPager pager, int[] colorResources, int[] imageResources) {
            this.mViewPager = pager;
            if (pager.getAdapter().getCount() != colorResources.length || pager.getAdapter().getCount() != imageResources.length)
                throw new IllegalArgumentException("colorResources and imageResources must be equal to the ViewPager items : " + pager.getAdapter().getCount());
    
            for (int i = 0; i < pager.getAdapter().getCount(); i++)
                addTab(new BottomNavigationItem(pager.getAdapter().getPageTitle(i).toString(), colorResources[i], imageResources[i]));
    
            mViewPager.addOnPageChangeListener(new internalViewPagerListener());
            invalidate();
        }
    
        private class internalViewPagerListener implements ViewPager.OnPageChangeListener {
    
            private int mScrollState;
    
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (mScrollState == ViewPager.SCROLL_STATE_DRAGGING)
                    onBottomNavigationItemClick(position);
            }
    
            @Override
            public void onPageSelected(int position) {
                onBottomNavigationItemClick(position);
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
                if (state == ViewPager.SCROLL_STATE_DRAGGING)
                    mScrollState = ViewPager.SCROLL_STATE_DRAGGING;
                else if (state == ViewPager.SCROLL_STATE_IDLE)
                    mScrollState = ViewPager.SCROLL_STATE_IDLE;
            }
        }
    
    
        /**
         * Setup interface for item onClick
         */
    
        public interface OnBottomNavigationItemClickListener {
            void onNavigationItemClick(int index);
        }
    
        public void setOnBottomNavigationItemClickListener(OnBottomNavigationItemClickListener onBottomNavigationItemClickListener) {
            this.onBottomNavigationItemClickListener = onBottomNavigationItemClickListener;
        }
    }
    

    新建底部导航工具类BottomNavigationUtils.java,代码如下:

    package cn.studyou.navigationviewlibrary;
    
    import android.animation.ArgbEvaluator;
    import android.animation.ValueAnimator;
    import android.util.TypedValue;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class BottomNavigationUtils {
    
        public static void imageColorChange(final ImageView image, int fromColor, int toColor) {
            ValueAnimator imageColorChangeAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), fromColor, toColor);
            imageColorChangeAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animator) {
                    image.setColorFilter((Integer) animator.getAnimatedValue());
                }
            });
            imageColorChangeAnimation.setDuration(150);
            imageColorChangeAnimation.start();
        }
    
        public static void backgroundColorChange(final View view, int fromColor, int toColor) {
            ValueAnimator imageColorChangeAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), fromColor, toColor);
            imageColorChangeAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animator) {
                    view.setBackgroundColor((Integer) animator.getAnimatedValue());
                }
            });
            imageColorChangeAnimation.setDuration(150);
            imageColorChangeAnimation.start();
        }
    
        public static void changeTopPadding(final View view, int fromPadding, int toPadding) {
            ValueAnimator animator = ValueAnimator.ofFloat(fromPadding, toPadding);
            animator.setDuration(150);
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    float animatedValue = (float) valueAnimator.getAnimatedValue();
                    view.setPadding(view.getPaddingLeft(),
                            (int) animatedValue,
                            view.getPaddingRight(),
                            view.getPaddingBottom());
                }
            });
            animator.start();
        }
    
        public static void changeTextSize(final TextView textView, float from, float to) {
            ValueAnimator textSizeChangeAnimator = ValueAnimator.ofFloat(from, to);
            textSizeChangeAnimator.setDuration(150);
            textSizeChangeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, (float) valueAnimator.getAnimatedValue());
                }
            });
            textSizeChangeAnimator.start();
        }
    
        public static void changeTextColor(final TextView textView, int fromColor, int toColor) {
            ValueAnimator changeTextColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), fromColor, toColor);
            changeTextColorAnimation.setDuration(150);
            changeTextColorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animator) {
                    textView.setTextColor((Integer) animator.getAnimatedValue());
                }
            });
            changeTextColorAnimation.start();
        }
    }
    

    创建实体类BottomNavigationItem.java,代码如下:

    package cn.studyou.navigationviewlibrary;
    
    public class BottomNavigationItem {
    
        private String title;
        private int color;
        private int imageResource;
    
        public BottomNavigationItem(String title, int color, int imageResource) {
            this.title = title;
            this.color = color;
            this.imageResource = imageResource;
        }
        public int getImageResource() {
            return imageResource;
        }
    
        public void setImageResource(int imageResource) {
            this.imageResource = imageResource;
        }
    
        public int getColor() {
            return color;
        }
    
        public void setColor(int color) {
            this.color = color;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    }
    
    

    新建一张图片shadow.xml,代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
    
        <gradient
            android:startColor="#20000000"
            android:endColor="#0000"
            android:type="linear"
            android:angle="90">
        </gradient>
    
    </shape>
    

    底部导航View的布局文件bottom_navigation.xml,代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/bottom_navigation_container"
        android:layout_width="match_parent"
        android:layout_height="@dimen/bottom_navigation_height"
        android:minWidth="@dimen/bottom_navigation_min_width"
        android:orientation="vertical"
        android:paddingBottom="@dimen/bottom_navigation_padding_bottom"
        android:paddingLeft="@dimen/bottom_navigation_padding_left"
        android:paddingRight="@dimen/bottom_navigation_padding_right"
        android:background="?selectableItemBackgroundBorderless"
        android:paddingTop="@dimen/bottom_navigation_padding_top_inactive">
    
        <ImageView
            android:id="@+id/bottom_navigation_item_icon"
            android:layout_width="@dimen/bottom_navigation_icon"
            android:layout_height="@dimen/bottom_navigation_icon"
            android:layout_gravity="center_horizontal"
            android:gravity="center" />
    
        <TextView
            android:id="@+id/bottom_navigation_item_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"
            android:gravity="center"
            android:lines="1"
            android:textSize="@dimen/bottom_navigation_text_size_inactive"
            tools:text="Label One"/>
    
    </FrameLayout>
    

    资源文件colors.xml,代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="itemActiveColorWithoutColoredBackground">#2196F3</color>
        <color name="colorActive">#FFFFFF</color>
        <color name="colorInactive">#d2d0d1</color>
        <color name="withoutColoredBackground">#757575</color>
        <color name="white">#ffffff</color>
    </resources>
    
    

    资源文件dimens.xml,代码如下:

    <resources>
        <dimen name="bottom_navigation_elevation">8dp</dimen>
        <dimen name="bottom_navigation_shadow_height">8dp</dimen>
        <dimen name="bottom_navigation_shadow_height_without_colored_background">4dp</dimen>
        <dimen name="bottom_navigation_min_width">104dp</dimen>
        <dimen name="bottom_navigation_max_width">168dp</dimen>
        <dimen name="bottom_navigation_height">56dp</dimen>
        <dimen name="bottom_navigation_icon">24dp</dimen>
        <dimen name="bottom_navigation_padding_top_active">5dp</dimen>
        <dimen name="bottom_navigation_padding_top_inactive">9dp</dimen>
        <dimen name="bottom_navigation_padding_top_inactive_without_text">16dp</dimen>
        <dimen name="bottom_navigation_padding_bottom">7dp</dimen>
        <dimen name="bottom_navigation_padding_left">12dp</dimen>
        <dimen name="bottom_navigation_padding_right">12dp</dimen>
        <dimen name="bottom_navigation_text_size_active">14sp</dimen>
        <dimen name="bottom_navigation_text_size_inactive">12sp</dimen>
    </resources>
    
    

    到这里我们就定义好了底部菜单栏的View,接下来就可以在我们的Activity中使用了,这里我们采用Activity+Fragment的方式实现布局的切换。

    新建MainActivity,如下:

    package cn.studyou.bottomnavigation.Activity;
    
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.TextView;
    
    import cn.studyou.bottomnavigation.Fragment.HomeFragment;
    import cn.studyou.bottomnavigation.Fragment.MeFragment;
    import cn.studyou.bottomnavigation.Fragment.MessageFragment;
    import cn.studyou.bottomnavigation.R;
    import cn.studyou.navigationviewlibrary.BottomNavigationItem;
    import cn.studyou.navigationviewlibrary.BottomNavigationView;
    
    public class MainActivity extends FragmentActivity {
        BottomNavigationView bottomNavigationView;
        private Fragment homeFragment;
        private Fragment meFragment;
        private Fragment messageFragment;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomNavigation);
            if (bottomNavigationView != null) {
                bottomNavigationView.isWithText(true);
                bottomNavigationView.isColoredBackground(true);
                //bottomNavigationView.disableShadow();
                bottomNavigationView.isColoredBackground(false);
                bottomNavigationView.setItemActiveColorWithoutColoredBackground(getResources().getColor(R.color.fourthColor));
            }
    
            BottomNavigationItem bottomNavigationItem = new BottomNavigationItem
                    (getString(R.string.home), getResources().getColor(R.color.firstColor), R.drawable.ic_home_24dp);
            BottomNavigationItem bottomNavigationItem1 = new BottomNavigationItem
                    (getString(R.string.message), getResources().getColor(R.color.secondColor), R.drawable.ic_markunread_24dp);
            BottomNavigationItem bottomNavigationItem2 = new BottomNavigationItem
                    (getString(R.string.me), getResources().getColor(R.color.fourthColor), R.drawable.ic_timer_auto_24dp);
    
            selectedImages(0);
            bottomNavigationView.addTab(bottomNavigationItem);
            bottomNavigationView.addTab(bottomNavigationItem1);
            bottomNavigationView.addTab(bottomNavigationItem2);
            bottomNavigationView.setOnBottomNavigationItemClickListener(new BottomNavigationView.OnBottomNavigationItemClickListener() {
                @Override
                public void onNavigationItemClick(int index) {
                    switch (index) {
                        case 0:
                            selectedImages(0);
                            break;
                        case 1:
                            selectedImages(1);
                            break;
                        case 2:
                            selectedImages(2);
                            break;
                    }
                }
            });
        }
    
        /**
         * 设置选中
         *
         * @param i
         */
        private void selectedImages(int i) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            hideFragment(fragmentTransaction);
            switch (i) {
                case 0:
                    if (homeFragment == null) {
                        homeFragment = new HomeFragment();
                        fragmentTransaction.add(R.id.fragment_navigation, homeFragment);
                    } else {
                        fragmentTransaction.show(homeFragment);
                    }
                    break;
                case 1:
                    if (messageFragment == null) {
                        messageFragment = new MessageFragment();
                        fragmentTransaction.add(R.id.fragment_navigation, messageFragment);
    
                    } else {
                        fragmentTransaction.show(messageFragment);
                    }
                    break;
                case 2:
                    if (meFragment == null) {
                        meFragment = new MeFragment();
                        fragmentTransaction.add(R.id.fragment_navigation, meFragment);
                    } else {
                        fragmentTransaction.show(meFragment);
                    }
                    break;
                default:
                    break;
    
            }
            fragmentTransaction.commit();
        }
    
        /**
         * 初始化隐藏所有Fragment
         *
         * @param fragmentTransaction
         */
        private void hideFragment(FragmentTransaction fragmentTransaction) {
            if (homeFragment != null) {
                fragmentTransaction.hide(homeFragment);
            }
            if (messageFragment != null) {
                fragmentTransaction.hide(messageFragment);
            }
            if (meFragment != null) {
                fragmentTransaction.hide(meFragment);
            }
    
        }
    }
    
    

    布局文件activity_main.xml 如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white">
    
        <cn.studyou.navigationviewlibrary.BottomNavigationView
            android:id="@+id/bottomNavigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true" />
    
        <FrameLayout
            android:id="@+id/fragment_navigation"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/bottomNavigation"
            ></FrameLayout>
    </RelativeLayout>
    
    

    然后创建Fragment,有几个菜单项就创建几个Fragment,这里我使用了三个菜单项,创建的fragment依次是:HomeFragment、MeFragment、MessageFragment。

    package cn.studyou.bottomnavigation.Fragment;
    
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import cn.studyou.bottomnavigation.R;
    
    public class HomeFragment extends Fragment {
    
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_home, container, false);
        }
    
    }
    
    package cn.studyou.bottomnavigation.Fragment;
    
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import cn.studyou.bottomnavigation.R;
    
    public class MeFragment extends Fragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_me, container, false);
        }
    }
    
    
    package cn.studyou.bottomnavigation.Fragment;
    
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import cn.studyou.bottomnavigation.R;
    
    public class MessageFragment extends Fragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_message, container, false);
        }
    }
    
    

    布局文件也很简单

    fragment_home.xml

    <FrameLayout 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"
        tools:context="cn.studyou.bottomnavigation.Fragment.HomeFragment">
    
        <!-- TODO: Update blank fragment layout -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="@string/home" />
    
    </FrameLayout>
    

    fragment_me.xml

    <FrameLayout 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"
        tools:context="cn.studyou.bottomnavigation.Fragment.MeFragment">
    
        <!-- TODO: Update blank fragment layout -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="@string/me" />
    
    </FrameLayout>
    
    

    fragment_message.xml

    <FrameLayout 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"
        tools:context="cn.studyou.bottomnavigation.Fragment.MessageFragment">
    
        <!-- TODO: Update blank fragment layout -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="@string/message" />
    
    </FrameLayout>
    
    

    菜单的图标是使用Android Studio创建的,如下:

    ic_home_24dp.xml

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="24dp"
            android:height="24dp"
            android:viewportWidth="24.0"
            android:viewportHeight="24.0">
        <path
            android:fillColor="#FF000000"
            android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"/>
    </vector>
    
    

    ic_markunread_24dp.xml

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="24dp"
            android:height="24dp"
            android:viewportWidth="24.0"
            android:viewportHeight="24.0">
        <path
            android:fillColor="#FF000000"
            android:pathData="M20,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2zm0,4l-8,5 -8,-5V6l8,5 8,-5v2z"/>
    </vector>
    
    

    ic_timer_auto_24dp.xml

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="24dp"
            android:height="24dp"
            android:viewportWidth="24.0"
            android:viewportHeight="24.0">
        <path
            android:fillColor="#FF000000"
            android:pathData="M12,4C9.79,4 8,5.79 8,8s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zm0,10c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.67 -5.33,-4 -8,-4z"/>
    </vector>
    
    

    最后给出资源文件

    strings.xml

    <resources>
        <string name="app_name">BottomNavigation</string>
        <string name="home">主页</string>
        <string name="message">消息</string>
        <string name="me">我的</string>
    </resources>
    
    

    colors.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="colorPrimary">#3F51B5</color>
        <color name="colorPrimaryDark">#303F9F</color>
        <color name="colorAccent">#FF4081</color>
        <color name="firstColor">#00BCD4</color>
        <color name="secondColor">#E91E63</color>
        <color name="thirdColor">#FF5722</color>
        <color name="fourthColor">#4CAF50</color>
    </resources>
    
    

    到这里整个底部菜单栏就完成来,看起来是一大堆的代码,其实很好理解,就是使用一个自定义的布局和Fragment结合来实现的,自定义布局我们都要理解,Fragment使用方式我们更要熟悉。

    相关文章

      网友评论

        本文标题:羊皮书APP(Android版)开发系列(十七)Android

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