在Android上实现Master/Detail Flow

  Master/Detail Flow包含Master和Detail两个页面,Master页面显示包含了若干项目(item)的列表,给出各个项目的大概信息。当点击某个项目时,包含了该项目详细信息的Detail页面会显示出来。这种模式的一个优势在于,可以方便地适配不同的屏幕尺寸:手机屏幕尺寸有限,一般一次只能展示一个页面,那么首先显示Master,当用户点击感兴趣的项目时,再将该项目的Detail显示出来;而平板电脑的屏幕尺寸比较大,可以将Master和Detail并排显示,避免显示空间的浪费。

  在Android上实现Master/Detail Flow十分方便,新版本的Android Studio已经自带了Master/Detail Flow的模板。下面通过一个例子介绍Master/Detail Flow的基本实现方法。例子从TMDb上获取一系列电影信息,在Master页面由RecyclerView以网格的形式显示出来,当点击了某一个电影之后,显示包含了该电影详细信息的Detail页面。从TMDb获取电影信息的方法可参考Retrofit使用方法举例,RecyclerView的使用方法可参考RecyclerView使用方法举例(1)RecyclerView使用方法举例(2)

  最终实现效果如下:

1. 页面层级和布局

1.1. Detail Activity布局

  首先进行Detail页面的布局,Detail页面在小屏幕上会覆盖Master页面显示,在大屏幕上会和Master页面并排显示,无论如何显示,Detail页面本身的布局是不变的。Detail Acitvity的布局层级如下:

其中 movie_detail_container 用于盛放Detail Fragment。注意这里在CollapsingToolbarLayout里面放了一个ImageView,用来显示一张电影图片。

【完整代码】

1.2. Detail Fragment布局

  Detail Fragment用来显示电影的详细信息,完整代码参考这里

1.3. Master Activity布局

  在Master页面中加入一个FrameLayout,其中include了 movie_grid :

【完整代码】

  上面的 movie_grid 是实现Master/Detail Flow布局自动适配屏幕尺寸的关键,在/res/layout/movie_grid.xml中,布局只有MovieGridFragment,即Master页面的Fragment,此时屏幕中只显示Master页面,适用于较小的屏幕:

【完整代码】

  此外在res/layout/movie_grid_twopanes.xml中,给出Master和Detail并列显示的布局, movie_detail_container 用于盛放Detail Fragment,适用于较大的屏幕:

【完整代码】

  最后在res/values-sw600dp/refs.xml中,以别名的形式,为最小屏幕宽度为600dp的设备适配Master和Detail并列显示的布局,即movie_grid_twopanes.xml。

【完整代码】

1.4. Master Fragment布局

  Master Fragment包含一个RecyclerView,用于以网格的形式显示电影。

【完整代码】

2. Master/Detail的切换

2.1. 判断当前布局类型

Master/Detail模式在不同屏幕尺寸的设备上具有不同的界面布局,首先需要获取当前的布局类型,以此来决定Detail Activity的显示逻辑。

  由前面Master Activity的布局可见,小屏幕和大屏幕设备布局的区别,在于 movie_detail_container 的位置。小屏幕设备使用/res/layout/movie_grid.xml,其中没有 movie_detail_container , movie_detail_container 位于Detail Activity的布局里。大屏幕设备使用res/layout/movie_grid_twopanes.xml,里面有 movie_detail_container ,可以直接将Detail Fragment添加进去。通过检查 movie_detail_container 是否存在,可以判断当前的布局类型。在Master Activity中加入:

其中 mTwoPane 用于指示当前布局类型。

【完整代码】

2.2. Detail页面的显示

当用户点击Master页面的电影时,将出现包含该电影详细信息的Detail页面。根据当前布局类型的不同,选择显示Detail Activity覆盖Master Activity(小尺寸屏幕),或者直接将Detail Fragment添加到Master页面旁边(大尺寸屏幕)。

2.1.1. 为RecyclerView Adapter添加OnClickListener

  首先要让RecyclerView能够支持点击事件,在RecyclerView Adapter中加入:

之后就可以使用 setOnItemClickListener() 来添加点击事件监听。

【完整代码】

2.2.2. 传递点击事件到Master Activity

  显示电影列表的RecyclerView位图Master Fragment,当点击事件发生时,Master Fragment将此事件传递给Master Activity,由Master Activity根据当前布局类型 mTwoPane 决定应当如何显示Detail页面。

  在Master Fragment中添加接口用于回调,Master Activity应实现该接口,然后在 onAttach() 的时候从Master Activity中获取回调方法:

  在点击事件发生时,调用该回调方法:

【完整代码】

2.2.3. 在Master Activity处理点击事件并显示Detail页面

  Master Activity实现Master Fragment定义的回调接口,当用户点击RecyclerView中的电影时,Master Fragment通过回调方法通知Master Activity。

mTwoPane 为true时,当前为大屏的双栏模式,直接将Detail Fragment添加到 movie_detail_container 里面;当 mTwoPane 为false时,当前为小屏,显示Detail Activity。

【完整代码】

3. 完整代码

  完整代码可以参考这里

 

 

 

2 Comments

  1. Zaki

    Thank you very much for the tutorial 🙂

    can you do more tutorial in changing the sorting data from SORT_BY_POPULARITY_DESC to SORT_BY_VOTE_AVERAGE_DESC by using button or popup menu?

    1. nex3z (Post author)

      Hi Zaki, I’ve added a popup menu for sort options. Check it out at here.
      You can also find the code here.

Comments are closed.