<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button"
/>
LinearLayout>
这个布局中放置了一个Button,并让它水平居中显示
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#00ff00"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="This is right fragment"
/>
LinearLayout>
这个布局的背景颜色设置成了绿色,并放置了一个TextView用于显示一段文本
LeftFragment :
public class LeftFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false);
return view;
}
}
重写Fragment的onCreateView()方法,然后在这个方法中通过LayoutInflater的inflate()方法将刚才定义的left_fragment布局动态加载进来
public class RightFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.right_fragment, container, false);
return view;
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/right_fragment"
android:name="com.example.fragmenttest.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
LinearLayout>
可以看到使用标签在布局中添加碎片,这里通过android:name属性来显示指明要添加的碎片类名,注意一定要将类的包名也加上
Fragment真正强大之在于,它可以在程序运行时动态地添加到活动中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#ffff00"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="This is another right fragment"
/>
LinearLayout>
这个布局和right_frgment.xml中的代码基本相同,只是将背景色改成黄色,并修改了显示的文字
public class AnotherRightFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.another_right_fragment, container, false);
return view;
}
}
同样是在onCreateView()方法中加载了刚刚创建的another_right_fragment布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
// 新增布局
<FrameLayout
android:id="@+id/right_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
FrameLayout>
LinearLayout>
可以看到,现在将右侧碎片替换成了一个FrameLayout,下面我们将在代码中想FrameLayout里添加内容,从而实现动态添加碎片的功能,修改MainActivity中的代码 :
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
replaceFragment(new RightFragment());
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
replaceFragment(new AnotherRightFragment());
break;
default:
break;
}
}
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.commit();
}
}
可以看到,首先我们给左侧Fragment中的按钮注册了一个点击事件,然后调用replaceFragment()方法动态添加了RightFragment这个碎片,当点击左侧碎片中的按钮时,又会调用replaceFragment()方法将右侧碎片替换成AnotherRightFragment,结合replaceFragment()方法中的代码可以看出,动态添加Fragment主要分为5步:
提交事务,调用commit()方法来完成
这样就完成了在活动中动态添加碎片的功能
可以看到,通过点击按钮添加了一个碎片之后,这时按下Back键程序就会直接退出
1.2中通过点击按钮添加了一个碎片之后,这时按下Back键程序就会直接退出,如果这里我们要模拟返回栈的效果,按下Back键可以回到上一个碎片,要实现这种效果其实很简单,FragmentTransaction中提供了一个addToBackStack()方法,可以用于将一个事务添加到返回栈中,修改MainActivity中的代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
...
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout, fragment);
// 添加
transaction.addToBackStack(null);
transaction.commit();
}
}
在这里我们在事务提交之前条用了FragmentTransaction的addToBackStack()方法,它可以接受一个名字用于描述返回栈的状态,一般传入null即可
虽然Fragment都是嵌入在Activity中显示的,可是实际上它们之间的关系并没有那么亲密,可以看出Fragment和Activity都是各自存在于一个独立的类当中的,它们之间并没有那么明显的方式来直接进行通信,如果想要在Activity中调用Fragment的方法,或者在Fragment中调用Activity方法,应该如何实现?
为了方便Fragment和Activity之间进行通信,FragmentManager提供了一个findFragmentById()的方法,专门用于从布局文件中获取碎片的实例:
NewsContentFragment newsContentFragment = (NewsContentFragment)getFragmentManager().findFragmentById(R.id.news_content_fragment);
调用FragmentManager的findFragmentById()方法,可以在Activity中得到相应Fragment的实例,然后就可以轻松地调用Fragment里面的方法了
那么Fragment又是怎样调用Activity里面的方法呢?在每个Fragment中都可以通过getActivity()方法来得到和当前Fragment相关联的Activity实例:
MainActivity activity = (MainActivity)getActivity();
有了Activity实例后,在Fragment中调用Activity里的方法就变得轻而易举了,当碎片中需要使用Context对象时,也可以使用getActivity()方法,因为获得的Activity本身就是个Context对象
那么Fragment与Fragment之间如何进行通信呢?
首先在Fragment中可以得到与它相关联的Activity,然后再通过这个Activity去获取另外一个Fragment的实例,这样也就实现了不同Fragment之间的通信功能
和Activity一样,Fragment也有自己的生命周期,理解Fragment的生命周期非常重要,我们通过代码的方式来瞧一瞧Fragment的生命周期是什么样的:
public class Fragment1 extends Fragment {
public static final String TAG = "Fragment1";
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.d(TAG, "onAttach");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
return inflater.inflate(R.layout.fragment1, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated");
}
@Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "onDestroyView");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
@Override
public void onDetach() {
super.onDetach();
Log.d(TAG, "onDetach");
}
}
可以看到,上面的代码在每个生命周期的方法里都打印了日志,然后我们来运行一下程序,可以看到打印日志如下:
这时点击一下home键,打印日志如下:
如果你再重新进入进入程序,打印日志如下:
然后点击back键退出程序,打印日志如下:
看到这里,我相信大多数朋友已经非常明白了,因为这和Activity的生命周期太相似了。只是有几个Activity中没有的新方法,这里需要重点介绍一下:
参考:
Android Fragment完全解析,关于碎片你所需知道的一切
https://blog.csdn.net/guolin_blog/article/details/8881711