虽然Fragment设计的初衷是为了大屏幕的平板设备,但走着走着它目前已经广泛应用于我们的手机设备上了。比如下面我们常见的设计就可以使用fragment实现,先来个图片三连:



对于这个设计有很多种方式实现,比如可以使用TabLayout+Fragment,不过我想快速且优雅的实现,所以最终借助了一个第三方库实现下面的布局Table,采用了BottomNavigation+Fragment的方式。
BottomNavigation的GitHub地址:
https://github.com/armcha/LuseenBottomNavigation
也可以直接
implementation 'com.github.armcha:LuseenBottomNavigation:1.8.2'
那么下面就开始本文的重点内容了
一、主页面布局
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="@+id/fr_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<com.luseen.luseenbottomnavigation.BottomNavigation.BottomNavigationView
android:id="@+id/bnv_item"
android:layout_width="match_parent"
android:layout_height="30dp"
app:bnv_colored_background="false"
android:layout_alignParentBottom="true">
</com.luseen.luseenbottomnavigation.BottomNavigation.BottomNavigationView>
</RelativeLayout>
主页面的布局很简洁,FrameLayout就是展示fragment内容的地方,下面的BottomNavigationView就是底部导航栏控件。
二、实现底部导航栏布局效果
public class MainActivity extends AppCompatActivity {
@BindView(R.id.fr_content)
FrameLayout frContent;
@BindView(R.id.bnv_item)
BottomNavigationView mBottomView;
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
BottomNavigationItem bottomNavigationItem=new BottomNavigationItem("首页",
ContextCompat.getColor(this,R.color.mainPager),R.drawable.loudspeaker);
BottomNavigationItem bottomNavigationItem1=new BottomNavigationItem("编程",
ContextCompat.getColor(this,R.color.programCode),R.drawable.program);
BottomNavigationItem bottomNavigationItem2=new BottomNavigationItem("读书",
ContextCompat.getColor(this,R.color.readPager),R.drawable.book);
BottomNavigationItem bottomNavigationItem3=new BottomNavigationItem("理财",
ContextCompat.getColor(this,R.color.manageMoneyPager),R.drawable.money);
mBottomView.addTab(bottomNavigationItem);
mBottomView.addTab(bottomNavigationItem1);
mBottomView.addTab(bottomNavigationItem2);
mBottomView.addTab(bottomNavigationItem3);
//...
}
代码很清晰,创建多个底部的每个item实例,再将其加入到view中。
这里我做了一下怪[啊哈哈],使用了ButterKnife来获取控件,你可以不用,按照最原始的方式即可。到这里已经完成了一小半了,够快吧....
三、准备一个Fragment
这里我们创建了4个fragment,分别是首页、编程、读书和理财。我就拿理财来举例了(最近迷上了理财这个东西),其他三个都是一样的,或许这就是传说中的举一反三吧。
ManageMoneyFragment.class
public class ManageMoneyFragment extends Fragment {
private static final String TAG = "ManageMoneyFragment";
@Override
public void onAttach(Context context) {
Log.d(TAG, "onAttach: ");
super.onAttach(context);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: ");
return inflater.inflate(R.layout.manage_money_fragment,null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onViewCreated: ");
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
Log.d(TAG, "onActivityCreated: ");
super.onActivityCreated(savedInstanceState);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreate: ");
super.onCreate(savedInstanceState);
}
@Override
public void onStart() {
Log.d(TAG, "onStart: ");
super.onStart();
}
@Override
public void onResume() {
Log.d(TAG, "onResume: ");
super.onResume();
}
@Override
public void onPause() {
Log.d(TAG, "onPause: ");
super.onPause();
}
@Override
public void onStop() {
Log.d(TAG, "onStop: ");
super.onStop();
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
}
@Override
public void onDestroyView() {
Log.d(TAG, "onDestroyView: ");
super.onDestroyView();
}
@Override
public void onDetach() {
Log.d(TAG, "onDetach: ");
super.onDetach();
}
}
什么鬼,写了这么长一串感觉啥也没干啊,这不都是activity的生命周期方法嘛。哈哈,准确的这些都是Fragment的生命周期方法,写这些是为了下面小谈一些它的生命周期。
其实Fragment可以算Android里的第五大组件了,之前,有人把View作为第五大组件,但是由于相对于四大组件来说它没有生命周期,所以从这个角度来说,Fragment更适合称为第五大组件。
创建一个fragment到用户能看到的状态经历了以下的生命周期

同样销毁一个fragment会经历如下生命周期

或许这张图看起来会更清晰明了一点

相比于Activity,它的生命周期方法多了几个,比如它最开始的方法走的是onAttach,销毁的最后一步是onDetach方法,它们是一对方法因为fragment是需要依附Activity存在的,所以就有了这样的两个方法。
好,可以回来了,在上面代码中和我们的页面view直接相关的是 onCreateView方法,用inflater.inflate方法把fragment的页面布局填充进去就好了
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: ");
return inflater.inflate(R.layout.manage_money_fragment,null);
}
随便写了一个简单的布局
R.layout.manage_money_fragment
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/frag_manage_money"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="35sp"
android:layout_centerInParent="true"
android:text=" 在别人贪婪的时候,我们要恐惧;
在别人恐惧的时候,我们要贪婪;"/>
</RelativeLayout>
四、依附到Activity中
这是最后一步也是最关键的一步,fragment是需要依附到Activity中的。
在底部的导航栏view中,是有个点击方法的,通过这个点击方法我们对每个item进行选择,从而切换到相应的fragment
public class MainActivity extends AppCompatActivity {
//当前的fragment
private Fragment mCurrFragment=new Fragment();
//理财的fragment
private ManageMoneyFragment mManageMoneyFragment=new ManageMoneyFragment();
//编程的fragment
private ProgramFragment mProgramFragment=new ProgramFragment();
//阅读的fragment
private ReadFragment mReadFragment=new ReadFragment();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//....省略上面已展示的
//点击底部按钮选择对应的fragment
mBottomView.setOnBottomNavigationItemClickListener(new OnBottomNavigationItemClickListener() {
@Override
public void onNavigationItemClick(int index) {
switch (index){
case 0:
skipToHome();
break;
case 1:
skipToProgram();
break;
case 2:
skipToRead();
break;
case 3:
skipToManage();
break;
default:
break;
}
}
});
}
//跳转到理财fragment
private void skipToManage() {
switchFragment(mManageMoneyFragment);
}
//.....
因为在添加导航栏的item时,它的内部实现是ArrayList,所以只需要判断它的index就可以获取对应的item了。
选择完后,进行fragment的展示。这里我们使用的hide和show的方式,对于没有添加到ArrayList的,需要先添加再展示,对于已经添加过的我们直接展示就好了,注意在展示之前要将当前展示的先隐藏。
对于隐藏这样的方式就有个好处,我们不需要重复创建它的实例,节省了不必要消耗的性能和用户的流量。
private void switchFragment(Fragment targetFragment){
FragmentTransaction fragmentTransaction=getSupportFragmentManager().beginTransaction();
//隐藏目前的fragment,展示目标fragment
if(!targetFragment.isAdded()){
fragmentTransaction.hide(mCurrFragment)
.add(R.id.fr_content,targetFragment,targetFragment.getClass().getName())
.commit();
}else {
fragmentTransaction.hide(mCurrFragment)
.show(targetFragment)
.commit();
}
mCurrFragment=targetFragment;
}
到这里,就实现了笔者最开始的素质三连图的最后一张了。对于其他两张图我们只需要再添加两个fragment,再依附到Activity中就ok了.整个过程还是很优雅的哈[蜜汁微笑QAQ]
网友评论