快速开发android应用4-使用viewpager+fragment构建主页

概述

本次快速开发Android应用系列,是基于课工场的公开课高效Android工程师6周培养计划,记录微服私访APP的整个开发过程以及当中碰到的问题,供日后学习参考。

上一篇我们主要实现基于okhttp解析服务端数据,并且以json格式返回给客户端,从而完成用户登录远程验证的功能。
还没看过前一篇文章的朋友可以先去参考快速开发android应用3-基于okhttp解析服务数据

这是本系列的第四篇,主要是实现APP的主页界面的框架,使用viewpager+fragment来展现主页内容,使用BottomNavigationBar来完成页面的切换。
效果图:
这里写图片描述

主页实现

构建主页布局

activity_main.xml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.torch.chainmanage.activity.MainActivity">

    <include
        android:id="@+id/layout_header"
        layout="@layout/header_title_bar" />

    <include
        android:id="@+id/layout_footer"
        layout="@layout/footer_bottom_bar" />

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/layout_footer"
        android:layout_below="@id/layout_header" />

</RelativeLayout>

header_title_bar.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="@dimen/title_bar_h"
    android:background="@color/colorAccent"
    android:gravity="center_vertical"
     >
    <TextView
        android:id="@+id/title_bar_back"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:drawableLeft="@drawable/title_bar_back"
        android:gravity="center"
        android:paddingLeft="@dimen/title_bar_back_left"
        android:paddingRight="@dimen/title_bar_add_padding"
        android:paddingBottom="@dimen/title_bar_back_bottom"
        android:paddingTop="@dimen/title_bar_back_bottom"/>

    <TextView
        android:id="@+id/title_bar_name"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="name"
        android:singleLine="true"
        android:textColor="@android:color/white"
        android:textSize="@dimen/title_bar_text_size" />

    <ImageView
        android:id="@+id/title_bar_more"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:src="@drawable/title_bar_add"
        android:paddingTop="@dimen/title_bar_add_bottom"
        android:paddingBottom="@dimen/title_bar_add_bottom"
        android:paddingLeft="@dimen/title_bar_add_padding"
        android:paddingRight="@dimen/title_bar_add_right"
        android:visibility="gone"
        />
    <ImageView
        android:id="@+id/title_bar_save"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:src="@drawable/title_bar_save"
        android:paddingTop="@dimen/title_bar_save_bootom"
        android:paddingBottom="@dimen/title_bar_save_bootom"
        android:paddingLeft="@dimen/title_bar_save_right"
        android:paddingRight="@dimen/title_bar_save_right"
        android:visibility="gone"
        />

    <ImageView
        android:id="@+id/title_bar_change"
        android:layout_width="wrap_content"
        android:layout_height="35dp"
        android:layout_toLeftOf="@+id/title_bar_more"
        android:layout_centerVertical="true"
        android:src="@drawable/title_bar_histroy"
        android:paddingTop="@dimen/title_bar_add_padding"
        android:paddingBottom="@dimen/title_bar_add_padding"
        android:paddingLeft="@dimen/title_bar_histroy_right"
        android:paddingRight="@dimen/title_bar_histroy_right"
        android:visibility="gone"
        />

</RelativeLayout>

footer_bottom_bar.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="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_alignParentBottom="true">
    <com.ashokvarma.bottomnavigation.BottomNavigationBar
        android:id="@+id/footer_bottom_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:bnbBackgroundColor="@color/color_bottom_layout_bg"
        app:bnbMode="mode_fixed"
        app:bnbInactiveColor="@color/bottom_text_color"
        app:bnbActiveColor="@color/colorAccent">

    </com.ashokvarma.bottomnavigation.BottomNavigationBar>

</RelativeLayout>

这里写图片描述
主页布局主要包括三个部分。

  • 自定义标题栏:包括标题以及增加、刷新等按钮,统一使用一个LinearLayout实现
  • 主页内容:使用一个viewpager,每个页面用一个fragment来展现,之后要修改界面只需修改fragment的布局即可。
  • 底部导航栏:使用BottomNavigationBar控件,控件中包含5个BottomNavigationItem,用来控制5个不同页面的切换。

页面frament实现

本次5个页面fragment的实现比较简单(后续会扩展),只是获取MainActivity传过来的fragment name,并显示在中间。
定义一个fragment使用的布局,以HomeFragment为例,其余类似。

<?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="@color/white"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textColor="@color/colorPrimary"
        android:textSize="22sp" />
</RelativeLayout>


新建fragment对象时,将需要传递的参数通过fragment.setArguments()方法传递进来。

 //将name传递给fragment
 public static HomeFragment newInstance(String name) {
        Bundle bundle = new Bundle();
        bundle.putString(BUNDLE_NAME, name);
        HomeFragment fragment = new HomeFragment();
        fragment.setArguments(bundle);
        return fragment;
    }


然后在调用fragment onCreate()方法时,解析出name,设置到textview当中。

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = getActivity();
        Bundle bundle = getArguments();
        if (bundle != null) {
            mFragmentName = bundle.getString(BUNDLE_NAME);
        }
        Log.d(TAG, "[onCreate] - " + mFragmentName);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView - " + mFragmentName);
        view = inflater.inflate(R.layout.fragment_home, container, false);
        TextView content = (TextView) view.findViewById(R.id.tv);
        content.setText(mFragmentName);
        content.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(getActivity(), LoginActivity.class));
            }
        });
        return view;
    }

BottomNavigationBar实现

BottomNavigationBar就是一个Material风格的底部导航栏,用于实现多个底部tag的切换效果,具体实现步骤如下。

第一步,在布局文件中配置

    <com.ashokvarma.bottomnavigation.BottomNavigationBar
        android:id="@+id/footer_bottom_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:bnbBackgroundColor="@color/color_bottom_layout_bg"
        app:bnbMode="mode_fixed"
        app:bnbInactiveColor="@color/bottom_text_color"
        app:bnbActiveColor="@color/colorAccent">

    </com.ashokvarma.bottomnavigation.BottomNavigationBar>

其中:

  • app:bnbMode=”mode_fixed”为显示文字,使用静态效果
  • app:bnbInactiveColor=”@color/bottom_text_color”为设置未选中文字颜色
  • app:bnbActiveColor=”@color/colorAccent”为设置选中文字颜色

    第二步,初始化BottomNavigationBar的图片和文字
    private final String[] mTitles = new String[]{"首页", "巡店", "拜访", "培训", "个人中心"}; //标题列表
    /** 底部图标资源-未选中状态 **/
    private final int[] mIconNormalRes = new int[]{R.drawable.menu_home_normal, R.drawable.menu_shop_normal,
        R.drawable.menu_visit_normal, R.drawable.menu_train_normal, R.drawable.menu_me_normal};
    /** 底部图标资源-选中状态 **/
    private final int[] mIconPressedRes = new int[]{R.drawable.menu_home_press, R.drawable.menu_shop_pressed,
            R.drawable.menu_visit_pressed, R.drawable.menu_train_pressed, R.drawable.menu_me_pressed};

    private List<BaseFragment> mFragments = new ArrayList<>(); //页面fragment列表
    private List<BottomNavigationItem> mNavigationItems = new ArrayList<>(); //底部item列表


        //初始化bottombar相关数据
        for (int i = 0; i < mTitles.length; i++) {
            BottomNavigationItem item = new BottomNavigationItem(mIconPressedRes[i], mTitles[i]);
            Drawable drawable = getResources().getDrawable(mIconNormalRes[i]);
            item.setInactiveIcon(drawable); //定制item未选中图片
            mNavigationItems.add(item);
        }


第三步,初始化BottomNavigationBar view,展现底部导航效果

     mBottomNavigationBar = (BottomNavigationBar)findViewById(R.id.footer_bottom_bar);
        for (BottomNavigationItem item : mNavigationItems) {
            mBottomNavigationBar.addItem(item);
        }
        mBottomNavigationBar.initialise();
        mBottomNavigationBar.setFirstSelectedPosition(0);
        setTitleName(mTitles[0]);


第四步,经过前三步,已经实现了展现的效果,这一步主要是监听item项的切换,完成标题栏和页面fragment的刷新。

     mBottomNavigationBar.setTabSelectedListener(new BottomNavigationBar.SimpleOnTabSelectedListener() {
            @Override
            public void onTabSelected(int position) {
                //未选中->选中
                mViewPager.setCurrentItem(position);
                refreshHeaderView(position);
            }
        });


viewpager实现

前面已经实现了页面布局及fragment的创建,接下来就要要将fragment加到viewpager中。
第一步,初始化viewpager所需的fragment实例

 private List<BaseFragment> mFragments = new ArrayList<>(); //页面fragment列表

        BaseFragment home = HomeFragment.newInstance("首页界面");
        mFragments.add(home);
        BaseFragment shop = ShopFragment.newInstance("巡店界面");
        mFragments.add(shop);
        BaseFragment visit = VisitFragment.newInstance("拜访界面");
        mFragments.add(visit);
        BaseFragment train = TrainFragment.newInstance("培训界面");
        mFragments.add(train);
        BaseFragment me = MeFragment.newInstance("个人中心");
        mFragments.add(me);


第二步,新建一个FragmentPagerAdapter对象,设置viewpager.setAdapter()方法初始化adapter对象

 private FragmentPagerAdapter mFragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }

        @Override
        public int getCount() {
            return mFragments.size();
        }
    };

        mViewPager = (ViewPager)findViewById(R.id.view_pager_content);
        mViewPager.setAdapter(mFragmentPagerAdapter);
        mViewPager.setCurrentItem(0);


第三步,通过viewpager.addOnPageChangeListener()方法监听页面切换,更新标题及底部item

       mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                Log.d(TAG, "onPageSelected - " + position);
                mBottomNavigationBar.selectTab(position);
                refreshHeaderView(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });


 /**
     * 更新当前页面的header view
     * @param position
     */
    private void refreshHeaderView(int position) {
        setTitleName(mTitles[position]);
        switch (position) {
            case 1:
                mTitleAddImage.setVisibility(View.VISIBLE);
                mTitleRefreshImage.setVisibility(View.VISIBLE);
                break;
            case 2:
                mTitleAddImage.setVisibility(View.VISIBLE);
                mTitleRefreshImage.setVisibility(View.INVISIBLE);
                break;
            default:
                mTitleAddImage.setVisibility(View.INVISIBLE);
                mTitleRefreshImage.setVisibility(View.INVISIBLE);
                break;
        }
    }

附录

快速开发android应用相关的代码都会更新在我的github上,大家可以通过star来跟进项目代码的变动
https://github.com/youyutorch/RapidDevAndroid

参考资料:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值