Android 开发 之 Fragment 详解

Android 开发 之 Fragment 详解


作者
 : 韩曙亮

转载请著名出处 : http://blog.youkuaiyun.com/shulianghan/article/details/38064191


本博客代码地址 :

-- 单一 Fragment 示例 : https://github.com/han1202012/Octopus-Fragement.git

-- 可复用的 Fragment 示例 : https://github.com/han1202012/Octopus-Fragement_TwoModel.git


1. Fragement 概述


Fragement 与 Activity 生命周期关系 : Fragement 嵌入到 Activity 组件中才可以使用, 其生命周期与 Activity 生命周期相关.

-- stop 与 destroy 状态 : Activity 暂停 或者 销毁的时候, 其内部嵌入的所有的 Fragement 也会执行 暂停 或者 销毁 操作;

-- 活动状态 : 只有当 Activity 处于活动状态的时候, 我们才能操作 Fragement;


Fragement 特征 :

-- Fragement 与 Activity 交互 : Fragement 调用 getActivity() 获取其 所嵌入的 Activity, Activity 获取 FragementManager 的findFragementById() 或 findFragementByTag()获取 Fragement;

-- Activity 增删 Fragement : Activity 调用 Fragement 的 add()remove()replace()等方法 添加 删除 替换 Fragement;

-- Fragement 与 Activity 对应关系 : 一个 Activity 中可以嵌入多个 Fragement, 一个 Fragement 可以嵌入多个 Activity;

-- 生命周期受 Activity 影响 : Fragement 的生命周期 受 Activity 生命周期控制;


Fragement 作用 : Fragement 是为了 Android 中 平台电脑 UI 设计, 开发者不用设计 非常负责的 界面, 只需要设计好模块, 对UI 组件进行 分组 和 模块化的设计和开发, 简化了 UI 组件;


Fragement 可复用性 : 同一个 app 应用, 可以在不同的 Activity 中加载同一个 Fragement;



2. Fragement 类 和 方法介绍


(1) Fragement 相关类介绍


Fragement 子类 :

-- DialogFragement : 对话框界面的 Fragement, 显示一个浮动的对话框, 这个对话框可以方便的与 Activity 进行交互, Activity 可以管理这个 Fragment;

-- ListFragement : 列表界面的 Fragement, 显示一个条目列表, 该列表可以设置一个适配器, 提供了许多管理 列表的函数;

-- PerformanceFragement : 选项设置界面的 Fragement, 该Fragment 创建 类似与 设置 应用程序时很管用;

-- WebViewFragement : WebView 界面的 Fragement;



(2) Fragement 生命周期相关方法介绍


onCreate() :

?
1
onCreate(Bundle savedInstanceState)

-- 回调时机 : 在创建 Fragement 的时候回调;

-- 参数解析 : Bundle savedInstance, 用于保存 Fragment 参数, Fragement 也可以 重写 onSaveInstanceState(Bundle outState) 方法, 保存Fragement状态;

-- 执行的动作 : 获取 Frgement 显示的内容, 以及启动Fragment 传入的参数, 调用 getArguments() 获取键值对;


onCreateView() :

?
1
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);

-- 回调时机 : Fragement 绘制界面组件 的时候回调, 该方法返回 View, 这个View就是 Fragement 本身;

-- 参数解析 : inflater 布局加载器, 是上下文传入, 不用自己创建; container 加载组件的父容器;

-- 执行的操作 : 使用 inflate 布局加载器 加载布局文件, 并未组件设置显示的值;


onPause() :

-- 回调时机 : Fragement 暂停的时候, 即进入后台的时候 回调;



3. Fragment 创建


Fragment 创建 :

-- 参数准备 : 创建一个 Bundle 对象, 并向其中设置参数 :

?
1
2
Bundle bundle = new Bundle();
bundle.putString( "key" , "value" );
--  创建 Fragment 对象 : 使用 new MyFragment() 创建对象, 并 调用 myFragment.setArguments(bundle) 方法传入参数;

?
1
2
MyFragment myFragment = new MyFragment();
myFragment.setArguments(bundle);


Fragment嵌入Activity方式 : Fragment 添加到 Activity 中才能显示, 以下是将 Fragment 嵌入 Activity 的方式;

-- 布局文件嵌入 : 在布局文件中 使用 元素, 通过定义 android:name = "com.example.MyFragment" 属性指定 Fragment 类;

-- 代码方式嵌入 : 调用 FragmentTransaction 对象的 add() 方法向 Activity 中添加 Fragment;



4. Fragment 与 Activity 通信


Fragment 获取 Activity : 调用 Fragment 对象的 getActivity()方法, 即可获取 Fragment 嵌入的 Activity 对象;


Activity 获取 Fragment :

-- Fragment 属性 : 在布局文件中, 可以为 元素指定 android:id 和 android:tag 属性;

-- 获取方法 : 调用 Activity 的 findFragmentById(int id) 或者 findFragmentByTag(String tag)方法;


Fragment 向 Activity 传递数据 : 将 Activity 当作接口子类对象, Fragment 中调用 Activity 中的接口方法;

-- Fragment 定义接口 : 在 Fragment 内部定义一个 Callback 接口;

-- Activity 实现该接口 : MyActivity extends Activity implement MyFragment.Callback;

-- Fragment 中获取该接口对象 : 在Fragment 中定义一个 Callback 全局变量, 然后在 onAttach(Activity activity) 方法中, 将 activity 强转为 Callback 对象;

-- 调用接口方法 : 上面获取了 Callback 对象, 即Activity对象, 调用 Activity 中的 接口方法, 就能在 Fragment 中调用 Activity 对应的方法了;


Activity 向 Fragment 传递数据 :

-- 创建 Bundle 数据包 : 创建一个 Bundle 对象, 把要存放的键值对 放到这个对象中;

-- 设置 Bundle 对象给 Fragment : 调用 Fragment 对象的 setArguments(Bundle bundle) 方法, 将 Bundle 对象设置给 Fragment;



5. Fragment 事务管理


FragmentManager 功能 : FragmentManager 对象 可以通过 activity.getFragmentManager()获取;

-- 获取指定 Fragment : 通过 findFragmentById() 或者 findFragmentByTag() 方法获取指定 Fragment;

-- 弹出栈 : 通过调用 popBackStack(), 将 Fragment 从后台的 栈 中弹出;

-- 监听栈 : 通过调用 addOnBackStackChangeListener 注册监听器, 监听 后台栈变化;


FragmentTransaction 对象获取途径 :

-- 获取 FragmentManager 对象 : 调用 Activity 的 getFragmentManager() 获取 FragmentManager 对象;

-- 获取 FragmentTansaction 对象 : 调用 FragmentManager 对象的 beginTransaction() 方法获取 FragmentTransaction 对象;


FragmentTransaction(Fragment 事务)作用 : 对 Fragement 进行 增, 删 , 改 操作需要 FragmentTransaction 对象进行操作, 开启 这个事务, 获取 事务对象, 然后执行对 Fragment 的操作, 最后提交事务;

-- 开启事务 : 调用 Fragement 对象的 beginTransaction() 方法可以获取 FragementTransaction 对象;

-- 操作碎片 : FragmentTransaction 对象 中 包含了 add(), remove(), replace() 等方法;

-- 提交操作 : 当执行完 Fragement 的操作之后, 可以调用 FragementTransaction 对象的commit() 方法提交修改;


addToBackStack()方法作用 : 该方法是 FragementTransaction 的方法, 在提交事务前调用该方法, 可以将 事务中执行的操作 添加到 back 栈中, 用户按下 回退键, 修改过的 Fragement 会 回退到 事务执行之前的状态;



6. Fragment 生命周期




(1) Fragment 状态


活动状态 : Fragment 处于前台, 可见可以获取焦点;


暂停状态 : Fragment 嵌入的Activity 也处于暂停状态, 即 Fragment 处于后台, 可见失去焦点;


停止状态 : Fragement 嵌入的 Activity 处于停止状态, 不可见失去焦点;


销毁状态 : Fragement 所在的 Activity 被销毁, 执行了 onDestroy() 方法, 此时 Fragement 被完全删除;



(2) Fragement 生命周期相关方法


\


红色方法 与 Activity 相对应, 蓝色方法 是 自身对应的方法, 棕色方法 单独对应;<喎�"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD48cD48YnIgLz48L3A+PHA+PHN0cm9uZz5vbkF0dGFjaCgpPC9zdHJvbmc+IDogx7bI6ywgRnJhZ2VtZW50ILG7x7bI67W9IEFjdGl2aXR5IMqxu9i197jDt723qCwg1ru74bX308PSu7TOOzwvcD48cD48YnIgLz48L3A+PHA+PHN0cm9uZz5vbkNyZWF0ZSgpIDwvc3Ryb25nPjogtLS9qCwgRnJhZ2VtZW50ILS0vai1xMqxuvK72LX3uMO3vbeoLCDWu7vhu9i199K7tM47PC9wPjxwPjxiciAvPjwvcD48cD48c3Ryb25nPm9uQ3JlYXRlVmlldygpIDwvc3Ryb25nPjogu+bWxiwg1NogRnJhZ2VtZW50ILvm1sa1xMqxuvK72LX3uMO3vbeoLCC4w7e9t6i74be1u9ggu+bWxrXEIFZpZXcg1+m8/js8L3A+PHA+PGJyIC8+PC9wPjxwPjxzdHJvbmc+b25BY3Rpdml0eUNyZWF0ZWQoKTwvc3Ryb25nPiA6IL3nw+a0tL2oLCBGcmFnZW1lbnQgy/nHtsjrtcQgQWN0aXZpdHkgtLS9qM3qs8m72LX3uMO3vbeoOzwvcD48cD48YnIgLz48L3A+PHA+PHN0cm9uZz5vblN0YXJ0KCkgPC9zdHJvbmc+OiDG9LavLCBGcmFnZW1lbnQgxvS2r8qxu9i19ywgtMvKsUZyYWdlbWVudL/JvPs7PC9wPjxwPjxiciAvPjwvcD48cD48c3Ryb25nPm9uUmVzdW1lKCk8L3N0cm9uZz4gOiC8pLvuLCBGcmFnZW1lbnQgvfjI68ewzKgsIL/Ju/HIob25tePKsbyku+47PC9wPjxwPjxiciAvPjwvcD48cD48c3Ryb25nPm9uUGF1c2UoKTwvc3Ryb25nPiA6INTdzaMsIEZyYWdlbWVudCC9+MjruvPMqCwgsru/ybvxyKG9ubXjyrG8pLvuOzwvcD48cD48YnIgLz48L3A+PHA+PHN0cm9uZz5vblN0b3AoKTwvc3Ryb25nPiA6IM2j1rksIEZyYWdlbWVudCCyu7/JvPvKsbvYtfc7PC9wPjxwPjxiciAvPjwvcD48cD48c3Ryb25nPm9uRGVzdHJveVZpZXcoKTwvc3Ryb25nPiA6IM/6u9nX6bz+LCDP+rvZIEZyYWdlbWVudCC75tbGtcQgVmlldyDX6bz+yrG72LX3OzwvcD48cD48YnIgLz48L3A+PHA+PHN0cm9uZz5vbkRlc3Ryb3koKTwvc3Ryb25nPiA6IM/6u9ksIM/6u9kgRnJhZ2VtZW50ILvYtfc7PC9wPjxwPjxiciAvPjwvcD48cD48c3Ryb25nPm9uRGV0YWNoKCk8L3N0cm9uZz4gOiDSxrP9LCBGcmFnZW1lbnQgtNMgQWN0aXZpdHkg1tDSxrP9tcTKsbryu9i19zs8L3A+PHA+PGJyIC8+PC9wPjxwPjxiciAvPjwvcD48aDI+Ny4gtPrC68q+wP0gPC9oMj48cD48YnIgLz48L3A+PHA+PGJyIC8+PC9wPjxoMz4oMSkg0OjH87fWzvY8L2gzPjxwPjxiciAvPjwvcD48cD48c3Ryb25nPtfdz/LK1rv6xsHEuzwvc3Ryb25nPiA6IMG9uPa958PmLCDDv7j2vefD5ra809DSu7j2IEZyYWdlbWVudCwgINK7uPZGcmFnZW1lbnTP1Mq+0MLOxcHQse0sINK7uPZGcmFnZW1lbnQgz9TKvtDCzsXE2sjdOzwvcD48cD48c3Ryb25nPrrhz/LK1rv6xsHEuzwvc3Ryb25nPiA6INK7uPa958PmLCDBvbj2RnJhZ2VtZW50LCBGcmFnZW1lbnQgz9TKvsTayN3T68nPw+bP4M2sOzwvcD48cD48YnIgLz48L3A+PHA+PGJyIC8+PC9wPjxoMz4oMikg0MLOxbHqzOIgRnJhZ21lbnQ8L2gzPjxwPjxiciAvPjwvcD48cD48c3Ryb25nPrTmt8XQws7FserM4rXEIEZyYWdtZW50PC9zdHJvbmc+IDogTmV3c1RpdHRsZUZyYWdtZW50LmphdmE8L3A+PHA+PC9wPjxwcmUgY2xhc3M9"brush:java;">package cn.org.octopus; import android.app.Activity; import android.app.ListFragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListAdapter; import android.widget.ListView; /** * 内部类 : * Callbacks接口 * Fragement中维护该接口子类对象 * 需要Activity实现该接口, 实现接口方法 * Activity 在onAttach()方法中传入; * * 方法简介 : * 重写生命周期的 11 个方法; * onAttach() 方法中, 传入所嵌入的Activity, 并判断是否嵌入正确 * onCreate() 方法中, 创建 Fragement 中 ListView 的适配器, 并将适配器设置给 ListView * onDetach() 方法中, 将 Callbacks 接口子类对象置空 * * setChoiceMode() 设置ListView 的选择模式 * onListItemClick() ListView 的点击回调方法 * 注意 Android * */ public class NewsTittleFragment extends ListFragment { private Callbacks activityCallback; /* 从 onAttach()方法中传入的 Callbacks 接口子类, 由 Activity 强制转换而来 */ /** 定义回调接口 * 接口用法 : * 1. 该 Fragement 所 Activity 实现该接口 * 2. 该 Fragement 中 维护一个 该接口子类, 即 Activity * 3. 调用 Activity 接口子类的方法, 将数据传递给 Activity **/ public interface Callbacks{ public void onNewsSelect(int id); } /** Fragment 嵌入Activity */ @Override public void onAttach(Activity activity) { super.onAttach(activity); System.out.println("onAttach"); if ( ! ( activity instanceof Callbacks)) System.out.println("Fragement in wrong Activity !"); /* 为Activity中定义的Callbacks接口子类对象赋值 */ activityCallback = (Callbacks) activity; } /** Fragement 创建 * 进行设置适配器操作 */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); System.out.println("onCreate"); /* 为 ListFragment 创建适配器 * 注意使用的是 Android 自带的布局, 在 sdk\platforms\android-10\data\res\layout 目录下 * */ ListAdapter adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_activated_1, android.R.id.text1, NewsContent.getInstance().news); /* 设置适配器 给 ListFragement */ setListAdapter(adapter); } /** Fragment 绘制 */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { System.out.println("onCreateView"); return super.onCreateView(inflater, container, savedInstanceState); } /** Activity 创建完毕 */ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); System.out.println("onActivityCreated"); } /** Fragement 进入可视状态 */ @Override public void onStart() { super.onStart(); System.out.println("onStart"); } /** Fragement 进入激活状态 */ @Override public void onResume() { super.onResume(); System.out.println("onResume"); } /** Fragement 进入暂停状态 */ @Override public void onPause() { super.onPause(); System.out.println("onPause"); } /** Fragement 进入停止状态 */ @Override public void onStop() { super.onStop(); System.out.println("onStop"); } /** 销毁 Fragement 显示组件 */ @Override public void onDestroyView() { super.onDestroyView(); System.out.println("onDestroyView"); } /** 销毁 Fragement */ @Override public void onDestroy() { super.onDestroy(); System.out.println("onDestroy"); } /** 将 Fragement 从 Activity 中删除 */ @Override public void onDetach() { super.onDetach(); System.out.println("onDetach"); activityCallback = null; } /** * 列表对象被点击之后回调的方法 */ @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); activityCallback.onNewsSelect((int) id); } /** 设定选择模式, 该列表默认不能选择, 可以设置为不能选择, 单选 和 多选 * ListView.CHOICE_MODE_NONE 不能选择 * ListView.CHOICE_MODE_SINGLE 单选 * ListView.CHOICE_MODE_MULTIPLE 多选 * */ public void setChoiceMode(int choiceMode) { getListView().setChoiceMode(choiceMode); } }



(3) 新闻内容的 Fragment


存放新闻内容的 Fragment : NewsContentFragement.java;

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package cn.org.octopus;
 
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
 
public class NewsContentFragement extends Fragment {
 
     /* Bundle的key */
     public static final String TAG_NEWS_ID = "cn.org.octopus.news.tittle" ;
     
     private News news;
     
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         
         /* 校验 参数中是否包含 TAG_NEWS_ID 键值*/
         boolean isIllegal = getArguments().containsKey(TAG_NEWS_ID);
         
         if (isIllegal){
             /* 如果包含 TAG_NEWS_ID 键值, 就会去键对应的 id */
             int id = getArguments().getInt(TAG_NEWS_ID);
             /* 从 NewsContent 单例对象中的 map 集合中获取 news 对象 */
             news = NewsContent.getInstance().news_map.get(id);
         }
     }
     
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super .onSaveInstanceState(outState);
     }
     
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
         
         /* 加载布局文件 */
         View rootView = inflater.inflate(R.layout.fragment_news_content, container, false );
         /* 获取新闻标题组件 */
         TextView news_content_tittle = (TextView) rootView.findViewById(R.id.news_content_tittle);
         /* 获取新闻内容组件 */
         TextView news_content_content = (TextView) rootView.findViewById(R.id.news_content_content);
         if ( null != news){
             /* 设置新闻标题 */
             news_content_tittle.setText(news.getTittle());
             /* 设置新闻内容 */
             news_content_content.setText(news.getContent());
         }
         
         return rootView;
     }
     
}



(4) 新闻内容存储相关代码


新闻实体类 :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package cn.org.octopus;
 
public class News {
 
     private int id;         //新闻序号
     private String tittle;  //新闻标题
     private String content; //新闻内容
 
     /** 构造方法  */
     public News( int id, String tittle, String content) {
         super ();
         this .id = id;
         this .tittle = tittle;
         this .content = content;
     }
 
     public int getId() {
         return id;
     }
 
     public void setId( int id) {
         this .id = id;
     }
 
     public String getTittle() {
         return tittle;
     }
 
     public void setTittle(String tittle) {
         this .tittle = tittle;
     }
 
     public String getContent() {
         return content;
     }
 
     public void setContent(String content) {
         this .content = content;
     }
 
     /* 这里只返回标题, 是为了适配 ListFragement 时使用 */
     @Override
     public String toString() {
//      return "News [id=" + id + ", tittle=" + tittle + ", content=" + content
//              + "]";
         return tittle;
     }
     
}


新闻数据 :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package cn.org.octopus;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
public class NewsContent {
 
     /* 单例模式
      * 1. 私有 静态 本类成员变量
      * 2. 私有 构造 函数
      * 3. 公共 静态 函数, 检查本类成员变量是否为null, 返回本类成员变量 */
     
     private static NewsContent newsContent;
     
     public List<news> news;
     public Map<integer, news= "" > news_map;
     
     private NewsContent(){
         news = new ArrayList<news>();
         news_map = new HashMap<integer, news= "" >();
         
         News news1 = new News( 0 , "郭振玺敛财术" , "7月30日,央视纪录频道CCTV-9总监刘文被带走。据相关报道,刘文被带走的原因是 “发现在纪录片对外采购上有财务问题”,另外,在一些高收视率的纪录片创作上,“涉嫌与隐性的植入广告有关的利益交换”。" );
         News news2 = new News( 1 , "朝鲜新版5000朝元新钞无金日成头像" , "韩国网刊《每日朝鲜》8月1日报道,已经开始流通的5000朝元新钞并未印金日成肖像,意味金日成肖像已从朝鲜货币上暂时消失。 旧版朝鲜5000元纸币上印有金日成头像。" );
         News news3 = new News( 2 , "美国医生感染埃博拉" , "菲律宾卫生部部长恩里克·奥尼亚说,目前菲律宾尚无埃博拉疫情。卫生部已通报地方卫生部门,一旦发现返菲海外劳工出现感染埃博拉病毒早期症状,立即对患者实行隔离治疗。卫生部还要求近期即将从海外回国的劳工如出现发烧、头痛、关节和肌肉疼痛、喉咙痛等症状,在回国前应获得所雇佣国家卫生部门的无感染证明,以避免埃博拉病毒传入菲律宾。" );
                 
         news.add(news1);
         news.add(news2);
         news.add(news3);
         
         news_map.put(news1.getId(), news1);
         news_map.put(news2.getId(), news2);
         news_map.put(news3.getId(), news3);
     }
     
     /**
      * 判断成员变量 是否为null
      *  如果不为null, 直接返回;
      *  如果为null, 先创建在返回;
      */
     public static NewsContent getInstance() {
         
         if (newsContent != null )
             return newsContent;
         else
             return new NewsContent();
     }
     
}
</integer,></news></integer,></news>



(5) 主界面 Actiity 代码


主界面代码 : MainActivity.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package cn.org.octopus;
 
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import cn.org.octopus.NewsTittleFragment.Callbacks;
 
public class MainActivity extends Activity implements Callbacks {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         
         /* 加载布局文件, 这个布局文件中有一个 Fragment, 会自动加载该 Fragmet */
         setContentView(R.layout.activity_main);
     }
 
     /**
      * 实现的 Callbasks 接口的方法,
      * 当 NewsTittleFragement 中的 ListView 被点击的时候 回调
      * */
     @Override
     public void onNewsSelect( int id) {
         /* 创建 Bundle 对象, Activity 传递给 Fragment 的参数需要靠该对象进行传递 */
         Bundle arguments = new Bundle();
         /* 封装数据到 Bundle 对象中, 注意提前定义好键值 */
         arguments.putInt(NewsContentFragement.TAG_NEWS_ID, id);
         /* 创建 Fragment 对象 */
         NewsContentFragement fragement = new NewsContentFragement();
         /* 将 Activity 要传递的数据 传递给 Fragment 对象 */
         fragement.setArguments(arguments);
         /* 获取FragmentManager 对象 */
         FragmentManager manager = getFragmentManager();
         /* 开启事务, 获取事务 */
         FragmentTransaction transaction =  manager.beginTransaction();
         /* 在事务中进行替换操作 */
         transaction.replace(R.id.news_content, fragement);
         /* 提交操作 */
         transaction.commit();
     }
 
}


(6) AndroidManifest.xml 配置文件


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<manifest xmlns:android= "http://schemas.android.com/apk/res/android" package = "cn.org.octopus" android:versioncode= "1" android:versionname= "1.0" >
 
     <uses-sdk android:minsdkversion= "15" android:targetsdkversion= "19" >
 
     
         
         <!--
             设置屏幕方向 android:screenOrientation :
                 unspecified : 默认值, 系统自动判定方向
                 landscape : 横屏显示
                 portrait : 竖屏显示
                 user : 用户当前首选方向
                 behind : 与 之前的 Activity 方向一致;
                 sensor : 由物理传感器决定
                 nosenser : 忽略物理传感器感应
          -->
         
         
             <intent-filter>
                 
 
                 <category android:name= "android.intent.category.LAUNCHER" >
             </category></action></intent-filter>
         </activity>
     </application>
 
</uses-sdk></manifest>


(7) 执行结果


跟踪的 Fragment 生命周期回调函数打印的结果 :

?
1
2
3
4
5
6
7
8
9
10
11
I/System.out( 8604 ): onAttach
I/System.out( 8604 ): onCreate
I/System.out( 8604 ): onCreateView
I/System.out( 8604 ): onActivityCreated
I/System.out( 8604 ): onStart
I/System.out( 8604 ): onResume
I/System.out( 8604 ): onPause
I/System.out( 8604 ): onStop
I/System.out( 8604 ): onDestroyView
I/System.out( 8604 ): onDestroy
I/System.out( 8604 ): onDetach

界面执行结果 :

\




.


8. 出错处理


(1) 引用 不用包中的 Fragment


引用 android.app.ListFragment, 不会出现错误, 而 引用android.support.v4.app.ListFragment 类会出现如下错误;


错误 :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ): FATAL EXCEPTION: main
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ): java.lang.RuntimeException: Unable to start activity ComponentInfo{cn.org.octopus/cn.org.octopus.MainActivity}: android.view.InflateException: Binary XML file line # 11 : Error inflating class fragment
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 2255 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java: 2309 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.ActivityThread.access$ 700 (ActivityThread.java: 157 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java: 1289 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.os.Handler.dispatchMessage(Handler.java: 99 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.os.Looper.loop(Looper.java: 176 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.ActivityThread.main(ActivityThread.java: 5319 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at java.lang.reflect.Method.invokeNative(Native Method)
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at java.lang.reflect.Method.invoke(Method.java: 511 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 1102 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 869 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at dalvik.system.NativeStart.main(Native Method)
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ): Caused by: android.view.InflateException: Binary XML file line # 11 : Error inflating class fragment
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java: 710 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.view.LayoutInflater.rInflate(LayoutInflater.java: 752 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.view.LayoutInflater.inflate(LayoutInflater.java: 495 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.view.LayoutInflater.inflate(LayoutInflater.java: 397 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.view.LayoutInflater.inflate(LayoutInflater.java: 353 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java: 360 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.Activity.setContentView(Activity.java: 1932 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at cn.org.octopus.MainActivity.onCreate(MainActivity.java: 13 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.Activity.performCreate(Activity.java: 5326 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java: 1097 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 2218 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     ... 11 more
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ): Caused by: android.app.Fragment$InstantiationException: Trying to instantiate a class cn.org.octopus.NewsTittleFragment that is not a Fragment
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.Fragment.instantiate(Fragment.java: 584 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.Fragment.instantiate(Fragment.java: 560 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.app.Activity.onCreateView(Activity.java: 4908 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java: 686 )
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     ... 21 more
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ): Caused by: java.lang.ClassCastException
08 - 06 22 : 17 : 12.537 : E/AndroidRuntime( 3751 ):     ... 25 more


(2) ListView 适配器设置错误


ListView 适配器引用的 组件, 必须是已经加载过的, 通过 onCreate()中的 setContentView()方法加载, 或者通过 LayoutInflater 进行加载;


错误 :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
08 - 06 22 : 39 : 22.139 : W/dalvikvm( 4413 ): threadid= 1 : thread exiting with uncaught exception (group= 0x40dc0930 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ): FATAL EXCEPTION: main
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ): android.content.res.Resources$NotFoundException: Resource ID # 0x7f080001 type # 0x12 is not valid
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.content.res.Resources.loadXmlResourceParser(Resources.java: 3033 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.content.res.Resources.getLayout(Resources.java: 1722 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.LayoutInflater.inflate(LayoutInflater.java: 395 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java: 371 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.ArrayAdapter.getView(ArrayAdapter.java: 362 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.AbsListView.obtainView(AbsListView.java: 2603 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.ListView.makeAndAddView(ListView.java: 1840 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.ListView.fillDown(ListView.java: 681 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.ListView.fillFromTop(ListView.java: 742 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.ListView.layoutChildren(ListView.java: 1661 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.AbsListView.onLayout(AbsListView.java: 2426 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.View.layout(View.java: 14905 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewGroup.layout(ViewGroup.java: 4601 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.FrameLayout.onLayout(FrameLayout.java: 448 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.View.layout(View.java: 14905 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewGroup.layout(ViewGroup.java: 4601 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.FrameLayout.onLayout(FrameLayout.java: 448 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.View.layout(View.java: 14905 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewGroup.layout(ViewGroup.java: 4601 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.RelativeLayout.onLayout(RelativeLayout.java: 1021 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.View.layout(View.java: 14905 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewGroup.layout(ViewGroup.java: 4601 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.FrameLayout.onLayout(FrameLayout.java: 448 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.View.layout(View.java: 14905 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewGroup.layout(ViewGroup.java: 4601 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java: 1694 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.LinearLayout.layoutVertical(LinearLayout.java: 1552 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.LinearLayout.onLayout(LinearLayout.java: 1465 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.View.layout(View.java: 14905 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewGroup.layout(ViewGroup.java: 4601 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.widget.FrameLayout.onLayout(FrameLayout.java: 448 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.View.layout(View.java: 14905 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewGroup.layout(ViewGroup.java: 4601 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java: 2213 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java: 2027 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java: 1237 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java: 5162 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java: 791 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.Choreographer.doCallbacks(Choreographer.java: 591 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.Choreographer.doFrame(Choreographer.java: 561 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java: 777 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.os.Handler.handleCallback(Handler.java: 725 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.os.Handler.dispatchMessage(Handler.java: 92 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.os.Looper.loop(Looper.java: 176 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at android.app.ActivityThread.main(ActivityThread.java: 5319 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at java.lang.reflect.Method.invokeNative(Native Method)
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at java.lang.reflect.Method.invoke(Method.java: 511 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 1102 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 869 )
08 - 06 22 : 39 : 22.139 : E/AndroidRuntime( 4413 ):     at dalvik.system.NativeStart.main(Native Method)


9. Fragement 复用问题


需求 : 在手机竖屏的时候, 新闻列表 和 新闻内容 在两个 Activity 中, 横屏的时候, 在一个 Activity 中;



(1) 根据不同的环境加载不同的布局


定义实际引用的资源 : 在 Java 代码中引用资源的时候, 会到 values 中查询, 是否有定义资源文件, 如果有, 优先按照该定义加载指定资源文件;

-- 定义方式 : 下面的定义, 如果代码中引用 R.layout.activity_main, 符合条件的话, 使用 R.layout.activity_main_land 布局文件;

?
1
2
3
<resources>
     <item type= "layout" name= "activity_main" > @layout /activity_main_land</item>
</resources>
--  属性说明 : type 资源的类型, name 资源名称;


(2) 判断加载的布局文件


判断的依据 : 根据 两个布局文件的差异, 任意查找一个组件, 或者定义一个 不占位置的组件, 来进行判定;

?
1
2
/* 查看加载的是哪个文件, 如果文件中包含 R.id.news_content_content 组件, 就说明现在是横屏的 */
isLand = findViewById(R.id.news_content) != null ;


(3) MainActivity 代码差异


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package cn.org.octopus;
 
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
import cn.org.octopus.NewsTittleFragment.Callbacks;
 
public class MainActivity extends Activity implements Callbacks {
 
     private boolean isLand;     /* 标识是否是横屏 */
     
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         
         /* 加载布局文件, 这个布局文件中有一个 Fragment, 会自动加载该 Fragmet */
         setContentView(R.layout.activity_main);
         
         /* 查看加载的是哪个文件, 如果文件中包含 R.id.news_content_content 组件, 就说明现在是横屏的 */
         isLand = findViewById(R.id.news_content) != null ;
     }
 
     /**
      * 实现的 Callbasks 接口的方法,
      * 当 NewsTittleFragement 中的 ListView 被点击的时候 回调
      * */
     @Override
     public void onNewsSelect( int id) {
         
         /* 如果是横屏的情况, 两个 Fragement 都在一个界面中  */
         if (isLand){
             /* 创建 Bundle 对象, Activity 传递给 Fragment 的参数需要靠该对象进行传递 */
             Bundle arguments = new Bundle();
             /* 封装数据到 Bundle 对象中, 注意提前定义好键值 */
             arguments.putInt(NewsContentFragement.TAG_NEWS_ID, id);
             /* 创建 Fragment 对象 */
             NewsContentFragement fragement = new NewsContentFragement();
             /* 将 Activity 要传递的数据 传递给 Fragment 对象 */
             fragement.setArguments(arguments);
             /* 获取FragmentManager 对象 */
             FragmentManager manager = getFragmentManager();
             /* 开启事务, 获取事务 */
             FragmentTransaction transaction =  manager.beginTransaction();
             /* 在事务中进行替换操作 */
             transaction.replace(R.id.news_content, fragement);
             /* 提交操作 */
             transaction.commit();
         } else /* 竖屏的情况, 需要开启 Activity */
             System.out.println( "isLand : " + isLand);
             Intent intent = new Intent(getApplicationContext(), NewsContentActivity. class );
             /* 通过 Intent 的 Bundle 对象传递参数 */
             intent.putExtra(NewsContentFragement.TAG_NEWS_ID, id);
             startActivity(intent);
         }
         
     }
 
}


(4) 新增了 NewsContentActivity


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package cn.org.octopus;
 
import android.app.Activity;
import android.os.Bundle;
 
public class NewsContentActivity extends Activity {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         /* 设置布局文件 */
         setContentView(R.layout.activity_news_content);
         
         /* 创建 Fragement */
         NewsContentFragement fragement = new NewsContentFragement();
         /* 创建绑定的数据 */
         Bundle bundle = new Bundle();
         /* 从Activity 获取 启动该 Activity 的 Intent */
         int id = getIntent().getIntExtra(NewsContentFragement.TAG_NEWS_ID, 0 );
         bundle.putInt(NewsContentFragement.TAG_NEWS_ID, id);
         /* 设置数据给 Fragment */
         fragement.setArguments(bundle);
         /* 开启事务 操作 Fragement 并提交 */
         getFragmentManager().beginTransaction().add(R.id.news_content, fragement).commit();
     }
}



(5) 新增 或 修改的布局文件


activity_main.xml :

?
1
2
3
4
5
<linearlayout 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= ".MainActivity" >
 
     <fragment android:id= "@+id/tittle_fragment" android:name= "cn.org.octopus.NewsTittleFragment" android:layout_width= "0dp" android:layout_weight= "1" android:layout_height= "match_parent" >
 
</fragment></linearlayout>


activity_main_land.xml :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<linearlayout 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= ".MainActivity" android:orientation= "horizontal" android:divider= "?android:attr/dividerHorizontal" android:showdividers= "middle" >
     
     <!--
         资源引用方式解析 : 
             @+id : 定义一个 id 值, 用于识别组件
             @id : 引用 id 值代表的组件
             @anroid :type : 引用 Android 内部的资源, type 指的是 drawable string 等资源类型
             ?android:attr : 引用 Android 内部的样式
         
         分割线解析 :
             分割线资源 : 在 android:divider 属性中引入样式, 这里通过 ?android:attr 引入一个 android 的自定义样式
             分割线样式 : android:showDivider 属性中设置, none 不显示分割线, beginning 在开始处显示, end 在结尾显示, middle 中间显示
      -->
 
     <fragment android:id= "@+id/tittle_fragment" android:name= "cn.org.octopus.NewsTittleFragment" android:layout_width= "0dp" android:layout_weight= "1" android:layout_height= "match_parent" >
     
     <frameLayout
         android:id= "@+id/news_content"
         android:layout_width= "0dp"
         android:layout_weight= "3"
         android:layout_height= "match_parent" />
 
</fragment></linearlayout>


activity_news_content.xml :

?
1
2
3
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" android:id= "@+id/news_content" android:layout_width= "match_parent" android:layout_height= "match_parent" android:orientation= "vertical" >
</linearlayout>



(6) 执行效果


竖屏 :

\


横屏 :







作者 : 韩曙亮

转载请著名出处 : http://blog.youkuaiyun.com/shulianghan/article/details/3806419
1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值