19、Fragment

一、Fragment

1.1、fragment介绍

fragment的出现是为了同时适应手机和平板,可以将其看做Activity的组成部分,甚至Activity界面完全由不同的Fragment组成,它拥有自己的生命

周期和接收、处理用户的事件,更为重要的是,可以动态的添加、替换和移除某个Fragment。

1.2、fragment版本

由于Fragment是在 3.0 后才有的,要使用 Fragment SDK 版本需要 大于 11; 由于Fragment的广泛使用,google 后期在V4包中提供了Fragment的支持.

在实际开发过程中,V4 包中Fragment 得到广泛使用。

1.3、fragment兼容

由于Fragment是在 3.0 后才有的,要使用 Fragment SDK 版本需要 大于 11; 由于Fragment的广泛使用,google 后期在V4包中提供了 Fragment的支持.

在实际开发过程中,V4 包中Fragment 得到广泛使用

a)新建Class继承android.app.Fragment(sdk>11)或android.support.v4.app.Fragment(通用,建议使用)

b)重写fragment中的onCreateView()方法。

public class MyFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {/**Inflate the layout for this fragment*/return inflater.inflate(R.layout.left_fragment, container,false);}
}

注意:inflater.inflate(R.layout.your_fragment_layout, container, false);中的参数必须为false

1.4、fragment生命周期

Fragment必须是依存于Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系:

image

可以看到Fragment比Activity多了几个额外的生命周期回调方法:

image

注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现。

生命周期

①Activity加载Fragment的时候,依次调用方法: onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart ->onResume

②当Fragment所在的Activity可见,但不获得焦点:onPause

③当对话框关闭,Activity又获得焦点: onResume

④当我们替换Fragment,并调用addToBackStack()将他添加到Back栈中 onPause -> onStop -> onDestoryView 

注意,此时的Fragment还没有被销毁哦!!!

⑤当我们按下键盘的回退键,Fragment会再次显示出来: onCreateView -> onActivityCreated -> onStart -> onResume

⑥如果我们替换后,在事务commit之前没有调用addToBackStack()方法将 Fragment添加到back栈中的话;又或者退出了Activity的话,那么Fragment将会被完全结束,

  Fragment会进入销毁状态 onPause -> onStop -> onDestoryView -> onDestory -> onDetach

1.5、静态加载

a) 创建Activity继承于FragmentActivity

b) 创建Fragment,分别为LeftFragment以及RightFragment,2.3.3版本需要导入的是v4包中的fragment

public class LeftFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {/** Inflate the layout for this fragment */return inflater.inflate(R.layout.left_fragment, container, false);}
}

c) 创建fragment的布局,比较简单这里直接省略

d) 在activity的布局中使用fragment

<fragmentandroid:id="@+id/left_fragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"class="cn.legend.fragment.LeftFragment" />
<fragmentandroid:id="@+id/right_fragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="2"class="cn.legend.fragment.RightFragment" />

配置过程中,Activity的布局文件内必须指定fragment的class或android:name为对应的Fragment的全包名类名。(通用性和灵活性不强)

adc9823c-5c47-474a-8872-39d346f183dc

1.6、动态加载

可以非常灵活的对Activity的视图进行增加和移除等操作,开发中推荐使用动态加载。

1.fragment实例

FragmentManager是Activity的中用来添加和移除Fragment的工具,因此FragmentManager是在Activity中使用的,也是在Activity中获得的。

a) SDK > 11

FragmentManager fm = getFragmentManager();

b) 通用V4包(Activity必须继承FragmentActivity)

FragmentManager fm = getSupportFragmentManager();

2.fragment添加

a)为Activity新建布局文件,采用FrameLayout当做容器,这样方便于两个fragment切换,并给其创建唯一ID。

b)在Activity的onCreate()方法中加载fragment,注意3.0版本Activity继承Activity,3.0以下需要继承FragmentActivity。

Fragment leftFragment = new LeftFragment();
Fragment rightFragment = new RightFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.activity_add_container,leftFragment,"fragment_left");
transaction.hide(R.id.activity_add_container,rightFragment,"fragment_right");
transaction.show(leftFragment);
transaction.commit();

3.fragment替换

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.activity_add_container,new LeftFragment(),"fragment_left");
transaction.commit();

4.fragment移除

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.activity_add_container,new LeftFragment(),"fragment_left");
transaction.commit();

4.fragment移除

transaction.remove(Fragment);

5.子fragment管理器

如果存在fragment嵌套fragment的情况,我们想获取fragment的管理器则需要调用以下方式:

FragmentManager childFragmentManager = getChildFragmentManager();

1.7、Fragment的onTouchEvent

fragment默认是没有提供onTouchEvent事件的,如果我们想在fragment中做手势识别则需要用到宿主Activity来相应事件,具体操作如下:

a)在Activity中创建内部接口,并对外提供注册touch事件的方法,由于可能存在多个fragment需要相应touch事件,所以将touch事件放入ArrayList中

/**实现监听触摸事的接口,让fragment去实现*/
private ArrayList<MyOnTouchListener> onTouchListeners = new ArrayList<MyOnTouchListener>(10);
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {for (MyOnTouchListener listener : onTouchListeners) {listener.onTouch(ev);}return super.dispatchTouchEvent(ev);
}
public void registerMyOnTouchListener(MyOnTouchListener myOnTouchListener) {onTouchListeners.add(myOnTouchListener);
}
public void unregisterMyOnTouchListener(MyOnTouchListener myOnTouchListener) {onTouchListeners.remove(myOnTouchListener);
}
public interface MyOnTouchListener {public boolean onTouch(MotionEvent ev);
}

b) 让需要响应touch事件的fragment来实现上方的activity中所提供的内部接口即可。

mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {//手指在屏幕上滑动//e1,e2:手指的事件:手指第一次触摸屏幕触发->手指离开屏幕触发//vX vY:水平和垂直方向的速度
    @Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2,float velocityX, float velocityY) {//过滤掉Y的移动if(Math.abs(e1.getRawY()-e2.getRawY())>150){Toast.makeText(mActivity,"手势无效", Toast.LENGTH_SHORT).show();return false;}if(e1.getRawX()-e2.getRawX()>30){//从右向左滑,显示下一个界面
            showState();return true;}else if (e2.getRawX()-e1.getRawX()>30) {//从左向右滑,显示上一个界面
            showOrder();return true;}return super.onFling(e1, e2, velocityX, velocityY);}
});
mMyTouchListener = new NewFrameActivity.MyOnTouchListener() {@Overridepublic boolean onTouch(MotionEvent ev) {return mGestureDetector.onTouchEvent(ev);}
};
mParentActivity = (NewFrameActivity)getActivity();
mParentActivity.registerMyOnTouchListener(mMyTouchListener);

上述所使用到的动画效果,在下方会继续进行讲解。

1.8、fragment切换动画

Fragment的转场动画实现分为使用v4包和不使用v4包两种情况,不使用v4包的话,最低API Level需要是11。

1.标准过渡动画

可以给Fragment指定标准的转场动画,通过setTransition(int transit)方法。
该方法可传入的三个参数是:
TRANSIT_NONE,
TRANSIT_FRAGMENT_OPEN,
TRANSIT_FRAGMENT_CLOSE
分别对应无动画、打开形式的动画和关闭形式的动画。标准动画设置好后,在Fragment添加和移除的时候都会有。

2.自定义过渡动画

a)自定义转场动画是通过setCustomAnimations()方法,因为Fragment添加时可以指定加入到Back Stack中,所以转场动画有添加、移除、从Back stack中pop出来,

还有进入四种情况。注意:setCustomAnimations()方法必须在add、remove、replace调用之前被设置,否则不起作用。

  b)不使用v4包的情况下(min API >=11)所对应的动画类型是Property Animation。即动画资源文件需要放在res\animator\目录下,且根标签是<set>, <objectAnimator>,

or <valueAnimator>三者之一。这一点也可以从Fragment中的这个方法看出:onCreateAnimator(int transit, boolean enter, int nextAnim),返回值是Animator。

  c)自定义转场动画时,四个参数的形式setCustomAnimations (int enter, int exit, int popEnter, int popExit)是API Level 13才有的,11只引入了两个动画的形式,

即无法指定Back Stack栈操作时的转场动画

private void addFragment() {if (mFragmentManager == null) {mFragmentManager = getFragmentManager();}mTextFragmentOne = new MyFragmentOne();FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();/**标准动画*/// fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);// fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);// fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);/**自定义动画*/// API LEVEL 11
    fragmentTransaction.setCustomAnimations(R.animator.fragment_slide_left_enter,R.animator.fragment_slide_right_exit);// API LEVEL 13// fragmentTransaction.setCustomAnimations(R.animator.fragment_slide_left_enter,R.animator.fragment_slide_left_exit,// R.animator.fragment_slide_right_enter,R.animator.fragment_slide_right_exit);
    fragmentTransaction.add(R.id.container, mTextFragmentOne);// 加入到BackStack中fragmentTransaction.addToBackStack(null);fragmentTransaction.commit();
}

其中下面四个动画是从apiDemos中提取的,3.0之后的动画的根标签是set,而3.0之前的动画是不一样的。

fragment_slide_left_enter:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><objectAnimatorandroid:interpolator="@android:interpolator/decelerate_quint"android:valueFrom="100dp" android:valueTo="0dp"android:valueType="floatType"android:propertyName="translationX"android:duration="@android:integer/config_mediumAnimTime" /><objectAnimatorandroid:interpolator="@android:interpolator/decelerate_quint"android:valueFrom="0.0" android:valueTo="1.0"android:valueType="floatType"android:propertyName="alpha"android:duration="@android:integer/config_mediumAnimTime" />
</set>

fragment_slide_left_exit:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><objectAnimatorandroid:interpolator="@android:interpolator/decelerate_quint"android:valueFrom="0dp" android:valueTo="-100dp"android:valueType="floatType"android:propertyName="translationX"android:duration="@android:integer/config_mediumAnimTime" /><objectAnimatorandroid:interpolator="@android:interpolator/decelerate_quint"android:valueFrom="1.0" android:valueTo="0.0"android:valueType="floatType"android:propertyName="alpha"android:duration="@android:integer/config_mediumAnimTime" />
</set>

fragment_slide_right_enter:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><objectAnimatorandroid:interpolator="@android:interpolator/decelerate_quint"android:valueFrom="-100dp" android:valueTo="0dp"android:valueType="floatType"android:propertyName="translationX"android:duration="@android:integer/config_mediumAnimTime" /><objectAnimatorandroid:interpolator="@android:interpolator/decelerate_quint"android:valueFrom="0.0" android:valueTo="1.0"android:valueType="floatType"android:propertyName="alpha"android:duration="@android:integer/config_mediumAnimTime" />
</set>

fragment_slide_right_exit:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><objectAnimatorandroid:interpolator="@android:interpolator/decelerate_quint"android:valueFrom="0dp" android:valueTo="100dp"android:valueType="floatType"android:propertyName="translationX"android:duration="@android:integer/config_mediumAnimTime" /><objectAnimatorandroid:interpolator="@android:interpolator/decelerate_quint"android:valueFrom="1.0" android:valueTo="0.0"android:valueType="floatType"android:propertyName="alpha"android:duration="@android:integer/config_mediumAnimTime" />
</set>

使用v4包,Fragment的使用不再局限于API Level 11之上,低等级的API也可以使用,但是这时候转场动画的类型是View Animation。动画资源放在res\anim\路径下。

Fragment中的方法:onCreateAnimation(int transit, boolean enter, int nextAnim)返回值Animation。

FragmentTransaction中的setCustomAnimations()方法,两参数类型和四参数类型都可用。

所以一般还是用v4包的这个版本,一是兼容性比较好,另外View Animation其实基本可以满足转场动画的需要。

private void addFragment() {if (null == mFragmentManager) {mFragmentManager = getSupportFragmentManager();}mTextFragmentOne = new MyFragmentOne();FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();fragmentTransaction.setCustomAnimations(R.anim.push_left_in,R.anim.push_left_out,R.anim.push_left_in,R.anim.push_left_out);fragmentTransaction.add(R.id.container, mTextFragmentOne);fragmentTransaction.addToBackStack(null);fragmentTransaction.commit();
}

早期版本所使用到的转场动画请参考手势识别篇的动画。

1.9、回退栈

在使用Fragment的时候我们一般会这样写

对于是否需要添加transaction.addToBackStack(null),也就是将Fragment添加到回退栈。取决于你是否要在回退的时候显示上一个Fragment。

2.0、Fragment通信

b3d974cf-1b41-4260-9217-5bd592d1b412

1)组件获取

Fragment获得Activity中的组件: getActivity().findViewById(R.id.list);
Activity获得Fragment中的组件(根据id或tag也行):getFragmentManager.findFragmentByid(R.id.fragment1)

2)数据传递

①Activit传递数据给Fragment:

   在Activity中创建Bundle数据包,调用Fragment实例的setArguments(bundle) 从而将Bundle数据包传给Fragment,然后Fragment中调用getArguments获得 Bundle对象,进行解析即可。

②Fragment传递数据给Activity

在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口, Fragment就可以通过回调接口传数据了,回调,。

Step 1:定义一个回调接口:(Fragment中)

public interface CallBack{  /*定义一个获取信息的方法*/  public void getResult(String result);  
}

Step 2:接口回调(Fragment中)

/*接口回调*/  
public void getData(CallBack callBack){  /*获取文本框的信息,当然你也可以传其他类型的参数,看需求咯*/  String msg = editText.getText().toString();  callBack.getResult(msg);  
}

Step 3:使用接口回调方法读数据(Activity中)

leftFragment.getData(new CallBack() {  @Override  public void getResult(String result) {Toast.makeText(MainActivity.this, "-->>" + result, 1).show();  }}); 
}

总结:

在Fragment定义一个接口,接口中定义抽象方法,需要传什么类型的数据参数就设置什么类型;
接着写一个调用借口中的抽象方法,把要传递的数据传过去 然后就是Activity了,调用Fragment提供的那个方法,然后重写抽象方法的时候进行数据的读取即可。

 

2.1、Fragment中的回调

我们知道在Activity中想要获取开启的另外一个Activity中的返回值,可以通过startActivityForResult来开启,然后在本Activity中实现onActivityResult方法并监听结果值即可。

其实在Frament中也是一样的,不过关于Fragment的回调可能存在以下几种情况:

1、Fragment中直接开启Activity

  这种情况下可以直接在Fragment中开启Activity即可。

2、Fragment中存在listView,我们在Adapter中进行开启

  这种情况我们需要在Adapter中获取Fragment实例,并调用startActivityForResult方法。

3、Fragment多层嵌套的时候

  在多层嵌套的情况下,我们首先看Activity中是否实现了OnActivityResult方法,并切忌不要删除Activity中的super.OnActivityResult即可。

 

转载于:https://www.cnblogs.com/pengjingya/p/5509102.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/252388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

喜好:

不喜欢吃&#xff1a;一瓣瓣的蘑菇、海带、豆腐皮、 不喜欢喝&#xff1a;鱼汤&#xff1b; 不喜欢吃&#xff1a;山楂片、法式小面包&#xff08;软软的&#xff09;、果冻、 不喜欢喝&#xff1a;对饮料无感、不喜欢脉动、可乐雪碧等少量还行、 喜欢&#xff1a;啃骨头、排骨…

将TUM数据集制作成BundleFusion数据集

在上一篇文章中,我写到了如何将TUM数据生成BundleFusion所需要的数据集,生成的数据集如下图中所示.并且是将每一组数据的groundtruth.txt中的位姿数据写如到这里的pose文件中,作为每一帧图像的先验位姿. 今天我便将生成的数据集转换为了.sens格式,然后运行bundlefusion算法,第…

每一次突破都是一种进步

一直以来&#xff0c;我接触一门新技术&#xff0c;都是先看开发文档&#xff0c;了解了这个技术是做什么的&#xff0c;能做什么。但是不知道怎么起步&#xff0c;也不敢贸然动手。我的解决办法是看视频&#xff0c;看别人怎么使用&#xff0c;跟着别人做&#xff0c;然后听别…

mysql盲注学习-1

mysql: 1.left() //left()函数 left(a,b)从左侧截取a,的b位 2.mid() //mid()函数 参数 描述 column_name 必需。要提取字符的字段。 start 必需。规定开始位置&#xff08;起始值是 1&#xff09;。 length 可选。要返回的字符数。如果省略&#xff0c;则 MID() 函数…

二分学习笔记

写在前面 二分是一种常用且非常精妙的算法&#xff0c;常常是我们解决问题的突破口。二分的基本用途是在单调序列或单调函数中做查找。因此当问题的答案具有单调性时&#xff0c;就可以通过二分把求解转化为判定。进一步地&#xff0c;我们还可以通过三分法解决单调函数的极值以…

解析.sens数据集

python脚本在下面网址中https://github.com/ScanNet/ScanNet/tree/master/SensReader/python 一定要使用python2运行此脚本. 使用指令如下 python reader.py --filename /media/yunlei/YL/DATASETS/ICL_DATABASE/lr_kt1/living_room_traj1n_frei_png.sens --output_path /me…

ConcurrentHashMap 解读

初始化&#xff1a; 问题&#xff1a;如何当且仅只有一个线程初始化table 1 private final Node<K,V>[] initTable() {2 Node<K,V>[] tab; int sc;3 while ((tab table) null || tab.length 0) {4 if ((sc sizeCtl) < 0)5 …

XML Schema 基本结构

<?xml version1.0?> <Schema name"cangchuSchema" metamodelVersion"4.0"><PhysicalSchema><Table name"highway_toll"><Key><Column name"uid"/></Key></Table><Table name&qu…

关于系统自带 .NET Framework 版本的说明

系统自带版本&#xff1a; Windows XP (SP3) .NET Framework 1.1Windows 7 (SP1) .NET Framework 3.5.1Windows 8.1 .NET Framework 4.5.1Windows 10 (1507) .NET Framework 4.6Windows 10 (1511) .NET Framework 4.6.1Windows 10 (1607) .NET Framework 4.6.2Windows 10 (1703…

BundleFusion那些事儿

背景&#xff1a;前面几篇博客中写了很多关于BundleFusion的东西&#xff0c;主要包括bundlefusion的论文阅读笔记&#xff0c;.sens数据集的生成等&#xff0c;经过最近几天的工作&#xff0c;我对bundlefusion又有了新的技术积累&#xff0c;在这里整理一下&#xff0c;也算是…

问题:图片怎么保存到数据库, 以及怎么把图片从数据库中取出来使用?(已解决)...

简单&#xff0c;不保存图片到数据库&#xff0c;而是图片的路径。 也就是说&#xff0c;先把图片下载到服务器的指定目录下&#xff0c;然后&#xff0c;在把相对的路径保存到数据库中。 如果下次获取图片&#xff0c;就访问数据库&#xff0c;获取图片路径&#xff0c;然后根…

Oracle Study之--Oracle 11gR2通过RMAN克隆数据库

Oracle Study之--Oracle 11gR2通过RMAN克隆数据库Purpose of Database Duplication A duplicate database is useful for a variety of purposes, most of which involve testing. You can perform the following tasks in a duplicate database: Test backup and recovery pro…

ubuntu16.04安装evo

背景:这已经是我第二次尝试安装evo了,最近因为在bundlefusion加入groundtruth的问题搞的很烦躁,我怀疑是不是我给定的groundtruth是不是不正确,所以我就写python脚本,获取计算生成的位姿数据,写入的groundtruth位姿数据.获取数据后,将数据可视化就成了一个很重要的问题,我还是打…

前端性能优化之gzip

gzip是GNUzip的缩写&#xff0c;它是一个GNU自由软件的文件压缩程序。它最早由Jean-loup Gailly和Mark Adler创建&#xff0c;用于UNⅨ系统的文件压缩。我们在Linux中经常会用到后缀为.gz的文件&#xff0c;它们就是GZIP格式的。现今已经成为Internet 上使用非常普遍的一种数据…

luogu2770 航空路线问题 网络流

题目大意&#xff1a; 给定一张航空图&#xff0c;图中顶点代表城市&#xff0c;边代表 2 城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。(1)从最西端城市出发&#xff0c;单向从西向东途经若干城市到达最东端城市&#xff0c;然后再单向从东向…

手机录音ogg格式怎么转换mp3

Ogg这种音频格式刚出来的时候大家是非常热爱的&#xff0c;但是随着时代的发展&#xff0c;这种音频格式已经已经被取代了&#xff0c;现在呢走在音频格式前端的是MP3格式&#xff0c;这是大家都比较熟悉的&#xff0c;但是我们还是会经常下载到ogg这种格式的音频&#xff0c;就…

TP3.2设置URL伪静态满足更好的SEO效果

URL伪静态通常是为了满足更好的SEO效果&#xff0c;ThinkPHP支持伪静态URL设置&#xff0c;可以通过设置URL_HTML_SUFFIX参数随意在URL的最后增加你想要的静态后缀&#xff0c;而不会影响当前操作的正常执行。 例如&#xff0c;我们设置 URL_HTML_SUFFIX>shtml 的话&#xf…

[机器学习] 推荐系统之协同过滤算法(转)

[机器学习]推荐系统之协同过滤算法 在现今的推荐技术和算法中&#xff0c;最被大家广泛认可和采用的就是基于协同过滤的推荐方法。本文将带你深入了解协同过滤的秘密。下面直接进入正题. 1. 什么是推荐算法 推荐算法最早在1992年就提出来了&#xff0c;但是火起来实际上是最近这…

BundleFusion代码框架讲解

背景&#xff1a;前面用了几篇文章来记录和总结了&#xff0c;我在研究bundlefusion过程中遇到的一些问题以及解决方法&#xff0c;本来想实现给bundlefusion输入先验轨迹&#xff0c;然后让其根据给定的轨迹进行重建&#xff0c;这样即便在环境比较恶劣的情况下&#xff0c;也…

BundlePhobia

1、BundlePhobia用于分析npm package的依赖、bundle后的大小、下载速度预估等等&#xff0c;帮助你在引用一个package之前了解引入该package的代价。 2、也可以将项目的package.json文件上传&#xff0c;BundlePhobia会帮你评估项目中所有包的大小和加载速度。