android: 碎片的demo
现在你已经将关于碎片的重要知识点都掌握得差不多了,不过在灵活运用方面可能还有 些欠缺,因此又该进入我们本章的最佳实践环节了。
前面有提到过,碎片很多时候都是在平板开发当中使用的,主要是为了解决屏幕空间不 能充分利用的问题。那是不是就表明,我们开发的程序都需要提供一个手机版和一个 Pad 版 呢?确实有不少公司都是这么做的,但是这样会浪费很多的人力物力。因为维护两个版本的 代码成本很高,每当增加什么新功能时,需要在两份代码里各写一遍,每当发现一个 bug 时, 需要在两份代码里各修改一次。因此今天我们最佳实践的内容就是,教你如何编写同时兼容 手机和平板的应用程序。
还记得在本章开始的时候提到过的一个新闻应用吗?现在我们就将运用本章中所学的 知识来编写一个简易版的新闻应用,并且要求它是可以同时兼容手机和平板的。新建好一个 FragmentBestPractice 项目,然后开始动手吧!
第一步我们要先准备好一个新闻的实体类,新建类 News,代码如下所示:
public class News { private String title; private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
News 类的代码还是比较简单的,title 字段表示新闻标题,content 字段表示新闻内容。 接着新建一个 news_item.xml 布局,用于作为新闻列表中子项的布局:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:id="@+id/news_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true" android:ellipsize="end"
android:textSize="18sp" android:paddingLeft="10dp"
android:paddingRight="10dp" android:paddingTop="15dp"
android:paddingBottom="15dp"
/>
</LinearLayout>
这段代码也非常简单,只是在 LinearLayout 中放入了一个 TextView 用于显示新闻的标
题。仔细观察 TextView,你会发现其中有几个属性是我们之前没有学过的。android:padding 表示给控件的周围加上补白,这样不至于让文本内容会紧靠在边缘上。android:singleLine 设 置为 true 表示让这个 TextView 只能单行显示。android:ellipsize 用于设定当文本内容超出控 件宽度时,文本的缩略方式,这里指定成 end 表示在尾部进行缩略。
接下来需要创建新闻列表的适配器,让这个适配器继承自 ArrayAdapter,并将泛型指定 为 News 类。新建类 NewsAdapter,代码如下所示:
public class NewsAdapter extends ArrayAdapter<News> {
private int resourceId;
public NewsAdapter(Context context,
int textViewResourceId, List<News>
objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) { News news
= getItem(position);
View view;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
} else {
view = convertView;
}
TextView newsTitleText = (TextView) view.findViewById(R.id.news_title);
newsTitleText.setText(news.getTitle());
return view;
}
}
可以看到,在 getView()方法中,我们获取到了相应位置上的 News 类,并让新闻的标题 在列表中进行显示。
这样基本就把新闻列表部分的代码编写完了,接下来我们看一下如何编写新闻内容部分
的代码。新建布局文件 news_content_frag.xml,代码如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/visibility_layout" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible" >
<TextView
android:id="@+id/news_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" android:padding="10dp"
android:textSize="20sp" />
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp" android:scaleType="fitXY"
android:src="@drawable/spilt_line" />
<TextView
android:id="@+id/news_content" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_weight="1"
android:padding="15dp" android:textSize="18sp" />
</LinearLayout>
<ImageView
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true" android:scaleType="fitXY"
android:src="@drawable/spilt_line_vertical" />
</RelativeLayout>
新闻内容的布局主要可以分为两个部分,头部显示完整的新闻标题,正文部分显示新闻
内容,中间使用一条细线分隔开。这里的细线是利用 ImageView 显示了一张很窄的图片来实
现的,将 ImageView 的 android:scaleType 属性设置为 fitXY,表示让这张图片填充满整个控 件的大小。
然后再新建一个 NewsContentFragment 类,继承自 Fragment,代码如下所示:
public class NewsContentFragment extends Fragment {
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.news_content_frag, container, false);
return view;
}
public void refresh(String newsTitle, String newsContent) {
View visibilityLayout = view.findViewById(R.id.visibility_layout);
visibilityLayout.setVisibility(View.VISIBLE);
TextView newsTitleText = (TextView) view.findViewById (R.id.news_title);
TextView newsContentText = (TextView) view.findViewById(R.id.news_
content);
newsTitleText.setText(newsTitle); // 刷新新闻的标题
newsContentText.setText(newsContent); //
刷新新闻的内容
}
}
首先在 onCreateView()方法里加载了我们刚刚创建的 news_content_frag 布局,这个没什
么好解释的。接下来又提供了一个 refresh()方法,这个方法就是用于将新闻的标题和内容显 示在界面上的。可以看到,这里通过 findViewById()方法分别获取到新闻的标题和内容控件,
然后将方法传递进来的参数设置进去。
接着要创建一个在活动中使用的新闻内容布局,新建 news_content.xml,代码如下所示:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="@+id/news_content_fragment" android:name="com.example.fragmentbestpractice.NewsContentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
这里我们充分发挥了代码的复用性,直接在布局中引入了 NewsContentFragment,这样 也就相当于把 news_content_frag 布局的内容自动加了进来。
然后新建 NewsContentActivity,作为显示新闻内容的活动,代码如下所示:
public class NewsContentActivity extends Activity {
public static void
actionStart(Context context, String newsTitle, String newsContent) {
Intent intent = new Intent(context,
NewsContentActivity.class); intent.putExtra("news_title", newsTitle);
intent.putExtra("news_content", newsContent);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle
savedInstanceState) { super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.news_content);
String newsTitle =
getIntent().getStringExtra("news_title");
// 获取传入的新闻标题
String newsContent = getIntent().getStringExtra("news_content");
// 获取传入的新闻内容
NewsContentFragment newsContentFragment = (NewsContentFragment)
getFragmentManager()
.findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(newsTitle, newsContent);
// 刷新NewsContentFragment界面
}
}
可以看到,在 onCreate()方法中我们通过 Intent 获取到了传入的新闻标题和新闻内容,
然后调用 FragmentManager 的 findFragmentById()方法得到了 NewsContentFragment 的实例, 接着调用它的 refresh()方法,并将新闻的标题和内容传入,就可以把这些数据显示出来了。 注意这里我们还提供了一个 actionStart()方法,还记得它的作用吗?如果忘记的话就再去阅 读一遍 2.6.3 节吧。
接下来还需要再创建一个用于显示新闻列表的布局,新建 news_title_frag.xml,代码如 下所示:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ListView
android:id="@+id/news_title_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
这个布局的代码就非常简单了,里面只有一个 ListView。不过想必你已经猜到了,这个 布局并不是给活动使用的,而是给碎片使用的,因此我们还需要创建一个碎片来加载这个布 局。新建一个 NewsTitleFragment 类,继承自 Fragment,代码如下所示:
public class NewsTitleFragment
extends Fragment implements
OnItemClickListener {
private ListView newsTitleListView;
private List<News> newsList; private
NewsAdapter adapter; private boolean isTwoPane;
@Override
public void
onAttach(Activity activity) {
super.onAttach(activity);
newsList = getNews(); // 初始化新闻数据
adapter = new NewsAdapter(activity, R.layout.news_item, newsList);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.news_title_frag, container, false);
newsTitleListView = (ListView)
view.findViewById(R.id.news_title_
list_view);
newsTitleListView.setAdapter(adapter);
newsTitleListView.setOnItemClickListener(this);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getActivity().findViewById(R.id.news_content_layout) != null) {
isTwoPane = true; // 可以找到news_content_layout布局时,为双页模式
} else {
isTwoPane = false; // 找不到news_content_layout布局时,为单页模式
}
}
@Override
public void
onItemClick(AdapterView<?> parent, View
view, int position, long id) {
News news = newsList.get(position);
if (isTwoPane) {
// 如果是双页模式,则刷新NewsContentFragment中的内容
NewsContentFragment newsContentFragment
= (NewsContentFragment)
getFragmentManager().findFragmentById(R.id.news_
content_fragment);
newsContentFragment.refresh(news.getTitle(), news.getContent());
} else {
// 如果是单页模式,则直接启动NewsContentActivity
NewsContentActivity.actionStart(getActivity(), news.getTitle(),
news.getContent());
}
}
private List<News>
getNews() {
List<News> newsList = new
ArrayList<News>(); News news1 = new News();
news1.setTitle("Succeed in College as a Learning Disabled Student");
news1.setContent("College freshmen will soon learn to live with a
roommate, adjust to a new social scene
and survive less-than-stellar dining hall
food. Students with
learning disabilities will
face these transitions while
also grappling with a few more hurdles."); newsList.add(news1);
News news2 = new News();
news2.setTitle("Google Android exec
poached by China's Xiaomi"); news2.setContent("China's Xiaomi
has poached a key Google
executive involved in the
tech giant's Android
phones, in a move seen
as a coup for the rapidly growing Chinese smartphone maker.");
newsList.add(news2);
return newsList;
}
}
这个类的代码有点长,我来重点解释一下。根据碎片的生命周期,我们知道,onAttach()
方法会首先执行,因此在这里做了一些数据初始化的操作,比如调用 getNews()方法获取几 条模拟的新闻数据,以及完成 NewsAdapter 的创建。然后在
onCreateView()方法中加载了 news_title_frag 布局,并给新闻列表的 ListView 注册了点击事件。接下来在 onActivityCreated()
方法中,我们通过是否能够找到一个 id
为 news_content_layout
的 View 来判断当前是双页 模式还是单页模式,这个 id
为 news_content_layout
的 View 只在双页模式中才会出现,在 稍后的布局里你将会看到。然后在 ListView 的点击事件里我们就可以判断,如果当前是单 页模式,就启动一个新的活动去显示新闻内容,如果当前是双页模式,就更新新闻内容碎 片里的数据。
剩下工作就非常简单了,修改 activity_main.xml 中的代码,如下所示:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/news_title_fragment"
android:name="com.example.fragmentbestpractice.NewsTitleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
上述代码表示,在单页模式下,只会加载一个新闻标题的碎片。然后新建 layout-sw600dp
文件夹,在这个文件夹下再新建一个 activity_main.xml 文件,代码如下所示:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/news_title_fragment"
android:name="com.example.fragmentbestpractice.NewsTitleFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="@+id/news_content_layout"
android:layout_width="0dp" android:layout_height="match_parent"
android:layout_weight="3" >
<fragment
android:id="@+id/news_content_fragment"
android:name="com.example.fragmentbestpractice.
NewsContentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
可以看出,在双页模式下我们同时引入了两个碎片,并将新闻内容的碎片放在了一个 FrameLayout 布局下,而这个布局的 id
正是 news_content_layout。因此,能够找到这个 id
的 时候就是双页模式,否则就是单面模式。
最后再将 MainActivity 稍作修改,把标题栏去除掉,代码如下所示:
public class MainActivity extends Activity {
@Override
protected void
onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
}
这样我们所有的编写工作就已经完成了,赶快来运行一下吧!首先在手机模拟器上运行, 效果如图 4.15 所示。

图 4.15
可以看到两条新闻的标题,并且超出屏幕部分的文字是在尾部使用省略号代替的。
然后点击第二条新闻,会启动一个新的活动来显示新闻的内容,效果如图 4.16 所示。

图 4.16
接下来将程序在平板模拟器上运行,同样点击第二条新闻,效果如图 4.17 所示。

图 4.17
android: 碎片的demo的更多相关文章
- TensorFlow 在android上的Demo(1)
转载时请注明出处: 修雨轩陈 系统环境说明: ------------------------------------ 操作系统 : ubunt 14.03 _ x86_64 操作系统 内存: 8GB ...
- 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
腾讯优测是专业的android自动化测试平台,拥有上千款真机,彻底解决android碎片化问题! 这里我要说的不是闪光灯的硬件特征,也不是说底层驱动的原理,我只是跟大家聊一聊在项目中遇到的一些关于闪光 ...
- Android学习小Demo(19)利用Loader来实时接收短信
之前写过一篇文章<Android学习小Demo(13)Android中关于ContentObserver的使用>,在里面利用ContentOberver去监測短信URI内容的变化.我们先来 ...
- android JNI 简单demo(2)它JNI demo 写
android JNI 简单demo(2)它JNI demo 写 一.搭建Cygwin 环境:http://blog.csdn.net/androidolblog/article/details/25 ...
- Android组件化demo实现以及遇坑分享
首先贴出demo的github地址:GitHub - TenzLiu/TenzModuleDemo: android组件化demo 作者:TenzLiu原文链接:https://www.jianshu ...
- 【Android】打电话Demo及Android6.0的运行时权限
新手开局,查看一些旧资料,从打电话.发短信的小应用开始.代码很简单,主要是学习了: 用StartActivity()激活一个Activity组件.这里是激活了系统原生的打电话和发短信Activity. ...
- QT 5.4.1 for Android Ubuntu QtWebView Demo
QT 5.4.1 for Android Ubuntu QtWebView Demo 2015-5-15 目录 一.说明: 二.参考文章: 三.QtWebView Demo在哪里? 四.Qt Crea ...
- Android碎片(Fragment)简述
碎片(Fragment)是一种可以嵌入活动当中的UI片段,它能让程序更加合理和充分地利用大屏幕的空间,因此碎片在平板上的应用非常广泛. 你可以将碎片理解成一个迷你型的活动,水平同样可能包含布局,同样都 ...
- Android ListFragment实例Demo(自己定义适配器)
上一篇文章介绍了ListFragment,当中的ListView并没有自己定义适配器,实际上在实际开发中常会用到自己定义适配器,是实现更复杂的列表数据展示. 所以这篇文章添加了自己定义适配器.来进行L ...
随机推荐
- python 运行日志logging代替方案
以下是自己写的 记录日志的代码.(和logging不搭嘎,如果如要学loggging模块,本文末尾有他人的链接.) # prtlog.py ############################## ...
- 【前端】三个bug
目录 一.Array对象的indexOf() 二.使用jquery,clone()下拉框问题 三.jquery获取获取html5的data-*属性 一.Array对象的indexOf() 1.inde ...
- OCM_第三天课程:Section1 —》表空间的操作和管理、服务配置
注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...
- 关于java中Stream理解
关于java中Stream理解 Stream是什么 Stream:Java 8新增的接口,Stream可以认为是一个高级版本的Iterator.它代表着数据流,流中的数据元素的数量可以是有限的, 也可 ...
- Codeforces 407B Long Path(好题 DP+思维)
题目链接:http://codeforces.com/problemset/problem/407/B 题目大意:一共n+1个房间,一个人从1走到n+1,每次经过房间都会留下一个标记,每个房间有两扇门 ...
- 性能测试四:jmeter进阶之逻辑控制器
常用的逻辑控制器 1,循环控制器:可以设置该控制器内的sampler执行的次数,循环次数与线程的循环次数各自独立 2,if控制器:根据判断条件决定是否执行该控制器内的请求,如果是字符串比较条件,参数和 ...
- 字节、字、bit、byte的关系【转】
字 word 字节 byte 位 bit 字长是指字的长度 1字=2字节(1 word = 2 byte) 1字节=8位(1 byte = 8bit) 一个字的字长为16 一个字节的字长是8 bps ...
- Android Rom build.prop文件详解
# begin build properties # autogenerated by buildinfo.sh #以下内容由脚本在编译时自动产生 ro.build.id=6.7.7_97 ...
- HDU 3032 (SG打表找规律)
题意: 有n堆石子,alice先取,每次可以选择拿走一堆石子中的1~x(该堆石子总数) ,也可以选择将这堆石子分成任意的两堆.alice与bob轮流取,取走最后一个石子的人胜利. 思路: 因为数的范围 ...
- hdu 2197 求长度为n的本原串 (快速幂+map)
Problem Description由0和1组成的串中,不能表示为由几个相同的较小的串连接成的串,称为本原串,有多少个长为n(n<=100000000)的本原串?答案mod2008.例如,10 ...