目标不是都能达到的,但它可以作为瞄准点。

72dcd259f21c473107b06fc51f310f92.png

前言:

Fragment是Android3.0后引入的一个新的API,它出现的初衷是为了适应大屏幕的平板电脑, 当然现在它仍然是平板APP UI设计的宠儿,而且我们普通手机开发也会加入这个Fragment, 我们可以把它看成一个小型的Activity,又称Activity片段!想想,如果一个很大的界面,我们就一个布局,写起界面来会有多麻烦,而且如果组件多的话是管理起来也很麻烦!而使用Fragment我们可以把屏幕划分成几块,然后进行分组,进行一个模块化的管理!从而可以更加方便的在运行过程中动态地更新Activity的用户界面!另外Fragment并不能单独使用,它需要嵌套在Activity中使用,尽管它拥有自己的生命周期,但是还是会受到宿主Activity的生命周期的影响,比如Activity被destory销毁了,它也会跟着销毁!

Fragment简介

4861392a64760ab2d6bcc35be14e2295.png

上图是Fragment的生命周期图,从该图中可以看到Fragment拥有跟Activity相似的生命周期,例如都有onCreate,onStart,onStop等过程。当然它也有自己独特的过程例如onCreateView,onActivityCreated等。官方文档说创建Fragment时至少需要实现三个方法:onCreate,onCreateView,OnPause。实际上真正需要重写的方法只有onCreateView一个,因为该方法是给Fragment提供视图的,所以重写该方法必不可少。

Fragment该如何使用?

本小节就android.app.Fragment实现选项卡功能来说明Fragment的一些用法。

基本思想:android.app.Fragment只能结合Activity使用,在使用上其实可以把它当成Activity中的一个视图控件。说的简单一点就是在一个Activity中需要几个布局界面,就添加几个Fragment来呈现和管理。例如:要实现一个带有三个选项的选项卡:

一、布局

首先是Activity的布局,Activity需要显示选项卡界面和内容界面两个部分,这里的内容区由FrameLayout进行包裹,具体呈现内容交由Fragment来实现:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

android:id="@+id/content"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1" >

android:layout_width="match_parent"

android:layout_height="60dp"

android:background="#F5F5F5" >

android:id="@+id/main_layout"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1" >

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:orientation="vertical" >

android:id="@+id/main_image"

android:layout_width="50dp"

android:layout_height="30dp"

android:layout_gravity="center_horizontal"

android:contentDescription="@string/desc"

android:src="@drawable/main_tab1" />

android:id="@+id/main_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal"

android:text="@string/main"

android:textColor="#929598"

android:textSize="15sp" />

android:id="@+id/navigation_layout"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1" >

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:orientation="vertical" >

android:id="@+id/navigation_image"

android:layout_width="50dp"

android:layout_height="30dp"

android:layout_gravity="center_horizontal"

android:contentDescription="@string/desc"

android:src="@drawable/navigation_tab2" />

android:id="@+id/navigation_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal"

android:text="@string/navigation"

android:textColor="#929598"

android:textSize="15sp" />

android:id="@+id/more_layout"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1" >

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:orientation="vertical" >

android:id="@+id/more_image"

android:layout_width="50dp"

android:layout_height="30dp"

android:layout_gravity="center_horizontal"

android:src="@drawable/more_tab2" />

android:id="@+id/more_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal"

android:text="@string/more"

android:textColor="#929598"

android:textSize="15sp" />

二、Fragment加载布局文件

在Activity的布局文件中,内容区是由FrameLayout进行包裹,具体呈现内容布局是由Fragment来实现,那么Fragment是如何实现一个界面布局呢?假如这里有一个布局文件fragment_main.xml,那么实现该布局文件代码如下:

public class Main extends Fragment {

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

View contactsLayout = inflater.inflate(R.layout.fragment_main, container, false);

return contactsLayout;

}

}

从上面可以看出页面不是一个Activity,而是一个Fragment。实现布局的加载是通过onCreateView()这个方法、通过LayoutInflater来获取页面view、false指的是添加非子视图、如果是true的话,就是添加子视图的意思。

三、最后,Fragment实现选项切换

在说明Fragment实现选项切换之前,首先要知道与FragmentTransaction相关的几个重要的方法。

// Fragment管理类

FragmentManager fragmentManager = getFragmentManager();

// 开启一个Fragment事务

FragmentTransaction transaction = fragmentManager.beginTransaction();

FragmentTransaction是Fragment的事务类,也是最直接操作Fragment的类。

transaction.add(int containerViewId, Fragment fragment);

add是用来添加一个Fragment到事务当中。

transaction.show(Fragment fragment);

show方法是用来展示Fragment。

transaction.commit();

提交Fragment事务。

transaction.hide(Fragment fragment);

hide方法是隐藏Fragment,与show方法相对。

下面看一下Activity具体怎么实现页面的跳转:

public class MainActivity extends Activity implements OnClickListener {

/**

* 用于展示主页的Fragment

*/

private Main mainFragment;

/**

* 用于展示导航的Fragment

*/

private Navigation navigationFragment;

/**

* 用于展示更多的Fragment

*/

private More moreFragment;

/**

* 主页界面布局

*/

private View mainLayout;

/**

* 导航界面布局

*/

private View navigationLayout;

/**

* 更多界面布局

*/

private View moreLayout;

/**

* 在Tab布局上显示主页图标的控件

*/

private ImageView mainImage;

/**

* 在Tab布局上显示导航图标的控件

*/

private ImageView navigationImage;

/**

* 在Tab布局上显示更多图标的控件

*/

private ImageView moreImage;

/**

* 在Tab布局上显示主页标题的控件

*/

private TextView mainText;

/**

* 在Tab布局上显示导航标题的控件

*/

private TextView navigationText;

/**

* 在Tab布局上显示更多标题的控件

*/

private TextView moreText;

/**

* 用于对Fragment进行管理

*/

private FragmentManager fragmentManager;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_main);

// 初始化布局元素

initViews();

fragmentManager = getFragmentManager();

// 第一次启动时选中第0个tab

setTabSelection(0);

}

/**

* 在这里获取到每个需要用到的控件的实例,并给它们设置好必要的点击事件。

*/

private void initViews() {

mainLayout = findViewById(R.id.main_layout);

navigationLayout = findViewById(R.id.navigation_layout);

moreLayout = findViewById(R.id.more_layout);

mainImage = (ImageView) findViewById(R.id.main_image);

navigationImage = (ImageView) findViewById(R.id.navigation_image);

moreImage = (ImageView) findViewById(R.id.more_image);

mainText = (TextView) findViewById(R.id.main_text);

navigationText = (TextView) findViewById(R.id.navigation_text);

moreText = (TextView) findViewById(R.id.more_text);

mainLayout.setOnClickListener(this);

navigationLayout.setOnClickListener(this);

moreLayout.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.main_layout:

// 当点击了主页tab时,选中第1个tab

setTabSelection(0);

break;

case R.id.navigation_layout:

// 当点击了导航tab时,选中第2个tab

setTabSelection(1);

break;

case R.id.more_layout:

// 当点击了更多tab时,选中第3个tab

setTabSelection(2);

break;

default:

break;

}

}

/**

* 根据传入的index参数来设置选中的tab页。

*

* @param index 每个tab页对应的下标。0表示主页,1表示导航,2表示更多

*/

private void setTabSelection(int index) {

// 每次选中之前先清楚掉上次的选中状态

clearSelection();

// 开启一个Fragment事务

FragmentTransaction transaction = fragmentManager.beginTransaction();

// 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况

hideFragments(transaction);

switch (index) {

case 0:

// 当点击了主页tab时,改变控件的图片和文字颜色

mainImage.setImageResource(R.drawable.main_tab1);

mainText.setTextColor(Color.parseColor("#0079FF"));

if (mainFragment == null) {

// 如果MessageFragment为空,则创建一个并添加到界面上

mainFragment = new Main();

transaction.add(R.id.content, mainFragment);

} else {

// 如果mainFragment不为空,则直接将它显示出来

transaction.show(mainFragment);

}

break;

case 1:

// 当点击了导航tab时,改变控件的图片和文字颜色

navigationImage.setImageResource(R.drawable.navigation_tab1);

navigationText.setTextColor(Color.BLUE);

if (navigationFragment == null) {

// 如果navigationFragment为空,则创建一个并添加到界面上

navigationFragment = new Navigation();

transaction.add(R.id.content, navigationFragment);

} else {

// 如果navigationFragment不为空,则直接将它显示出来

transaction.show(navigationFragment);

}

break;

case 2:

// 当点击了更多tab时,改变控件的图片和文字颜色

moreImage.setImageResource(R.drawable.more_tab1);

moreText.setTextColor(Color.BLUE);

if (moreFragment == null) {

// 如果moreFragment为空,则创建一个并添加到界面上

moreFragment = new More();

transaction.add(R.id.content, moreFragment);

} else {

// 如果moreFragment不为空,则直接将它显示出来

transaction.show(moreFragment);

}

break;

}

transaction.commit();

}

/**

* 清除掉所有的选中状态。

*/

private void clearSelection() {

mainImage.setImageResource(R.drawable.main_tab2);

mainText.setTextColor(Color.parseColor("#929598"));

navigationImage.setImageResource(R.drawable.navigation_tab2);

navigationText.setTextColor(Color.parseColor("#929598"));

moreImage.setImageResource(R.drawable.more_tab2);

moreText.setTextColor(Color.parseColor("#929598"));

}

/**

* 将所有的Fragment都置为隐藏状态。

*

* @param transaction 用于对Fragment执行操作的事务

*/

private void hideFragments(FragmentTransaction transaction) {

if (mainFragment != null) {

transaction.hide(mainFragment);

}

if (navigationFragment != null) {

transaction.hide(navigationFragment);

}

if (moreFragment != null) {

transaction.hide(moreFragment);

}

}

}

在本案例中一共提供了三个Fragment,分别是Main(mainFragment)、Navigation(navigationFragment)、More(moreFragment),这三个Fragment是虚构对象,具体代码未给出,这里只是用来说Activity内如何操作Fragment。实际上通过以上代码可以看出Fragment实现选项切换是通过FragmentTransaction来实现的,即由核心方法setTabSelection来实现。

微信公众号:书客创作

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐