动态添加一个fragment有两种方法
1.add
2.replace
两个方法的使用
两者的区别是什么(这里只做简单的阐述)?
add:允许Fragment共存
replace:不允许Fragment共存
共存和不共存的区别是,允许共存的话(add),再次添加一个Fragment,这个Fragment会覆盖到那个Fragment的上面;不共存的情况下(replace),再次添加一个Fragment时会先将一开始的Fragment的移除才会添加新的
两者存在着各自的有点也有各自的缺点
比如在一个fragment中有一个20秒中的网络请求,当replace方法添加fragment,网络请求的数据也会被移除,下一次回来要重新请求,如果是用add再次添加的话可以避免
又比如,我的第一个Fragment是几乎透明的,我用add方法添加一个新的Fragment,这个时候Fragment之间的文字会相互覆盖,效果如下
允许共存的情况下下每个Fragment之间都是可以获取焦点的
也就是说当前显示的是首页,但是我却可以去点帮助界面的按钮,并有反应
那么怎么解决界面重合影响整体效果的问题呢~~下面开始说正事!
怎样解决用add方法添加Fragment界面重合
以上图三个Fragment为例,分别是HomeFragment,SettingFragment,HelpFragment
PS:所有的Fragment都是存在一个栈中
1.点击下方三个Button,显示不同的Fragment
2.在显示前判断Fragment是否已经存在于栈中
-如果不存在将其添加(add)并显示
-如果存在直接从栈中取出来显示
3.显示当前的Fragment时将它上一个显示的Fragment隐藏掉
(首先要判断它是否存在上一个Fragment,第一个显示的Fragment肯定是不存在的)
天呐!!我竟然哔哔了这么多字,下面上代码!!!!!!!
创建Fragment布局
这些是布局的创建,不想看的直接看下一个板块
1.在MainActivtiy布局中创建< FrameLayout >占位符
<FrameLayout
android:id="@+id/main_fram"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
下面有个RadioGroup的导航栏
<RadioGroup
android:id="@+id/main_rg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<RadioButton
android:id="@+id/main_home_rb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="首页"
android:button="@null"
android:textSize="16sp"
android:paddingLeft="0dp"
android:drawableTop="@drawable/main_tab_home"
android:drawablePadding="10dp"
android:textColor="@drawable/text_color_select"
android:gravity="center"
android:checked="true"
/>
......
<RadioGroup>
只演示一个RadioButton
设计Fragment布局,创建HomeFragment继承Fragment
public class HelpFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View v= inflater.inflate(R.layout.fragment_help,null);
return v;
}
}
这样我们的Fragment就创建好了,下一步就是点击RadioButton添加不同的布局了
添加布局
1.创建FragmentManager
manager = getSupportFragmentManager();
2.自定义一个添加Fragment的方法
1.判断当前fragment是否存在于栈中,这里是为Fragment添加了一个标签判断的
如果不存在添加并显示,存在直接显示show出来,不用再添加到栈
Fragment fragment;
private void addFragment(String fTag) {
//判断这个标签是否存在Fragment对象,如果存在则返回,不存在返回null
fragment = manager.findFragmentByTag(fTag);
//如果这个fragment不存于栈中
if (fragment == null) {
//初始化Fragment事物
transaction = manager.beginTransaction();
//根据RaioButton点击的Button传入的tag,实例化,添加显示不同的Fragment
if (fTag.equals("home")) {
fragment = new HomeFragment();
} else if (fTag.equals("help")) {
fragment = new HelpFragment();
} else if (fTag.equals("setting")) {
fragment = new SettingFragment();
}
transaction.add(R.id.main_fram, fragment, fTag);
transaction.commit();
} else {
//如果添加的Fragment已经存在,fragment不为空,直接显示fragment
transaction = manager.beginTransaction();
transaction.show(fragment);
transaction.commit();
}
}
上面只是将Fragment添加到栈,并保证栈中只存在三个Fragment,并不能 解决界面重合
3.解决界面重合问题
1.判断 在想要显示的Fragment之前是否存在fragment
//保留当前可见的Fragment
private Fragment currentFragment;
在第一次显示Fragment时这个对象是空的
如果不为空将上一个(current)Fragment隐藏,显示当前点击的Fragment,然后把当前(被点击的)的Fragment赋值给(current)Fragment
//在添加之前先将上一个Fragment隐藏掉
if (currentFragment != null) {
transaction.hide(currentFragment);
}
transaction.add(R.id.main_fram, fragment, fTag);
transaction.commit();
//更新可见
currentFragment = fragment;
这是fragment不存在于栈中的情况下 ,如果存在于栈中就不用add,直接show出来就好了
transaction.show(fragment);
transaction.hide(currentFragment);
//更新可见
currentFragment = fragment;
transaction.commit();
那么整体代码
private void addFragment(String fTag) {
//判断这个标签是否存在Fragment对象,如果存在则返回,不存在返回null
fragment = (BaseFragment) manager.findFragmentByTag(fTag);
// 如果这个fragment不存于栈中
if (fragment == null) {
//初始化Fragment事物
transaction = manager.beginTransaction();
//根据RaioButton点击的Button传入的tag,实例化,添加显示不同的Fragment
if (fTag.equals("home")) {
fragment = new HomeFragment();
} else if (fTag.equals("help")) {
fragment = new HelpFragment();
} else if (fTag.equals("setting")) {
fragment = new SettingFragment();
}
//在添加之前先将上一个Fragment隐藏掉
if (currentFragment != null) {
transaction.hide(currentFragment);
}
transaction.add(R.id.main_fram, fragment, fTag);
transaction.commit();
//更新可见
currentFragment = fragment;
} else {
//如果添加的Fragment已经存在,则将隐藏掉的Fragment再次显示,其余当前
transaction = manager.beginTransaction();
transaction.show(fragment);
transaction.hide(currentFragment);
//更新可见
currentFragment = fragment;
transaction.commit();
}
}
方法的调用
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
switch (checkedId) {
case R.id.main_home_rb:
addFragment(HOME);
break;
case R.id.main_setting_rb:
addFragment(SETTING);
break;
case R.id.amain_help_rb:
addFragment(HELP);
break;
}
}
});
写了这么多字不知道看这篇博客的你有没有看懂呢~
下面奉上Fragment声明周期图,Android面试必备!
图片有些不清楚,可以先复制保存到电脑上然后再查看