目录
易错点一:如果fragment外面没有一层layout包裹它,则一定要给id,否则报错,类似下面这样是不行的
易错点:当前显示的fragment如果不是要删除的那个,执行remove也是没用的
易错点一:如下图,实测replace之后,fragment并没有变空,如果放在if(fragmentLeft==null)的里面,那么再切换回来的时候,不会执行if里面的语句,所以就什么都不显示出来
易错点二: 无论是采用add 或者replace进行替换,如果没有加addToBackStack的话按返回键都会退出APP,加了的话,replace会回退到上一个fragment而不是直接退出
一、Fragment的创建
1、XML
首先给fragment定义一个布局,然后新建一个类继承Fragment,在onCreateView中加载布局。
然后在activity的xml中通过<fragment/>标签包含进来,最重要的是它的属性name
易错点一:如果fragment外面没有一层layout包裹它,则一定要给id,否则报错,类似下面这样是不行的
但是外面有一层layout,则不用id也是可以的,如下
2、动态创建
不在XML中操作,在activity中new就行了
易错点一:FragmentTransaction只能提交一次,所以可将多个操作搞在一起,最后一次性提交;不然就多用getSupportFragmentManager().beginTransaction()
易错点二:动态加载时,activity通过findviewbyid能找到fragment的控件id,但是拿到的却是空的,如果尝试给这个控件设置点击事件则会报错,需要在该控件所属的fragment的onCreateView中设置点击事件
二、Fragment的删除
易错点:当前显示的fragment如果不是要删除的那个,执行remove也是没用的
三、Fragment的替换
有两种方法:add 或者 replace--->hide所有的fragment---->show需要显示的fragment
区别就是add的时候不会刷新,replace会刷新
易错点一:如下图,实测replace之后,fragment并没有变空,如果放在if(fragmentLeft==null)的里面,那么再切换回来的时候,不会执行if里面的语句,所以就什么都不显示出来
易错点二: 无论是采用add 或者replace进行替换,如果没有加addToBackStack的话按返回键都会退出APP,加了的话,replace会回退到上一个fragment而不是直接退出
下面是add 和 replaced的测试代码
代码如下:
left_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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是左边"
android:id="@+id/leftText" />
</LinearLayout>
middle_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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是中间"
android:id="@+id/middleText" />
</LinearLayout>
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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是右边"
android:id="@+id/rightText" />
</LinearLayout>
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/frameLayout"
android:layout_weight="6">
</FrameLayout>
<LinearLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="0dp" >
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="左边"
android:layout_weight="1"
android:id="@+id/leftBtn" />
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="中间"
android:id="@+id/middleBtn" />
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="右边"
android:id="@+id/rightBtn" />
</LinearLayout>
</LinearLayout>
3个Fragment都是类似的,如下:
最后MainActivity如下:主要就是分别尝试add 和replace来进行替换
package com.example.fragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Button leftBtn;
private Button midBtn;
private Button rigBtn;
private Fragment fragmentLeft;
private Fragment fragmentMid;
private Fragment fragmentRight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
leftBtn = (Button) findViewById(R.id.leftBtn);
rigBtn = (Button) findViewById(R.id.rightBtn);
midBtn = (Button) findViewById(R.id.middleBtn);
leftBtn.setOnClickListener(this);
rigBtn.setOnClickListener(this);
midBtn.setOnClickListener(this);
initFragmentleft();
// getSupportFragmentManager().beginTransaction().add(R.id.frameLayout,new LeftFrag()).commit();
}
private void add() {
getSupportFragmentManager().beginTransaction().add(R.id.frameLayout,new MiddleFragment()).commit();
}
private void replace() {
getSupportFragmentManager().beginTransaction().addToBackStack(null).add(R.id.frameLayout,new RightFrag()).commit();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.leftBtn:
// add();
initFragmentleft();
break;
case R.id.middleBtn:
// replace();
initFragmentMid();
break;
case R.id.rightBtn:
initFragmentRig();
break;
}
}
private void initFragmentleft() {
FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
if (fragmentLeft == null) {
fragmentLeft = new LeftFrag();
transaction.add(R.id.frameLayout,fragmentLeft);
// transaction.replace(R.id.frameLayout,fragmentLeft);//易错点,不能在这里面replace
}
// transaction.replace(R.id.frameLayout,fragmentLeft);
hideAllFragment(transaction);
transaction.show(fragmentLeft);
transaction.commit();
}
private void hideAllFragment(FragmentTransaction transaction) {
if (fragmentLeft != null) {
transaction.hide(fragmentLeft);
}
if (fragmentMid != null) {
transaction.hide(fragmentMid);
}
if (fragmentRight != null) {
transaction.hide(fragmentRight);
}
}
private void initFragmentMid() {
FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
if (fragmentMid == null) {
fragmentMid = new MiddleFragment();
transaction.add(R.id.frameLayout,fragmentMid);
// transaction.replace(R.id.frameLayout,fragmentMid);
}
// transaction.replace(R.id.frameLayout,fragmentMid);
hideAllFragment(transaction);
transaction.show(fragmentMid);
transaction.commit();
}
private void initFragmentRig() {
FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
if (fragmentRight == null) {
fragmentRight = new RightFrag();
transaction.add(R.id.frameLayout,fragmentRight);
// transaction.replace(R.id.frameLayout,fragmentRight);
}
// transaction.replace(R.id.frameLayout,fragmentRight);
hideAllFragment(transaction);
transaction.show(fragmentRight);
transaction.commit();
}
}
通过add进行替换的效果:
通过replace进行替换的效果:
四、Fragment和Activity之间的通信
1、在Activity中操作Fragment的控件和属性
1.1 如果Fragment是通过XML加入Activity的,先getSupportFragmentManager().findFragmentById或者getSupportFragmentManager().findFragmentByTag找到相应的Fragment。然后通过fragment.getView().findViewById找到相应的控件进行操作
1.2 如果Fragment是通过动态加载的,那么直接通过它的引用getView().findViewById()
1.3 如果是想获得Fragment的属性,那么可以在Fragment中暴露一个get接口给Activity调用
2、在Fragment中操作Activity的控件和属性
(耦合高,不推荐):
2.1通过getActivity().findViewById()就可以拿到Activity的控件,就可以进行相应的操作
2.2 如果是想获得Activity的属性,那么同样可以在Activity中暴露一个get接口给Fragment调用
五、Fragment和Fragment之间的通信
思路:Fragment1中回调某个接口,由Activity实现这个接口这样数据就传到Activity,然后通过Activity和Fragment2进行通信
六、超级易错点
如果Fragment的layout文件只是一个控件,外面没有包裹一个布局,如下:
在Fragment中加载布局是没问题的,如下:
但是在Activity中获取到的控件为null,切记!!!!!!!,如下