上一篇把左侧碎片的RecyclerView的部分完成啦,这一部分就是使用限定符兼容手机平板的重头戏啦。
*********************************************************
继续来看图示:
一、单页模式:
上一篇中,我们为了查看RecyclerView的效果,已经将左侧碎片LeftTitleFragment添加到MainActivity中啦。那么现在,我们也可以同样地将右侧碎片RightDetailFragment添加到一个Activity中。新建DetailContentActivity和activity_detail,加入以下代码:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<fragment
android:id="@+id/fragment_page_detail"
android:name="com.example.tahlia.newsclient_2.RightDetailFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
}
}
这里我们新建了一个Activity,当然不能忘记去AndroidMainfest文件中注册这个活动了!在AndoridManifest文件中已有的<activity>标签下方再添加一行代码:
<activity android:name=".DetailActivity"/>
注册完成。
在单页模式下,我们要完成从标题页Activity到详情页Activity的跳转。为了能统一启动跳转的代码和传递的数据格式,添加一个actionStart()方法。这个方法添加在MainActivity或者DetailActivity都可以,但是在使用的时候,单页模式下两个Activity都用到,而双页模式下DetailActiviy完全不出现,也就意味着不需要用到actionStart()这个方法。为了代码的清爽,我们将这个方法添加到DetailActivity中。
public static void actionStart(Context context, String title, String content){
Intent intent = new Intent(context, DetailActivity.class);
intent.putExtra("news_title", title);
intent.putExtra("news_content", content);
context.startActivity(intent);
}
修改跳转事件(LeftTitleFragment-NewsAdapter-OnCreatViewHolder中):
@Override
public void onClick(View v) {
News news = newsList.get(holder.getAdapterPosition());
DetailActivity.actionStart(getActivity(), news.getTitle(), news.getContent());
}
跳转页面的同时,我们使用了intent进行传递数据,把title和content也一起传递过去了。在DetailActivity中我们应该把它取出来,然后更新显示。对于单页模式和双页模式来说,更新都是右侧详情碎片所需要的功能,因此在RightDetailFragment中添加一个refresh()方法用来更新页面数据:
public class RightDetailFragment extends Fragment {
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.right_detail_fragment, container, false);
return view;
}
public void refresh(String title, String content){
TextView newsTitle = (TextView) view.findViewById(R.id.text_detail_title);
TextView newsContent = (TextView) view.findViewById(R.id.text_detail_content);
newsTitle.setText(title);
newsContent.setText(content);
}
}
这里要注意的是,Fragment中要通过findViewById去获取控件实例,是需要通过activity中加载的布局去拿到的,也就是需要一个view,而在OnCreatView中我们已经有一个view了。我们可以将view的定义放在类之中,令整个类的方法都可以使用到view这个变量,以便于我们refresh方法的使用。下一步就是单页跳转之后数据的传递和更新了。
在获得Intent包含的数据后,调用refresh对DetailActivity中的数据进行更新显示。修改DetailActivity中的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
String title = getIntent().getStringExtra("news_title");
String content = getIntent().getStringExtra("news_content");
RightDetailFragment detailFragment = (RightDetailFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_page_detail);
detailFragment.refresh(title, content);
}
完成。运行看看单页跳转效果如何?
嗯单页已经成功啦!
二、双页模式
双页模式是我们留给平板之类的屏幕比较大的设备使用的。在这个模式里,使用最小宽度限定符指定最小值作为两个屏幕尺寸加载页面的区分。
在res目录下新建layout-sw600dp文件夹,然后新建activity_main.xml,将做好的两个碎片都加载进来。这里要注意,左侧碎片的id与右侧碎片id要和之前单页模式的id一致。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/fragment_page_title"
android:name="com.example.tahlia.newsclient_2.LeftTitleFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2">
<fragment
android:id="@+id/fragment_page_detail"
android:name="com.example.tahlia.newsclient_2.RightDetailFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
新建完成后,考虑到点击页面的RecyclerView触发的效果是不一样的(单页模式是启动一个新的Activity,双页模式是直接刷新右侧碎片内容),因此要新建一个布尔变量去判断到底是单页模式还是双页模式,以进行不同的触发操作。
在LeftTitleFragment中,我们新建一个布尔变量isTwoPage,然后重写OnActivityCreate如下:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getFragmentManager().findFragmentById(R.id.fragment_page_detail) != null){
isTwoPage = true;
}else{
isTwoPage = false;
}
}
※OnCreatActivity方法是当和碎片相关联的活动一定创建好的时候调用的一个函数。在确保活动创建完成的时候,我们能够保证当前活动已经确定好了使用哪个布局。此时在布局中寻找id为fragment_page_detail(右侧碎片),如果当前活动中包含了右侧碎片,则说明加载的是双页模式,isTwoPage为true;当前布局不包含右侧碎片,则说明加载的是单页模式,isTwoPage为false。
判断完成后,也要修改RecyclerView子项的点击触发事件。修改如下:
holder.item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
News news = newsList.get(holder.getAdapterPosition());
if (isTwoPage){
RightDetailFragment rightDetailFragment = (RightDetailFragment) getFragmentManager().findFragmentById(R.id.fragment_page_detail);
rightDetailFragment.refresh(news.getTitle(), news.getContent());
}else{
DetailActivity.actionStart(getActivity(), news.getTitle(), news.getContent());
}
}
});
修改完成。大体上所有功能都完成啦!运行一下看看结果:
嗯,基本样式已经完成啦!
当然还有一些小问题没有处理好,比如说两个Fragment之间的分隔线不知道为什么没有显示出来,还有双页模式下右侧碎片的初始状态等等。但是现在已经解决了大部分问题啦。这些小问题就交给下一次优化的时候再解决吧!