您的位置:首页 > 移动开发 > Android开发

快速开发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【经典案例】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐