碎片的真正强大之处在于,可以在程序运行时,动态添加到活动中。
代码继续接上文《Android碎片学习(一)——简单用法》
一、动态添加碎片
1、碎片布局
another_right_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffff00">
<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>
2、类
AnotherRightFragment.java
public class AnotherRightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.another_right_fragment, container, false);
}
}
3、主布局
将右侧碎片替换成<FrameLayout>
参考资料:《Android布局学习(三)——帧布局FrameLayout》
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:name="com.example.day06_fragment.LeftFragment"
android:id="@+id/left_fragment"
/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/right_layout"
/>
</LinearLayout>
这里仅需要往布局中添加一个碎片,不需要任何定位,非常适合FrameLayout
4、主活动
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(this);
replaceFragment(new RightFragment());
}
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.commit();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
replaceFragment(new AnotherRightFragment());
break;
default:
break;
}
}
}
首先在左侧碎片的按钮中注册了点击事件,然后调用replaceFragment()
方法动态添加RightFragment
这个碎片,点击按钮时又会将右侧碎片替换成AnotherRightFragment
5、运行
点击按钮前
点击后:
6、总结
动态添加/替换碎片分为五步:
- 创建待添加的碎片实例
- 获取
FragmentManger
,可以在活动中用getSupportFragmentManager()
获得 - 开启一个事务,调用
beginTransaction()
开启 - 向容器添加
add
或替换replace()
碎片 - 提交事务
commit()
二、在碎片中返回栈
直接点BACK
就会退出,如果想实现返回上一个碎片,该怎么做呢?
使用addToBackStack()
方法可以将一个事务添加到返回栈当中
修改主活动:
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
三、碎片和活动间的通信
碎片和活动都是各自存在于一个独立的类中的,那么碎片和活动如何调用对方的方法呢?
1、活动中调用碎片的方法
FragmentManager
提供了findFragmentById()
用来从布局文件中获取碎片实例:
RightFragMent rightFragment = (RightFragment) getSupportFragmentManger().findFragmentById(R.id.right_fragment);
2、碎片中调用活动的方法
每个碎片都可以调用getActivity()
来获取相关联的活动实例
MainActivity activity = (MainActivity) getActivity();
需要使用Context
对象时也是调用这个方法
3、碎片中调用碎片的方法
参考上两条,结合一下,嘿嘿~