Android动画+Fragment
导语
Fragment介绍 动画介绍
一、Fragment
1、为什么要使用fragment(Android 3.0 API 2011 开始)
- 适配大屏幕
- 用途:在一个Activity里切换界面,切换界面时只切换Fragment里面的内容
2、如何使用fragment
- fragment 理解成迷你activity,依托于activity存活,如果activity挂了,fragment也挂了。
2.1. 写一个类继承 Fragment
2.2. 重写onCreateView()方法,返回当前fragement显示的view对象。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//返回一个view对象
}
2.3. 在activity获取Fragment01对象
Fragment01 fg1 = new Fragment01();
2.3.1. 在activity获取到碎片管理器 FragmentManager
FragmentManager fm = getFragmentManager();
2.4. 如果要更新界面要保证同时成功或者同时失败,开启事务
FragmentTransaction ft = fm.beginTransaction();
2.5. 替换activity界面某个容器里面显示的内容(fragment)
ft.replace(R.id.container, new Fragment03());
ft.add();
ft.remove();
2.6. 如果要更新界面要保证同时成功或者同时失败,提交事务
ft.commit();
3、使用fragment细节
写一个类继承 Fragment,并定义一个布局文件作为Fragment的显示内容(先要定义一个布局文件)
public class Fragment01 extends Fragment {
//与ListAdapter中的getView方法类似
//此方法返回的View对象就是Fragment显示的内容
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//用布局文件填充成一个View对象,返回出去,那么就显示在Fragment上了
View view = inflater.inflate(R.layout.fragment01, null);
return view ;
}
}
把Fragment显示至指定ViewGroup中
//把fragment显示至界面
//new出fragment对象
Fragment01 fg = new Fragment01();
FragmentManager fm = getFragmentManager();
//开启事务
FragmentTransaction ft = fm.beginTransaction();
//把fragment对象显示到指定资源id的组件里面
ft.replace(R.id.fl, fg);
ft.commit();
3.2使用fragment示例
//Activity界面显示fragment01
public void click1(View v){
//1 获取Fragment01对象,//Fragment01对象的onCreateView返回一个view对象
Fragment01 fg1 = new Fragment01();
//2.获取fragment管理器
FragmentManager fm = getFragmentManager();
//3.开启事务
FragmentTransaction ft = fm.beginTransaction();
//4.把fg1设置显示在帧布局中
ft.replace(R.id.fl, fg1);
//5.提交事务
ft.commit();
}
4、生命周期
- 生命周期方法跟Activity一致,可以理解把其为就是一个Activity
- fragment切换时会销毁旧的,再创建新的
- fragment切换时旧fragment对象会销毁,新的fragment对象会被创建
- 完整生命周期
oncreate-->oncreateView-->onstart-->onresume-->onpause--->onstop---ondestroy
- 可视生命周期
onstart-->onresume-->onpause--->onstop
- 前台生命周期
onresume-->onpause
5、低版本兼容
- 在support-v4.jar包中有相关api,也就是说fragment可以在低版本模拟器运行
- 使用 support-v4.jar包。包含有新版本sdk的AP 。
- 替换所有的导包 android.app.* —> android.support.v4.app.*;
- 继承activity的时候 换成 FragmentActivity
- getFragmentManager() —>getSupportFragmentManager();
- 在实际开发当中,基本上使用的都是v4包里面的fragement
–示例–
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends FragmentActivity {
private Fragment01 fg1;
private LinearLayout ll;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll = (LinearLayout) findViewById(R.id.ll);
//1 获取Fragment01对象
fg1 = new Fragment01();
//2.获取fragment管理器
FragmentManager fm = getSupportFragmentManager();
//3.开启事务
FragmentTransaction ft = fm.beginTransaction();
//4.把fg1设置显示在帧布局中
ft.replace(R.id.fl, fg1);
//5.提交事务
ft.commit();
//
fg1.setLinearLayout(ll);
}
//显示fragment01
public void click1(View v){
//1 获取Fragment01对象
//Fragment01 fg1 = new Fragment01();
//2.获取fragment管理器
FragmentManager fm = getSupportFragmentManager();
//3.开启事务
FragmentTransaction ft = fm.beginTransaction();
//4.把fg1设置显示在帧布局中
ft.replace(R.id.fl, fg1);
//5.提交事务
ft.commit();
}
//显示fragment02
public void click2(View v){
//1 获取Fragment01对象
Fragment02 fg2 = new Fragment02();
//2.获取fragment管理器
FragmentManager fm = getSupportFragmentManager();
//3.开启事务
FragmentTransaction ft = fm.beginTransaction();
//4.把fg1设置显示在帧布局中
ft.replace(R.id.fl, fg2);
//5.提交事务
ft.commit();
}
//显示fragment03
public void click3(View v){
//1 获取Fragment01对象
Fragment03 fg3 = new Fragment03();
//2.获取fragment管理器
FragmentManager fm = getSupportFragmentManager();
//3.开启事务
FragmentTransaction ft = fm.beginTransaction();
//4.把fg1设置显示在帧布局中
ft.replace(R.id.fl, fg3);
//5.提交事务
ft.commit();
}
}
6、activity与fragement的数据传递
6.1 从activity——->Fragment数据传递
- 1 获取activity中EditView中的数据,通过Fragment对象调用方法传递数据
public void click4(View v){ //获取用户输入的数据 EditText et_main = (EditText) findViewById(R.id.et_main); String text = et_main.getText().toString(); //获取Fragment02对象 Fragment02 fg2= new Fragment02(); //调用Fragment02对象的setText()方法,将数据作为参数传递 fg2.setText(text); }
- 2 在Fragment中,获取方法传递过来的数据,并对数据进行操作
public void setText(String text) { //获取传递过来的数据,并对数据进行操作 //获取输入控件 EditText tv_fragment2= (EditText) view.findViewById(R.id.tv_fragment2); //给输入控件设置数据,显示在桌面 tv_fragment2.setText(text); }
6.2 从Fragment——->activity数据传递
- 1 在Fragment的java类中获取用户输入的数据,调用activity对象方法,传递数据
//获取按钮控件 Button bt_fragment03 = (Button) view.findViewById(R.id.bt_fragment03); //设置按钮点击事件,发送用户输入数据到activity bt_fragment03.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //查找EditText控件,得到用户输入数据 EditText et = (EditText) view.findViewById(R.id.et); String text = et.getText().toString(); //获取Activity对象,调用其.setText()方法,传递数据(作为参数传递) ((MainActivity)getActivity()).setText(text); } });
- 2 在Activity中,获取方法传递过来的数据,并对数据进行操作
public void setText(String text) { //查找EditText控件 EditText et_main = (EditText) findViewById(R.id.et_main); //操作数据,将数据显示在桌面上 et_main.setText(text); }
二 动画
2.1 帧动画 FrameAnimation
一张张图片不断的切换,形成动画效果
- 1 在drawable-hdpi中添加一张张图片
- 2 在drawable目录下定义xml文件,子节点为animation-list,在这里定义要显示的图片和每张图片的显示时长
- 2.1 android:oneshot=”false” true表示一次,false表示重复多次
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false"
>
<item android:drawable="@drawable/g1" android:duration="200" />
<item android:drawable="@drawable/g2" android:duration="200" />
<item android:drawable="@drawable/g3" android:duration="200" />
<item android:drawable="@drawable/g4" android:duration="200" />
<item android:drawable="@drawable/g5" android:duration="200" />
<item android:drawable="@drawable/g6" android:duration="400" />
<item android:drawable="@drawable/g7" android:duration="400" />
<item android:drawable="@drawable/g8" android:duration="400" />
<item android:drawable="@drawable/g9" android:duration="200" />
<item android:drawable="@drawable/g10" android:duration="200" />
<item android:drawable="@drawable/g11" android:duration="200" />
</animation-list>
- 3 在屏幕上播放帧动画(先要在布局文件中设置ImageView),根据Drawable Animation文档写
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView iv = (ImageView) findViewById(R.id.iv); //设置imageview的背景图//把动画文件设置为imageView的背景 iv.setBackgroundResource(R.drawable.frameanimation); AnimationDrawable ad = (AnimationDrawable)iv.getBackground(); //开始播放帧动画 ad.start(); } }
2.2 补间动画(TweenAnimation),实现ImageView(图片控件)的位移、旋转、缩放、透明
- 原形态变成新形态时为了过渡变形过程,生成的动画就叫补间动画,不携带属性
- 位移、旋转、缩放、透明
ImageView(图片控件)的位移:
- 关于位移动画对象TranslateAnimation构造方法参数的详解
构造方法1:
TranslateAnimation ta = new TranslateAnimation(10, 100, 20, 170);
* 10:动画的x轴开始位置
* iv的x坐标+10
* 100:动画的x轴结束位置
* iv的x坐标+100
* 20:动画的y轴开始位置
* iv的y坐标 + 20
构造方法2.1:
TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 3,
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
* 0.5f:动画的x轴开始位置
* iv的x坐标 + 0.5 * iv宽度
* 3:动画的x轴结束位置
* iv的x坐标 + 3 * iv的宽度
构造方法2.2:
TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -0.5f, Animation.RELATIVE_TO_PARENT, 0.5f,
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
* -0.5f:动画的x轴开始位置
* iv的x坐标 - 0.5 * 父元素的宽度
* 0.5f:动画的x轴结束位置
* iv的x坐标 + 0.5 * 父元素的宽度
加深理解:对于上面的参数内容再解释一遍
构造1:
- 参数10指的是X的起点坐标,但不是指屏幕x坐标为10的位置,而是imageview的 真实X + 10
- 参数150指的是X的终点坐标,它的值是imageview的 真实X + 150
//创建为位移动画对象,设置动画的初始位置和结束位置 TranslateAnimation ta = new TranslateAnimation(10, 150, 20, 140);
构造2:
- x坐标的起点位置,如果相对于自己,传0.5f,那么起点坐标就是 真实X + 0.5 * iv宽度
- x坐标的终点位置,如果传入2,那么终点坐标就是 真实X + 2 * iv的宽度
- y坐标的起点位置,如果传入0.5f,那么起点坐标就是 真实Y + 0.5 * iv高度
- y坐标的终点位置,如果传入2,那么终点坐标就是 真实Y + 2 * iv高度
TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 2, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 2);
- 动画播放相关的设置
//设置动画持续时间 ta.setDuration(2000); //动画重复播放的次数 ta.setRepeatCount(1); //动画重复播放的模式 ta.setRepeatMode(Animation.REVERSE); //动画播放完毕后,组件停留在动画结束的位置上 ta.setFillAfter(true); anim.setInterpolator(new LinearInterpolator());// 匀速运动 anim.setRepeatCount(Animation.INFINITE);// 无限循环 //播放动画 iv.startAnimation(ta);
- ImageView位移示例
//Activity点击事件:位移补间动画 public void translate(View v){ //创建位移动画对象,填入数据(两种构造,参数不同) //TranslateAnimation ta = new TranslateAnimation(10, 100, 20, 170); ta = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -0.5f, Animation.RELATIVE_TO_PARENT, 0.4f, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0); //动画持续时间 ta.setDuration(2000); //设置播放重复次数 //ta.setRepeatCount(1); //设置重复的模式 //ta.setRepeatMode(Animation.REVERSE); //填充动画结束时的位置 ta.setFillAfter(true); //播放动画 iv.startAnimation(ta); }
ImageView(图片控件)缩放:
- 关于缩放动画对象ScaleAnimation构造方法参数的详解
构造方法1:
ScaleAnimation sa = new ScaleAnimation(0.5f, 2, 1, 3);
* 0.5f:动画开始时的组件宽度
* 0.5 * iv的宽度
* 2:动画结束时的组件宽度
* 2 * iv的宽度
构造方法2:
ScaleAnimation sa = new ScaleAnimation(0.5f, 2, 2, 0.5f, iv.getWidth() / 2, iv.getHeight() / 2);
* iv.getWidth() / 2:缩放点的x坐标
* iv的x坐标 + iv.getWidth() / 2
构造方法3:
ScaleAnimation sa = new ScaleAnimation(0.5f, 2, 2, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
* Animation.RELATIVE_TO_SELF, 0.5f:缩放点的x坐标
* iv的x坐标 + 0.5 * iv的宽度
解释
构造方法1:
- 参数0.1f表示动画的起始宽度是真实宽度的0.1倍
- 参数4表示动画的结束宽度是真实宽度的4倍
- 缩放的中心点在iv左上角
ScaleAnimation sa = new ScaleAnimation(0.1f, 4, 0.1f, 4);
构造方法3:
- 参数0.1f和4意义与上面相同
- 改变缩放的中心点:传入的两个0.5f,类型都是相对于自己,这两个参数改变了缩放的中心点
- 中心点x坐标 = 真实X + 0.5 * iv宽度
- 中心点Y坐标 = 真实Y + 0.5 * iv高度
ScaleAnimation sa = new ScaleAnimation(0.1f, 4, 0.1f, 4, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
缩放示例
//Activity点击事件:缩放补间动画
public void scale(View v){
//ScaleAnimation sa = new ScaleAnimation(0.5f, 2, 1, 3);
//ScaleAnimation sa = new ScaleAnimation(0.5f, 2, 2, 0.5f, iv.getWidth() / 2, iv.getHeight() / 2);
sa = new ScaleAnimation(0.5f, 2, 2, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(2000);
//设置播放重复次数
sa.setRepeatCount(1);
//设置重复的模式
sa.setRepeatMode(Animation.REVERSE);
//填充动画结束时的位置
sa.setFillAfter(true);
//播放动画
iv.startAnimation(sa);
}
ImageView(图片控件)透明:
- 0为完全透明,1为完全不透明。(0, 0.5f)表示有完全透明转为1/2透明
AlphaAnimation aa = new AlphaAnimation(0, 0.5f);
- ImageView(图片控件)透明示例
//Activity点击事件:透明补间动画 public void alpha(View v){ aa = new AlphaAnimation(0.1f, 0.9f); aa.setDuration(2000); //设置播放重复次数 aa.setRepeatCount(1); //填充动画结束时的位置 aa.setFillAfter(true); iv.startAnimation(aa); }
ImageView(图片控件)旋转:
- 关于旋转动画对象RotateAnimation构造方法参数的详解
构造方法2:
RotateAnimation ra = new RotateAnimation(10, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
* 10:动画开始时的角度
* 360:动画结束时的角度
构造方法1:
- 20表示动画开始时的iv的角度(20是相对于最初iv的角度)
- 360表示动画结束时iv的角度(360是相对于最最最初iv的角度)
- 默认旋转的圆心在iv左上角
- 如下
RotateAnimation ra = new RotateAnimation(20, 360);
构造方法2:
- 20,360的意义和上面一样
- 指定圆心坐标,相对于自己,值传入0.5,那么圆心的x坐标:真实X + iv宽度 * 0.5
- 圆心的Y坐标:真实Y + iv高度 * 0.5
- 如下:
RotateAnimation ra = new RotateAnimation(20, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
- ImageView(图片控件)旋转示例:
//Activity点击事件:旋转补间动画 public void rotate(View v){ //RotateAnimation ra = new RotateAnimation(10, 180); //RotateAnimation ra = new RotateAnimation(10, 360, iv.getWidth() / 2, iv.getHeight() / 2); //旋转动画对象RotateAnimation ra = new RotateAnimation(10, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ra.setDuration(2000); //设置播放重复次数 ra.setRepeatCount(1); //设置重复的模式 ra.setRepeatMode(2); ra.setFillAfter(true); iv.startAnimation(ra); }
所有动画一起飞
//Activity点击事件:补间动画一起飞
public void fly(View v){
//创建动画集合
AnimationSet as = new AnimationSet(false);//true:共用同一个插补器,false:各用个的插补器
//添加动画至集合
as.addAnimation(ta);
as.addAnimation(sa);
as.addAnimation(aa);
as.addAnimation(ra);
//播放动画集合中所有动画
iv.startAnimation(as);
}
2.3 属性动画PropertyAnimation
- 补间动画,只是一个动画效果,组件其实还在原来的位置上,xy没有改变
- 属性动画改变组件对象的属性值
3.1 位移:
- 改变x或者y坐标属性
- 第一个参数target指定要显示动画的组件
- 第二个参数propertyName指定要改变组件的哪个属性
- 第三个参数values是可变参数,就是赋予属性的新的值
- 传入0,代表x起始坐标:当前x + 0
- 传入100,代表x终点坐标:当前x + 100
//具有get、set方法的成员变量就称为属性 ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "translationX", 0, 100) ;
- 位移示例
//Activity点击事件:位移属性动画 public void translate(View v){ //创建属性动画师 //arg0:要修改的对象 //arg1:要修改对象的哪个属性 //arg2:可变参数 要把属性改成什么值 ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 0, 50, -50, 100); oa.setDuration(2000); //设置播放重复次数 //oa.setRepeatCount(1); //设置重复的模式(参数可以用1默认,2倒放模式表示) //oa.setRepeatMode(ObjectAnimator.REVERSE); oa.start(); }
3.2 缩放:
- 改变scaleX或scaleY的属性
- scaleX:水平缩放比例
- scaleY:竖直缩放比例
-
第三个参数指定缩放的比例
- 0.1是从原本高度的十分之一开始
-
2是到原本高度的2倍结束
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "scaleY", 0.1f, 2);
- 缩放示例
//Activity点击事件:缩放属性动画 public void scale(View v){ //创建属性动画师 //arg0:要修改的对象 //arg1:要修改对象的哪个属性 //arg2:可变参数 要把属性改成什么值 ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "scaleX", 0.5f, 1, 0.3f, 2); oa.setDuration(2000); oa.start(); }
3.3 透明:
- 透明度,0是完全透明,1是完全不透明
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "alpha", 0.1f, 1);
- 透明示例
//Activity点击事件:透明属性动画 public void alpha(View v){ ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.8f, 0.2f, 1); oa.setDuration(2000); oa.start(); }
3.4 旋转
- Rotation:以组件中心为旋转点旋转
- RotationX:以x轴为轴心翻转
- RotationY:以Y轴为轴心翻转
-
rotation指定是顺时针旋转
- 20是起始角度
-
270是结束角度
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "rotation", 20, 270);
- 属性指定为rotationX是竖直翻转
- 属性指定为rotationY是水平翻转
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "rotationY", 20, 180);
- 旋转示例
//Activity点击事件:旋转属性动画 public void rotate(View v){ ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotation", 0, 180, 90, 270); //ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationX", 0, 180, 90, 360); //ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationY", 0, 180, 90, 360); oa.setDuration(2000); oa.start(); }
可变参数
- 第三个参数可变参数可以传入多个参数,可以实现往回位移(旋转、缩放、透明)
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "translationX", 0, 70, 30, 100) ;
所有动画一起飞
//创建动画师集合
AnimatorSet set = new AnimatorSet();
//设置要播放动画的组件//设置改变哪个对象的属性
set.setTarget(iv);
//设置所有动画有先后顺序的播放
//set.playSequentially(oa, oa2, oa3, oa4);
//设置所有动画一起播放
set.playTogether(oa, oa2, oa3, oa4);
//开始动画播放
set.start();
- 一起飞示例
//Activity点击事件:属性动画一起飞 public void fly(View v){ //创建动画师集合 AnimatorSet as = new AnimatorSet(); //(设置要播放动画的组件)设置改变哪个对象的属性 as.setTarget(iv); //设置组件要播放什么动画 ObjectAnimator oa1 = ObjectAnimator.ofFloat(iv, "translationX", 0, 50, -50, 100); oa1.setDuration(2000); oa1.setRepeatCount(1); oa1.setRepeatMode(ObjectAnimator.REVERSE); ObjectAnimator oa2 = ObjectAnimator.ofFloat(iv, "scaleX", 0.5f, 1, 0.3f, 2); oa2.setDuration(2000); oa2.setRepeatCount(1); ObjectAnimator oa3 = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.8f, 0.2f, 1); oa3.setDuration(2000); oa3.setRepeatCount(1); oa3.setRepeatMode(ObjectAnimator.RESTART); ObjectAnimator oa4 = ObjectAnimator.ofFloat(iv, "rotation", 0, 180, 90, 270); oa4.setDuration(2000); oa4.setRepeatCount(1); oa4.setDuration(2000); //把要播放的动画对象添加至此方法中,然后所有动画会顺序播放 //as.playSequentially(oa1, oa2, oa3, oa4); //所有动画一起播放 as.playTogether(oa1, oa2, oa3, oa4); //开始动画播放 as.start(); }
2.4 可以使用xml文件定义
- 1 在animator文件夹下定义.xml文件
/res/animator/objectanimator.xml
- 根节点为objectAnimator
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="translationY"
android:duration="2000"
android:valueFrom="0"
android:valueTo="100"
android:repeatCount="1"
android:repeatMode="reverse"
>
</objectAnimator>
-
2 Activity界面点击按钮 实现xml中的动画效果
public void xml(View v){ //加载xml属性动画文件 Animator at = AnimatorInflater.loadAnimator(this, R.animator.objectanimator); at.setTarget(iv); at.start(); }