快速开发android应用4-使用viewpager+fragment构建主页
2017-07-18 23:30
495 查看
概述
本次快速开发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=" 4000 @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
参考资料:
UI-BottomNavigationBar-底部导航栏
ViewPager+Fragment【经典案例】
相关文章推荐
- android 快速开发四、ViewPager+Fragment 组合使用
- 【Android 应用开发】Android中使用ViewPager制作广告栏效果 - 解决ViewPager占满全屏页面适配问题
- 【Android 应用开发】Android中使用ViewPager制作广告栏效果 - 解决ViewPager占满全屏页面适配问题
- Android应用开发(2):制作一个漂亮的引导界面--viewpager的使用
- 【移动开发】Android中Fragment+ViewPager的配合使用 推荐
- Android开发学习之使用ViewPager打造应用引导界面面
- Android开发ViewPager和Fragment结合使用实现新闻类app基本框架(一)
- Android开发ViewPager的预加载和Fragment的销毁问题,以及tabLayout+ViewPager的使用,tablayout平板适配问题解决
- Android开发ViewPager和Fragment结合使用实现新闻类app( 三 )(基本成型的app)
- Android 使用Fragment,ViewPagerIndicator 开发APP项目的主框架
- 【Android 应用开发】Android中使用ViewPager制作广告栏效果 - 解决ViewPager占满全屏页面适配问题
- Android UI开发第三十篇——使用Fragment构建灵活的桌面
- 【Android UI设计与开发】第02期:引导界面(二)使用ViewPager实现欢迎引导页面
- 【Android UI设计与开发】第01期:引导界面(一)ViewPager介绍和使用详解
- 【Android UI设计与开发】第02期:引导界面(二)使用ViewPager实现欢迎引导页面
- 【Android UI设计与开发】第02期:引导界面(二)使用ViewPager实现欢迎引导页面
- 【Android UI设计与开发】第02期:引导界面(二)使用ViewPager实现欢迎引导页面
- 【Android 开发】:UI控件之 ViewPager 多页面滑动效果控件的的使用
- Android UI开发第三十篇——使用Fragment构建灵活的桌面
- android_使用ViewPager和Fragment实现滑动导航