Android在3.0之后引入了Fragment的概念,我猜测其想法可能只是想更好地兼容大屏幕或者平板的开发,因为大屏幕可以展示更多的内容,而内容一多,逻辑有可能就乱,而利用Fragment,则可以将不同的逻辑封装进不同的Fragment中,但是展现呢,还是在同一个Activity中,在同一个屏幕上显示。而对于屏幕并不大的手机来说,如果一个页面展示的东西并不多,那么其实将逻辑直接写在Activity,利用多个Activity实现多个页面的展示,我觉得也是可以接受的,毕竟用Activity还是用Fragment只是一种手段的选择,能够帮助我们解决问题就好,没有什么是一定的。
但是既然Google那么推荐我们用Fragment,连ADT中默认的创建Activity都会帮我们把实现放到Fragment中,那说明在后面,某些我们不清楚的地方,fragment肯定是有着activity没有的优势的,即使Fragment在Fragment之间的跳转和传值是比较麻烦的,我们都要学习一下怎么使用Fragment。
今天这篇博文我们就来学习一下如何使用Fragment,并且直接在Fragment中触发跳到另一个Fragment中。
1)定义一个Activity:activity_main.xml,内容很简单,就是放置一个FrameLayout作为Container,如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.lms.fmdemo.MainActivity" tools:ignore="MergeRootFrame" />
2)定义三个Fragment的布局,如下:
2.1)fragment_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.lms.fmdemo.MainActivity$PlaceholderFragment" > <Button android:id="@+id/btnMain" android:layout_width="200dp" android:layout_height="50dp" android:layout_centerInParent="true" android:text="@string/main_fragment" /> </RelativeLayout>
2.2)fragment_sec.xml 和 fragment_third.xml都跟fragment_main.xml类似,中间只放置一个按钮。
这三个布局呢,当我们点击Main的按钮时,会跳到第二个Fragment,当我们点击第二个Fragment中的按钮时,就会跳到第三个Fragment,简单实在。
3)创建三个Fragment实例,分别对应上面的三个布局,我们就拿第一个MainFragment来讲解一下。
public class MainFragment extends Fragment implements OnClickListener{ public interface MainFragmentClickListener{ public void onMainButtonClicked(); } private MainFragmentClickListener mActionTaker; public MainFragment() { } public void onAttach(Activity activity) { super.onAttach(activity); try { mActionTaker = (MainFragmentClickListener) activity; } catch (Exception e) { throw new RuntimeException(activity.toString() + " must implements MainFragmentClickListener Inerface"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); Button btnMain = (Button) rootView.findViewById(R.id.btnMain); btnMain.setOnClickListener(this); return rootView; } @Override public void onClick(View arg0) { mActionTaker.onMainButtonClicked(); } }
3.1)创建的MainFragment要继承于Fragment(注意,为了兼容2.x的系统,这里要使用support.v4包里面的fragment类)。
3.2)定义一个回调接口,且这个接口必须要被包含此Fragment的Activity实现。Fragment之间是没有办法互相跳转的,它们之间所谓的跳转操作其实是由FragmentManager在主Activity中的添加替换删除等操作组成的,也就是说,其实它们是被操作的,所以如果想在Fragment中触发跳转的操作的话,就必须将这个跳转事件让Activity知道,由Activity来操作。
3.3)在onAttach方法中,将Activity给强制转换成第二步实现的接口,如果有异常,说明Activity没有实现此接口,则会报错。这一步,只是为了确保主Activity有实现这个接口,当然,也可以在这里获取一个Activity对象,供后面利用。
3.4)定义onCreateView方法,在onCreateView方法中,实始化当前Fragment的布局,并为不同的控件设置不同的响应函数等之类。在这个例子中,我们只是简单设置了一个按钮。
3.5)在按钮的响应函数中,由于只有一个按钮有这个响应函数,所以在这里并不判断控件的id,直接调用第二步定义接口的回调函数,即Activity会处理这个响应函数。
一个Fragment主要的实现框架基本上就是这样,在本页面上的逻辑,基本上就跟普通的Activity一样,可以直接处理。只有当涉及到其他的页面(Fragment)的时候,我们才需要利用回调接口,来实现过渡。有可能是本个Fragment会被替换成另外一个Fragment,而这只能由Activity做,没办法自杀的。
4)在Activity中加载我们定义的Fragment,并且处理对应Fragment的接口函数,如下:
public class MainActivity extends ActionBarActivity implements MainFragmentClickListener, SecondFragmentClickListener{ private FragmentManager fragmentManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); fragmentManager = getSupportFragmentManager(); if (savedInstanceState == null) { fragmentManager.beginTransaction().add(R.id.container, new MainFragment()).commit(); } } ... @Override public void onMainButtonClicked() { fragmentManager.beginTransaction().replace(R.id.container, new SecondFragment()).addToBackStack(null).commit(); } @Override public void onSecondButtonClicked() { fragmentManager.beginTransaction().replace(R.id.container, new ThirdFragment()).addToBackStack(null).commit(); }
在上面的Activity中,实现了MainFragmentClickListener和SecondFragmentClickListener,分别是两个Fragment中定义的接口,而在其对应的实现方法,我们只是简单地将一个新的Fragment放到Container中去,
如 onMainButtonClicked,在此方法,我们利用FragmentManager.beginTransaction方法获得Transaction对象,然后调用其replace方法,将SecondFragment替换掉原来在onCreate时加载的MainFragment对象,最后 commit。
综合来看,Activity的逻辑是最简单的,可以说,它没有什么业务相关的逻辑,所有业务相关的逻辑应该都在对应的Fragment中实现,而Activity只是负责不同的Fragment之间的切换。
到这里,在Activity中利用Fragment来实现App页面之间跳转就基本实现了。而这跟普通的app,利用Activity来实现页面跳转,其实架构基本上是一样的,下面就是其运行效果:
结束。源代码下载!