1 Fragment简介
现在手机、平板有各种尺寸,特别是平板尺寸比较大,因此在呈现界面时可以呈现更多的内容。因此,我们可以将界面呈现动态地改变内容。
Fragment可以很好的实现这一点
Fragment又称为碎片,可以嵌套在Activity中使用,也有自己的生命周期(当然也与Activity的生命周期有关) 他可以很好的解决大屏幕的适配问题
2 Fragment生命周期
过程:
先与Activity 连接 (OnAttach()),再创建Fragment(OnCreate()),再创建Fragment的视图(OnCreateView()) 当Activity的Oncreate返回时调用(OnActivityCreate())
onStart()
onResume()
onPause()
onPause()
onDestroy()
和Activity原理类似 只是换成了Fragment
destroy时,先 销毁视图(onDestroyView()) 再销毁Fragment (onDestroy()) 最后解除与Activity的连接(onDetach())
所有Fragment和Activity生命周期绑定,ACtivity回调啥所有Fragment就会回调啥
从该Fragment切换到其他Fragment:
onPause()
onStop()
onDestroyView()
切换回本身的Fragment:
onCreateView()
onActivityCreated()
onStart()
onResume()
Fragment不可见(屏幕熄灭或回到桌面,或者跳转其他界面)
回调Activity的onPause() onStop()
回调所有Fragment的onPause() onStop()
Fragment所在的Activity从不可见到可见
回调Activity的onStart()和onResume()
回调所有Fragment的onStart() 和 onResume()
3 常见使用
1 如首次开启软件的动画,左右滑动看软件相关内容
2 广告 切换不同的广告内容
3 滑动切换界面
fragmentManager 管理fragment栈
// 加入栈顶 tag可为空 调用commit()可以返回id
addToBackStack(tag)
// 出栈顶
popBackStack()
// 出某个tag/id的栈
// 其中id表示提交变更时commit()的返回值。
popBackStack(int id, int flags)
// 其中name是addToBackStack(String tag)中的tag值。
// flag: 0不包括该栈 POP_BACK_STACK_INCLUSIVE包括该栈
popBackStack(String name, int flags):
4 Fragment创建
1 直接去右键 new 一个 Fragment的布局
这里有3个可勾选项:
① create layout xml? 是否创建XML文件 一般为勾选
② include fragment factory methods? 是否创建工厂方法 (用于fragment方法的调用) 根据情况勾选
③ include interface callbacks? 是否为Fragment创建回调接口 根据情况勾选
2 这时会生成一个继承Fragment的类
并且重写了 onCreateView()方法
5 Fragment使用
Fragment可以加入到Activity中使用,并且对Fragment内容的操作在Fragment.java文件中,这样可以减少Activity的复杂度,并且可以更好的重用Fragment
1 静态方式
直接在想加入fragment的Activity的布局的XML文件中加入< fragment>标签即可
记得加name属性
android:name=fragment的完整包路径
2 动态方式
在Activity的java代码中
// 1 创建 你创建的Fragment对象
MyFragment myFragment = new MyFragment();
// 2 创建 FragmentManager对象
FragmentManager fm = getFragmentManager();
// 3 创建 FragmentTransaction对象
FragmentTransaction ft= fm.FragmentTransaction();
// 4 建立连接
ft.add(要加入的资源id名, myFragment );
ft.commit();
结束当前fragment所在Activity
getActivity().finish();
要建立与XML的连接(findViewById)
//在自动生成的 onViewCreate()中:
return inflater.inflate(R.layout.fragment_fragment4, container, false);
//改成:
View view = inflater.inflate(R.layout.fragment_fragment4, null, false);
TextView fragment4textView0 = view.findViewById(R.id.fragment4textView0);
//后面就可以写 findViewById了 (要加view.)
//最后再
return view;
Fragment-> Activity
Intent intent_1 = new Intent(getActivity(),LoginActivity.class);
startActivity(intent_1);
Activity->Fragment
1 到指定的Fragment
Intent intent = new Intent(UserLoginActivity.this,MainActivity.class);
intent.putExtra("userloginflag", 1);
startActivity(intent);
先跳到 装载Fragment的Activity上
再在Activity的onResume中
根据传过来的 值去跳转不同Fragment
protected void onResume() {
int id = getIntent().getIntExtra("userloginflag", 0);
if (id == 1 ) {
mTabHost.setCurrentTab(3);
}
super.onResume();
}
2 想从这个activity中再跳转回fragment
直接finish这个activity即可
获取别的界面的回传跳转到不同的Fragment(结合BottomNavigationBar使用)
BottomNavigationBar使用地址:http://blog.csdn.net/weixin_37577039/article/details/79058838
// 设置一个默认的 选择值
private int FIRSTSELECTEDPOSITION=2;
// 获取回传值
Intent intent =getIntent();
FIRSTSELECTEDPOSITION=intent.getIntExtra("flag",2);//后一个数值为 前一个不存在时 指定的一个默认值
// 在bottomNavigationBar中设置
.setFirstSelectedPosition(FIRSTSELECTEDPOSITION)// 设置底部点击的初始位置
6 实际使用 —— 根据点击不同导航栏显示不同主体内容
参考博客:使用materia-design设计的底部导航栏BottomNavigationBar
public interface MyTouchListener {
public void onTouchEvent(MotionEvent event);
}
// 保存MyTouchListener接口的列表
private ArrayList<MyTouchListener> myTouchListeners = new ArrayList<MainActivity.MyTouchListener>();
/**
* 提供给Fragment通过getActivity()方法来注册自己的触摸事件的方法
* @param listener
*/
public void registerMyTouchListener(MyTouchListener listener) {
myTouchListeners.add(listener);
}
/**
* 提供给Fragment通过getActivity()方法来取消注册自己的触摸事件的方法
* @param listener
*/
public void unRegisterMyTouchListener(MyTouchListener listener) {
myTouchListeners.remove( listener );
}
/**
* 分发触摸事件给所有注册了MyTouchListener的接口
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
for (MyTouchListener listener : myTouchListeners) {
listener.onTouchEvent(ev);
}
return super.dispatchTouchEvent(ev);
}
Fragment中,implements MainActivity.MyTouchListener
@Override
Public boolean onTouch(MotionEvent event){
Log.d("test","ontouchevent!");
Return detector.onTouchEvent(event);
}
onCreateView中:
MainActivity.MyTouchListener myTouchListener = new MainActivity.MyTouchListener() {
@Override
public boolean onTouch(MotionEvent event) {
// 处理手势事件
return true;
}
};
// 将myTouchListener注册到分发列表
((MainActivity)this.getActivity()).registerMyTouchListener(myTouchListener);
return view;
参考:
http://blog.csdn.net/seeytom/article/details/39294657
问题一、transaction.replace时 报错
'replace(int, android.app.Fragment)' in 'android.app.FragmentTransaction' cannot be applied
to '(int, com.biniu.bottomnavigationbardemo.CRM.customerDetails.CustomerDetailsFragment1)'
因为fragment有两种 :
import android.support.v4.app.Fragment;
//或者
import android.app.Fragment;
这里的replace的第二个参数的fragment要为第二种 :app.Fragment形式的
问题二、
java.lang.RuntimeException: Unable to start activity ComponentInfo XXXXXX must implement OnFragmentInteractionListener
解决 加上接口
implements YourFragment.OnFragmentInteractionListener
问题三、IllegalStateException: Can not perform this action after onSaveInstanceState
原因:在这个onSaveInstance之后 执行fragment的commit方法 会导致Activity没有保存到fragment的状态而导致fragment状态丢失
解决:1 可以使用commitAllowingStateLoss //不管丢失还是执行commit操作
2 Activity显示情况下才进行fragment的修改