Android之fragment的简单使用

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173


/*
Fragment与activity类似,有其自己的声明周期,是一个可重用的、模块化的 UI 组件
每一个Fragment实例都必须与一个FragmentActivity关联,
在activity运行过程中,fragment可添加与移除。
*/

/* 创建一个Fragment */

public class extend Fragment{

/* 必须重写的方法,重写获取布局后才能显示Fragment */

public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle saveInstanceState){
//获取该fragment的布局
return inflater.inflate(R.layout.xxx,container,false);
}
}

/*
静态引用:与一般View(button,TextView)一样,在activity布局xml文件中引用即可。
此方法不能替换fragment。
*/

/*
动态添加:即在activity运行时再添加fragment(利用FragmentManager,FragmentTransaction)
此方法下,fragment可动态添加(在activity的oncreate()方法中添加初始化fragment),移除与替换。

实现activity中动态添加Fragment,即在该activity下必须提供容器显示Fragment(一般用framelayout,且一次只能显示一个)。
实例如下:
*/

/*
注:AppCompatActivity是FragmentActivity的子类
*/
public class ExampleActivity extend AppCompatActivity{

private FrameLayout containerFl;

public void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);

// 获取容器
containerFl = FindViewById(R.id.frame_layout);

//创建实例
MyFragment myFragment = new MyFragment();
//向该fragment传递数据
myFragment.setArgumnets(key,value);//或利用Bundle传递 -->myFragment.setArgumnets(new Bundle(key,value));

// 将该 Fragment 添加到 containerFl 中
getSupportFragmentManager().beginTransaction()//beginTransaction 获取到FragmentTransaction
.add(R.id.frame_layout, firstFragment).commit();

/*
替换当前fragment
OtherFragment otherFragment = new OtherFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, firstFragment); 调用replace方法(replace()调用了remove(),add()方法)

//如若需要回退到前fragment
addToBackStack(null);
addToBackStack() 方法可接受可选的字符串参数,来为事务指定独一无二的名称。
除非你打算使用 FragmentManager.BackStackEntry API 执行高级 Fragment 操作,否则传入null即可。

transaction.commit();
*/
}
}

/* fragment间的交互:
所有 Fragment 之间的交互应通过与之关联的 Activity 来完成。
两个 Fragment 之间不应直接交互。

自己在项目中是fragment间直接交互的,如fragment间的替换以及传递消息
所以一直都觉得fragment间交互比较混乱,处理得不好的情况下会导致fragment重叠。
现在才知道,fragment间的交互应该通过其关联的activity来进行。
*/

/* 定义接口进行交互 (与adapter提供回调接口类似)
以下为从官方文档的代码:
*/
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;

// 容器 Activity 必须实现该接口
// (译注:“容器 Activity”意即“包含该 Fragment 的 Activity”)
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}


public void onAttach(Activity activity) {
super.onAttach(activity);

// 确认容器 Activity 已实现该回调接口。否则,抛出异常
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
...
}

/*
现在 Fragment 可以通过调用 mCallback(OnHeadlineSelectedListener 接口的实例)的 onArticleSelected() 方法(也可以是其它方法)与 Activity 进行消息传递。

例如,当用户点击列表条目时,Fragment 中的下面的方法将被调用。Fragment 用回调接口将事件传递给父 Activity。
*/


public void onListItemClick(ListView l, View v, int position, long id) {
// 向宿主 Activity 传送事件
mCallback.onArticleSelected(position);
}

//activity中实现接口

public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...

public void onArticleSelected(int position) {
// 用户从 HeadlinesFragment 选择了一篇文章的标题
// 在这里做点什么,以显示该文章
}
}

//向另一fragment传递消息
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...

public void onArticleSelected(int position) {
// 用户从 HeadlinesFragment 选择了一篇文章的标题
// 在这里做点什么,以显示该文章

ArticleFragment articleFrag = (ArticleFragment)
getSupportFragmentManager().findFragmentById(R.id.article_fragment);

if (articleFrag != null) {
// 若 articleFrag 有效,则表示我们正在处理两格布局(two-pane layout)……

// 调用 ArticleFragment 的方法,以更新其内容
articleFrag.updateArticleView(position);
} else {
// 否则,我们正在处理单格布局(one-pane layout)。此时需要 swap frags...

// 创建 Fragment,向其传递包含被选文章的参数
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// 无论 fragment_container 视图里是什么,用该 Fragment 替换它。并将
// 该事务添加至回栈,以便用户可以往回导航(译注:回栈,即 Back Stack。
// 在有多个 Activity 的 APP 中,将这些 Activity 按创建次序组织起来的
// 栈,称为回栈)
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// 执行事务
transaction.commit();
}
}
}