最近做项目要用到公告系统,不用想,肯定要用到Fragment碎片。但Fragment是Android3.0(API Level 11)才开始引入的,而我们写的项目最低版本是Android2.3(API Level 9),最蛋疼的就是你要为这大约7%(截止到2015年2月)的用户考虑,不能直接用android.app.Fragment。谷歌也没办法,总不能让android3.0以下的用户用不了fragment吧,如果强迫用户去更新系统或硬件那肯定会被骂死的,所以google那些大神们就写了兼容低版本的Fragment并放在android.support.v4.jar兼容包中。
我没注意到xml文件中不能使用<fragment>节点,因为前面提到了:Fragment是Android3.0(API Level 11)才开始引入的,我的项目最小版本是Android2.3(API Level 9),编译版本是Android4.0(API Level 14)。所以就出现了下面这样的错误:
...
android.view.InflateException: Binary XML file line #9: Error inflating class fragment
...
Caused by: android.app.Fragment$InstantiationException: Trying to instantiate a class cn.smc.notice.NoticeListFragment that is not a Fragment
...
第一个错误信息还阔以理解:xml文件中的<fragment>节点默认是使用android.app.Fragment中的Fragment,而Fragment类是继承自android.support.v4.app.Fragment中的Fragment,所以会实例化失败。但第二个我第一次见到就懵了:它竟敢说我的NoticeListFragment不是一个Fragment,我都继承了Fragment你还说我不是一个Fragment?不过现在看来就不难理解了,原来这是两个不同包中的Fragment类,不可以互用。
可是,就在刚刚我再次运行时竟然发现竟然奇迹般的可以运行了,也不报错。我啥也没干啊,他不崩溃我可就崩溃了。哪位大神知道可以跟我解释一下。
所以要保证所有的关于Fragment的相关引入和类引用都是来自Android支持包,就只能在Java代码中动态加载Fragment了。
关于Fragment新闻的例子网上和很多Android书上都有,这里就不细讲了,他们一般都是在xml文件中设置<fragment>节点实现的,我这里是动态加载fragment。
原理:
NoticeActivity:公告Activity
NoticeContentActivity:公告内容Activity
NoticeListFragment:公告列表Fragment
NoticeContentFragment:公告内容Fragment
所以,为了同时适应手机和平板,需要两个activity(包含三个布局文件)、两个Fragment(包含两个布局文件)来实现。
目录结构:
关键代码:
NoticeActivity.java:
public class NoticeActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_notice); if (this.findViewById(R.id.fl_notice_list_container) != null) { if (savedInstanceState != null) { return; } NoticeListFragment noticeListFragment = new NoticeListFragment(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.fl_notice_list_container, noticeListFragment); transaction.commit(); if (this.findViewById(R.id.fl_notice_content_container) != null) { Log.e("shang", "big!big!"); NoticeContentFragment noticeContentFragment = new NoticeContentFragment(); FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction(); transaction2.add(R.id.fl_notice_content_container, noticeContentFragment); transaction2.commit(); } } } }
public class NoticeContentActivity extends FragmentActivity { public static NoticeContentFragment noticeContentFragment; public static void actionStart(Context context, String title, String author, String publishTime, String content) { Intent intent = new Intent(context, NoticeContentActivity.class); intent.putExtra("title", title); intent.putExtra("author", author); intent.putExtra("publishTime", publishTime); intent.putExtra("content", content); context.startActivity(intent); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_notice_content); if (this.findViewById(R.id.fl_notice_content_container) != null) { if (savedInstanceState != null) { return; } noticeContentFragment = new NoticeContentFragment(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.fl_notice_content_container, noticeContentFragment); transaction.commit(); } } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); String title = getIntent().getStringExtra("title"); String author = getIntent().getStringExtra("author"); String publishTime = getIntent().getStringExtra("publishTime"); String content = getIntent().getStringExtra("content"); noticeContentFragment.refresh(title, author, publishTime, content); } }
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater .inflate(R.layout.fragment_notice_list, container, false); lv_notice_list = (ListView) view .findViewById(R.id.lv_notice_list); lv_notice_list.setAdapter(mAdapter); lv_notice_list.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub NoticeBean noticeBean = list_notice.get(position); if (isTwoPane) { NoticeContentFragment noticeContentFragment = (NoticeContentFragment) NoticeListFragment.this.myActivity.getSupportFragmentManager() .findFragmentById(R.id.fl_notice_content_container); noticeContentFragment.refresh(noticeBean.getTitle(),noticeBean.getAuthor(),noticeBean.getPublish_time(),noticeBean.getContent()); } else { NoticeContentActivity.actionStart(getActivity(),noticeBean.getTitle(),noticeBean.getAuthor(),noticeBean.getPublish_time(),noticeBean.getContent()); } } }); return view; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (getActivity().findViewById(R.id.fl_notice_content_container) != null) { isTwoPane = true; } else { isTwoPane = false; } }
源码免费下载:
源码下载