GVKun编程网logo

Android使用animator实现fragment的3D翻转效果(animate的3d旋转工具)

20

关于Android使用animator实现fragment的3D翻转效果和animate的3d旋转工具的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于3D翻转效果介绍,Android动画分

关于Android使用animator实现fragment的3D翻转效果animate的3d旋转工具的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于3D翻转效果介绍,Android动画分析、Android Fragment – 使用activity的loadermanager而不是Fragment.好吗?、Android Fragment 和 FragmentManager 的代码分析、Android FragmentManage FragmentTransaction 介绍等相关知识的信息别忘了在本站进行查找喔。

本文目录一览:

Android使用animator实现fragment的3D翻转效果(animate的3d旋转工具)

Android使用animator实现fragment的3D翻转效果(animate的3d旋转工具)

今天老师留的作业,使用俩个Fragment来实现3D翻转效果,遇到了一点点的问题,于是在网上进行了查找,但是发现有些博主的代码不正确,对其他人进行了误导,在网上使用属性动画实现3D效果非常少,所以经过我自己的实验摸索,我将自己的代码和遇到的问题给他讲解一下提供一点点借鉴,并且希望可以帮助到大家。
首先讲解一下主要实现动画的函数:

getFragmentManager().beginTransaction()
    .setCustomAnimations(R.animator.fragment_second_3d_reversal_enter,R.animator.fragment_second_3d_reversal_exit)
    .replace(R.id.container,new MainFragment()).commit();

我想信这个函数大家在实现动画时都会使用到,先获得FragmentManager然后进行transaction,主要添加动画的函数是setCustomAnimations(),在网上可以查到的解释,对这个方法有些错误,描述的是当前的Fragment对象的进入和退出时的动画效果,是这个对象的一种属性,但是这个方法真正的解释应该是在当前Activity在切换Fragment时所执行的动画方式,也就是说当前Fragment退出时用的是方法中的退出动画,新的Fragment进入时执行的是进入的动画效果,可以理解为这一次动画效果完全是利用这一个语句来完成,有些博客的记载对我们产生了一些误导。

官方的注释如下:

/**
 * Set specific animation resources to run for the fragments that are
 * entering and exiting in this transaction. These animations will not be
 * played when popping the back stack.
 */
public abstract FragmentTransaction setCustomAnimations(int enter,int exit);

整体的3D翻转效果代码如下:

第二个Fragment。

/**
 * Created by Liurs on 2016/6/14.
 **/
public class SecondFragment extends Fragment {

  private LinearLayout root;
  private Button mButton;

  public SecondFragment() {

  }

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
    root = (LinearLayout) inflater.inflate(R.layout.fragment_second,container,false);
    //Set listener;
    setListener();
    return root;
  }

  /**
   * set listener
   */
  private void setListener() {
    mButton = (Button) root.findViewById(R.id.button);
    mButton.setonClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        getFragmentManager().beginTransaction()
            .setCustomAnimations(R.animator.fragment_second_3d_reversal_enter,R.animator.fragment_second_3d_reversal_exit)
            .replace(R.id.container,new MainFragment()).commit();
      }
    });
  }

  @Override
  public void onViewCreated(View view,Bundle savedInstanceState) {
    super.onViewCreated(view,savedInstanceState);

  }
}

第一个Fragment。

/**
 * Created by Liurs on 2016/6/14.
 **/
public class MainFragment extends Fragment {

  private LinearLayout root;
  private Button mButton;

  public MainFragment() {

  }

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater,Bundle savedInstanceState) {
    root = (LinearLayout) inflater.inflate(R.layout.content_main,false);
    //Set listener;
    setListener();

    return root;
  }

  /**
   * set listener
   */
  private void setListener() {
    mButton = (Button) root.findViewById(R.id.button);
    mButton.setonClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        getFragmentManager()
            .beginTransaction()
            .addToBackStack(null)
            .setCustomAnimations(R.animator.fragment_3d_reversal_enter,R.animator.fragment_3d_reversal_exit,R.animator.fragment_second_3d_reversal_enter,new SecondFragment())
            .commit();
      }
    });
  }


  @Override
  public void onViewCreated(View view,savedInstanceState);

  }
}

逆时针翻转动画进入时配置文件。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially">
  <objectAnimator
    android:duration="0"
    android:propertyName="rotationY"
    android:valueFrom="0f"
    android:valueto="270f" />
  <objectAnimator
    android:duration="500"
    android:propertyName="rotationY"
    android:startOffset="500"
    android:valueFrom="270f"
    android:valueto="360f" />
</set>

退出时动画配置文件,

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially">
  <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:propertyName="rotationY"
    android:valueFrom="0f"
    android:valueto="90f">
    </objectAnimator>
</set>

顺时针翻转动画进入时配置文件,

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
  android:ordering="sequentially">
  <objectAnimator
    android:duration="0"
    android:propertyName="rotationY"
    android:valueFrom="180f"
    android:valueto="90f" />
  <objectAnimator
    android:duration="500"
    android:propertyName="rotationY"
    android:startOffset="500"
    android:valueFrom="90f"
    android:valueto="0f" />
</set>

退出时动画配置文件,

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially">
  <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:propertyName="rotationY"
    android:valueFrom="0f"
    android:valueto="-90f">
  </objectAnimator>
</set>

至此,两个Fragment的3D翻转切换已经完成,希望我的经验可以帮助到你们。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

3D翻转效果介绍,Android动画分析

3D翻转效果介绍,Android动画分析

Android动画分析 - 3D翻转效果Android动画分析 - 3D翻转效果

android中的翻转动画效果的实现,首先看一下运行效果如上图所示。,更多android面试题..

Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和 Transformation。

Animation动画的主要接口,其中主要定义了动画的一些属性比如开始时间,持续时间,是否重复播放等等。而Transformation中则包含一个矩阵和alpha值,矩阵是用来做平移,旋转和缩放动画的,而alpha值是用来做alpha动画的,要实现3D旋转动画我们需要继承自Animation类来实现,我们需要重载getTransformation和applyTransformation,在getTransformation中Animation会根据动画的属性来产生一系列的差值点,然后将这些差值点传给applyTransformation,这个函数将根据这些点来生成不同的Transformation。下面是具体实现:

package com.example.textviewtest;
 
 import android.graphics.Camera;
 import android.graphics.Matrix;
 import android.view.animation.Animation;
 import android.view.animation.Transformation;
 
 public class Rotate3dAnimation extends Animation {
     // 开始角度
     private final float mFromDegrees;
     // 结束角度
     private final float mToDegrees;
     // 中心点
     private final float mCenterX;
     private final float mCenterY;
     private final float mDepthZ;
     // 是否需要扭曲
     private final boolean mReverse;
     // 摄像头
     private Camera mCamera;
 
     public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX,
             float centerY, float depthZ, boolean reverse) {
         mFromDegrees = fromDegrees;
         mToDegrees = toDegrees;
         mCenterX = centerX;
         mCenterY = centerY;
         mDepthZ = depthZ;
         mReverse = reverse;
     }
 
     @Override
     public void initialize(int width, int height, int parentWidth,
             int parentHeight) {
         super.initialize(width, height, parentWidth, parentHeight);
         mCamera = new Camera();
     }
 
     // 生成Transformation
     @Override
     protected void applyTransformation(float interpolatedTime, Transformation t) {
         final float fromDegrees = mFromDegrees;
         // 生成中间角度
         float degrees = fromDegrees
                 + ((mToDegrees - fromDegrees) * interpolatedTime);
 
         final float centerX = mCenterX;
         final float centerY = mCenterY;
         final Camera camera = mCamera;
 
         final Matrix matrix = t.getMatrix();
 
         camera.save();
         if (mReverse) {
             camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
         } else {
             camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
         }
         camera.rotateY(degrees);
         // 取得变换后的矩阵
         camera.getMatrix(matrix);
         camera.restore();
 
         matrix.preTranslate(-centerX, -centerY);
         matrix.postTranslate(centerX, centerY);
     }
 }

其中包括了旋转的开始和结束角度,中心点、是否扭曲、和一个Camera,这里我们主要分析applyTransformation函数,其中第一个参数就是通过getTransformation函数传递的差指点,然后我们根据这个差值通过线性差值算法计算出一个中间角度degrees,Camera类是用来实现绕Y轴旋转后透视投影的,因此我们首先通过t.getMatrix()取得当前的矩阵,然后通过camera.translate来对矩阵进行平移变换操作,camera.rotateY进行旋转。这样我们就可以很轻松的实现3D旋转效果了。

下面是布局文件main.xml:

MainActivity的代码如下:

package com.example.textviewtest;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.Menu;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.Button;
 import android.widget.TextView;
 
 public class MainActivity extends Activity {
     private TextView tv;
     private Button btn;
     private int count = 1;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         tv = (TextView) findViewById(R.id.tv);
         tv.setText(String.valueOf(count));
         btn = (Button) findViewById(R.id.next_btn);
         applyRotation(0, 90);
 
         btn.setOnClickListener(new View.OnClickListener() {
 
             @Override
             public void onClick(View v) {
                 applyRotation(0, 90);
             }
         });
 
     }
 
     private void applyRotation(float start, float end) {
         // 计算中心点
         final float centerX = tv.getWidth() / 2.0f;
         final float centerY = tv.getHeight() / 2.0f;
 
         final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end,
                 centerX, centerY, 310.0f, true);
         rotation.setDuration(500);
         rotation.setFillAfter(true);
         rotation.setInterpolator(new AccelerateInterpolator());
         // 设置监听
         rotation.setAnimationListener(new DisplayNextView());
 
         tv.startAnimation(rotation);
     }
 
     private final class DisplayNextView implements Animation.AnimationListener {
 
         public void onAnimationStart(Animation animation) {
         }
 
         // 动画结束
         public void onAnimationEnd(Animation animation) {
             tv.post(new SwapViews());
         }
 
         public void onAnimationRepeat(Animation animation) {
         }
     }
 
     private final class SwapViews implements Runnable {
 
         public void run() {
             final float centerX = tv.getWidth() / 2.0f;
             final float centerY = tv.getHeight() / 2.0f;
             Rotate3dAnimation rotation = null;
 
             tv.requestFocus();
 
             rotation = new Rotate3dAnimation(90, 0, centerX, centerY, 310.0f,
                     false);
             rotation.setDuration(500);
             rotation.setFillAfter(true);
             rotation.setInterpolator(new DecelerateInterpolator());
             // 开始动画
             tv.startAnimation(rotation);
             tv.setText(String.valueOf(count++));
         }
     }
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.activity_main, menu);
         return true;
     }
 
 }
文章摘自: http://www.baisoujs.com/detail_137434189082654.html

Android Fragment – 使用activity的loadermanager而不是Fragment.好吗?

Android Fragment – 使用activity的loadermanager而不是Fragment.好吗?

给定一个使用加载器从数据库加载(大量)数据的片段.

问题:

我有一个寻呼机适配器,当用户离开拿着它的标签时会破坏该片段,并在用户返回该标签时重新创建它.由于这种重新创建,每次都会创建一个新的加载器,并且每次都会加载数据.

题 :

为了避免每次创建片段时重新创建加载器,是否可以在片段的onActivityCreated方法中使用getActivity.getSupportLoaderManager.initLoader(loaderId,null,false)?

我试过它,测试它,似乎工作正常.但我不相信这是对的.

解决方法

实际上,检查源代码,你最终也会这样做.

Fragment.getLoaderManager:

/**
 * Return the LoaderManager for this fragment,creating it if needed.
 */
public LoaderManager getLoaderManager() {
    if (mloaderManager != null) {
        return mloaderManager;
    }
    if (mActivity == null) {
        throw new IllegalStateException("Fragment " + this + " not attached to Activity");
    }


    mCheckedForLoaderManager = true;
    mloaderManager = mActivity.getLoaderManager(mWho,mloadeRSStarted,true);
    return mloaderManager;
}

mWho基本上是片段ID.

final void setIndex(int index,Fragment parent) {
    mIndex = index;
    if (parent != null) {
        mWho = parent.mWho + ":" + mIndex;
    } else {
        mWho = "android:fragment:" + mIndex;
    }
}

Activity.getLoaderManager()的区别在于谁(root)

所以即使你可以做你想要的,直接从Fragment调用它可能是一个更好的方法

> Activity source code
> Fragment source code

免责声明:我只检查了最新版本的源代码,但我不认为它会有很大不同

Android Fragment 和 FragmentManager 的代码分析

Android Fragment 和 FragmentManager 的代码分析

这两天在研究插件化编程,在使用 Fragment 碰到了一些问题,于是查看源码,顺便分析了一下 Fragment 和 FragmentManager 以及其他几个 API 的原代码,看看他们是怎么工作的。

我们知道 Fragment 有个 onCreateView() 方法,这个方法在 Fragment 创建 View 的时候被调用,并且返回一个 View 对象。那么 onCreateView 在什么时候被调用呢,咱们在 Fragment 这个类里找到了一个方法,performCreateView() 方法。

Fragment.java
public View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {
 return null;
}

performCreateView 这个方法在什么时候会被调用呢,在 Fragment 里找不到调用它的代码。咱们可以猜测一下,大概会在 FragmentManager 里。

View performCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
 if (mChildFragmentManager != null) {
  mChildFragmentManager.noteStateNotSaved();
 }
 return onCreateView(inflater,container,savedInstanceState);
}

在 FragmentManager 里,咱们找到了调用 Fragment.performCreateView 的代码,在 movetoState() 方法里,这个方法有点大,我只粘贴了部分代码。可以看到,它会在 Fragment 初始化或者创建的时候被调用。并且我们知道,创建的View 被赋值给 Fragment 的 mView 成员变量了。

FragmentManager.java
void movetoState(Fragment f,int newState,int transit,int transitionStyle,boolean keepActive) {
 switch (f.mState) {
 case Fragment.INITIALIZING:
  if (f.mFromLayout) {
   f.mView = f.performCreateView(f.getLayoutInflater(
   f.mSavedFragmentState),null,f.mSavedFragmentState);
 }
 break;
case Fragment.CREATED:
 if (!f.mFromLayout) {
  f.mView = f.performCreateView(f.getLayoutInflater(
   f.mSavedFragmentState),f.mSavedFragmentState);
 }
break;
} 
}

接下来,咱们要看什么时候会调用 movetoState() 这个方法。找了一下,发现很 N 多的地方调用了这个方法。这样给咱们逆推找代码造成了一定的难度。于是咱们换个思路,正推来分析。怎么正推了,看咱们怎么使用 Fragment 和 FragmentManager 来分析。

一般咱们都是 getFragmentManager() 或者 getSupportFragmentManager() 的方法来获取 FragmentManager.以 FragmentActivity 为例,一般情况下,咱们在这个类的子类里调用这两个方法之一。

咱们在 FragmentActivity 里找到了相应的代码。FragmentManager 是一个抽象类,FragmentManagerImpl 是 FragmentManager 的子类,在 FragmentManager 同一个 java 文件内,是一个内部类。它是 FragmentManager 的实现。

FragmentActivity.java
//FragmentManagerImpl is subclass of FragmentManager
final FragmentManagerImpl mFragments = new FragmentManagerImpl();
public FragmentManager getSupportFragmentManager() {
 return mFragments;
}

获取到 FragmentManager 后,咱们一般就会调用 beginTransaction() 方法,返回一个 FragmentTransaction 。咱们看代码去。

FragmentManager.java
public abstract FragmentTransaction beginTransaction();
FragmentManagerImpl extends FragmentManager
@Override
public FragmentTransaction beginTransaction() {
 return new BackStackRecord(this);
}
/**
* Static library support version of the framework's {@link android.app.FragmentTransaction}.
* Used to write apps that run on platforms prior to Android 3.0. When running
* on Android 3.0 or above,this implementation is still used; it does not try
* to switch to the framework's implementation. See the framework SDK
* documentation for a class overview.
*/
public abstract class FragmentTransaction

我们发现 FragmentManager 是一个抽象方法,实现在 FragmentManagerImpl。FragmentManagerImpl.beginTransaction() 返回的是一个BackStackRecord,而 FragmentTransaction 是一个抽象类。那么 BackStackRecord 是个什么鬼。

我们找到了 BackStackRecord 这个类。我们注意到,它继承于 FragmentTransaction,并且实现了 Runable 接口。它的方法有很多,咱们就分析一个咱们比较常用的,比如 add() 方法。

BackStackRecord.java
final class BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry,Runnable 
final FragmentManagerImpl mManager;
public BackStackRecord(FragmentManagerImpl manager) {
 mManager = manager;
}

add() 方法其实没干啥,咱们一路追下去看。

public FragmentTransaction add(Fragment fragment,String tag) {
 doAddOp(0,fragment,tag,OP_ADD);
 return this;
}
private void doAddOp(int containerViewId,Fragment fragment,String tag,int opcmd) {
 fragment.mFragmentManager = mManager;
 if (tag != null) {
  if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
   throw new IllegalStateException("Can't change tag of fragment "
     + fragment + ": was " + fragment.mTag
     + " Now " + tag);
  }
  fragment.mTag = tag;
 }
 if (containerViewId != 0) {
  if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
   throw new IllegalStateException("Can't change container ID of fragment "
     + fragment + ": was " + fragment.mFragmentId
     + " Now " + containerViewId);
  }
  fragment.mContainerId = fragment.mFragmentId = containerViewId;
 }
 Op op = new Op();
 op.cmd = opcmd;
 op.fragment = fragment;
 addOp(op);
}
void addOp(Op op) {
 if (mHead == null) {
  mHead = mTail = op;
 } else {
  op.prev = mTail;
  mTail.next = op;
  mTail = op;
 }
 op.enteranim = mEnteranim;
 op.exitAnim = mExitAnim;
 op.popEnteranim = mPopEnteranim;
 op.popExitAnim = mPopExitAnim;
 mNumOp++;
}

一直追到 addOp() 就断了,好像啥事也没干。不过它大概是在一个 add 操作添加到一个链表上了。那咱们怎么办呢?一般咱们add 完后会 commit 一下,咱们看看 commit 都干了啥。

public int commit() {
 return commitInternal(false);
}
int commitInternal(boolean allowStateLoss) {
 if (mCommitted) throw new IllegalStateException("commit already called");
 mCommitted = true;
 if (mAddToBackStack) {
  mIndex = mManager.allocBackStackIndex(this);
 } else {
  mIndex = -1;
 }
 mManager.enqueueAction(this,allowStateLoss);
 return mIndex;
}

commit 好像也没干啥特殊的事情,不过可以看到这么一行代码 mManager.enqueueAction(this,allowStateLoss); 看 enqueueAction 这个方法名,应该会做点事情的。

同样,咱们在 FragmentManagerImpl 里找到了这个方法。

public void enqueueAction(Runnable action,boolean allowStateLoss) {
  if (!allowStateLoss) {
    checkStateLoss();
  }
  synchronized (this) {
    if (mDestroyed || mActivity == null) {
      throw new IllegalStateException("Activity has been destroyed");
    }
    if (mPendingActions == null) {
      mPendingActions = new ArrayList<Runnable>();
    }
    mPendingActions.add(action);
    if (mPendingActions.size() == 1) {
      mActivity.mHandler.removeCallbacks(mExecCommit);
      mActivity.mHandler.post(mExecCommit);
    }
  }
}

这个方法把咱们的 BackStackRecord -- 其实是 FragmentTransaction,也是 Runnable -- 添加到一个 mPendingActions 的 ArrayList 里了。然后调用 mActivity.mHandler.post(mExecCommit); mExecCommit 又是什么鬼?

Runnable mExecCommit = new Runnable() {
  @Override
  public void run() {
    execPendingActions();
  }
};
mActivity.mHandler.post(mExecCommit); 说明它在主线程里执行了 mExecCommit 的 run 方法。别问我咋知道的。
execPendingActions() 方法稍微比较大,我把注释写在代码里。
public boolean execPendingActions() {
  if (mExecutingActions) {
    throw new IllegalStateException("Recursive entry to executePendingTransactions");
  }
  //如果不是在主线程,抛出一个异常。
  if (Looper.myLooper() != mActivity.mHandler.getLooper()) {
    throw new IllegalStateException("Must be called from main thread of process");
  }
  boolean didSomething = false;
  // 这里有一个 while true 循环。
  while (true) {
    int numActions;
    // 这里在一个同步语句块里,把上次 mPendingActions 里的元素转移到 mTmpActions 数组里。并且执行 run方法。执行谁的 run 方法呢?!就是 BackStackRecord , 也就是 FragmentTransaction 。我在最后面贴了 BackStackRecord 的 run 方法。
    synchronized (this) {
      if (mPendingActions == null || mPendingActions.size() == 0) {
        break;
      }
      numActions = mPendingActions.size();
      if (mTmpActions == null || mTmpActions.length < numActions) {
        mTmpActions = new Runnable[numActions];
      }
      mPendingActions.toArray(mTmpActions);
      mPendingActions.clear();
      mActivity.mHandler.removeCallbacks(mExecCommit);
    }
    mExecutingActions = true;
    for (int i=0; i<numActions; i++) {
      mTmpActions[i].run();
      mTmpActions[i] = null;
    }
    mExecutingActions = false;
    didSomething = true;
  }
  // 这里有好几行代码,不知道干啥的,反正就是做了一些判断,最后可能会调用 startPendingDeferredFragments() 方法。
  if (mHavePendingDeferredStart) {
    boolean loadersRunning = false;
    for (int i=0; i<mActive.size(); i++) {
      Fragment f = mActive.get(i);
      if (f != null && f.mloaderManager != null) {
        loadersRunning |= f.mloaderManager.hasRunningLoaders();
      }
    }
    if (!loadersRunning) {
      mHavePendingDeferredStart = false;
      startPendingDeferredFragments();
    }
  }
  return didSomething;
}

startPendingDeferredFragments 方法又是一坨不知道啥意思的代码。最后可能调用了 performPendingDeferredStart()

void startPendingDeferredFragments() {
  if (mActive == null) return;
  for (int i=0; i<mActive.size(); i++) {
    Fragment f = mActive.get(i);
    if (f != null) {
      performPendingDeferredStart(f);
    }
  }
}

在 这个方法里,咱们看到了很熟悉的 movetoState() 方法。接着就是上面的分析,Fragment 的 onCreateView 会被调用。

public void performPendingDeferredStart(Fragment f) {
  if (f.mDeferStart) {
    if (mExecutingActions) {
      // Wait until we're done executing our pending transactions
      mHavePendingDeferredStart = true;
      return;
    }
    f.mDeferStart = false;
    movetoState(f,mCurState,false);
  }
}

咱们在回来看 BackStackRecord 的 run 方法。这坨代码有点大,我还是写注释在代码里。

public void run() {
  if (FragmentManagerImpl.DEBUG) Log.v(TAG,"Run: " + this);
  if (mAddToBackStack) {
    if (mIndex < 0) {
      throw new IllegalStateException("addToBackStack() called after commit()");
    }
  }
  bumpBackStacknesting(1);
  TransitionState state = null;
  SparseArray<Fragment> firstOutFragments = null;
  SparseArray<Fragment> lastInFragments = null;
  if (SUPPORTS_TRANSITIONS) {
    firstOutFragments = new SparseArray<Fragment>();
    lastInFragments = new SparseArray<Fragment>();
    calculateFragments(firstOutFragments,lastInFragments);
    state = beginTransition(firstOutFragments,lastInFragments,false);
  }
  int transitionStyle = state != null ? 0 : mTransitionStyle;
  int transition = state != null ? 0 : mTransition;
  // 注意这里要开始 while 循环了,要遍历刚才咱们说的链表了。
  Op op = mHead;
  while (op != null) {
    int enteranim = state != null ? 0 : op.enteranim;
    int exitAnim = state != null ? 0 : op.exitAnim;
    switch (op.cmd) {
      // OP_ADD 很简单,mManager.addFragment(f,false); 其他的几个也类似,调用 mManager 相应的方法。
      case OP_ADD: {
        Fragment f = op.fragment;
        f.mNextAnim = enteranim;
        mManager.addFragment(f,false);
      } break;
      case OP_REPLACE: {
        Fragment f = op.fragment;
        if (mManager.mAdded != null) {
          for (int i=0; i<mManager.mAdded.size(); i++) {
            Fragment old = mManager.mAdded.get(i);
            if (FragmentManagerImpl.DEBUG) Log.v(TAG,"OP_REPLACE: adding=" + f + " old=" + old);
            if (f == null || old.mContainerId == f.mContainerId) {
              if (old == f) {
                op.fragment = f = null;
              } else {
                if (op.removed == null) {
                  op.removed = new ArrayList<Fragment>();
                }
                op.removed.add(old);
                old.mNextAnim = exitAnim;
                if (mAddToBackStack) {
                  old.mBackStacknesting += 1;
                  if (FragmentManagerImpl.DEBUG) Log.v(TAG,"Bump nesting of "
                      + old + " to " + old.mBackStacknesting);
                }
                mManager.removeFragment(old,transition,transitionStyle);
              }
            }
          }
        }
        if (f != null) {
          f.mNextAnim = enteranim;
          mManager.addFragment(f,false);
        }
      } break;
      case OP_REMOVE: {
        Fragment f = op.fragment;
        f.mNextAnim = exitAnim;
        mManager.removeFragment(f,transitionStyle);
      } break;
      case OP_HIDE: {
        Fragment f = op.fragment;
        f.mNextAnim = exitAnim;
        mManager.hideFragment(f,transitionStyle);
      } break;
      case OP_SHOW: {
        Fragment f = op.fragment;
        f.mNextAnim = enteranim;
        mManager.showFragment(f,transitionStyle);
      } break;
      case OP_DETACH: {
        Fragment f = op.fragment;
        f.mNextAnim = exitAnim;
        mManager.detachFragment(f,transitionStyle);
      } break;
      case OP_ATTACH: {
        Fragment f = op.fragment;
        f.mNextAnim = enteranim;
        mManager.attachFragment(f,transitionStyle);
      } break;
      default: {
        throw new IllegalArgumentException("UnkNown cmd: " + op.cmd);
      }
    }
    op = op.next;
  }
  // 最后还调用了movetoState() 这个方法。跟刚才的区别,看最后一个参数,一个true,一个false。
  // 而且注意,这行代码在 while 循环之后。
  mManager.movetoState(mManager.mCurState,transitionStyle,true);
  if (mAddToBackStack) {
    mManager.addBackStackState(this);
  }
}

以上所述是小编给大家介绍的Android Fragment 和 FragmentManager 的代码分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

Android FragmentManage FragmentTransaction 介绍

Android FragmentManage FragmentTransaction 介绍

OSC 请你来轰趴啦!1028 苏州源创会,一起寻宝 AI 时代

FragmentManage:

FragmentManager 能够实现管理 activity 中 fragment. 通过调用 activity 的 getFragmentManager () 取得它的实例.

FragmentManager 可以做如下一些事情:
1、使用 findFragmentById () (用于在 activity layout 中提供一个 UI 的 fragment) 或 findFragmentByTag ()
   (适用于有或没有 UI 的 fragment) 获取 activity 中存在的 fragment
2、将 fragment 从后台堆栈中弹出,使用 popBackStack () (模拟用户按下 BACK 命令).
3、使用 addOnBackStackChangeListener () 注册一个监听后台堆栈变化的 listener.
 

FragmentTransaction:

      FragmentTransaction 对 fragment 进行添加,移除,替换,以及执行其他动作。
从 FragmentManager 获得一个 FragmentTransaction 的实例 :

FragmentManager fragmentManager = getFragmentManager(); 
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

每一个事务都是同时要执行的一套变化。可以在一个给定的事务中设置你想执行的所有变化,使用诸如 add (), remove (), 和 replace (). 然后,要给 activity 应用事务,必须调用 commit ().

在调用 commit () 之前,你可能想调用 addToBackStack (), 将事务添加到一个 fragment 事务的 back stack.  这个 back stack 由 activity 管理,并允许用户通过按下 BACK 按键返回到前一个 fragment 状态.

举个例子,这里是如何将一个 fragment 替换为另一个,并在后台堆栈中保留之前的状态:
 // Create new fragment and transaction  Fragment newFragment = new ExampleFragment();  FragmentTransaction transaction = getFragmentManager().beginTransaction();  // Replace whatever is in the fragment_container view with this fragment,  // and add the transaction to the back stack  transaction.replace(R.id.fragment_container, newFragment);  transaction.addToBackStack(null);  // Commit the transaction  transaction.commit();

在这个例子中,newFragment 替换了当前 layout 容器中的由 R.id.fragment_container 标识的 fragment. 通过调用 addToBackStack (), replace 事务被保存到 back stack, 因此用户可以回退事务,并通过按下 BACK 按键带回前一个 fragment.

如果添加多个变化到事务 (例如 add () 或 remove ()) 并调用 addToBackStack (), 然后在你调用 commit () 之前的所有应用的变化会被作为一个单个事务添加到后台堆栈,BACK 按键会将它们一起回退.

添加变化到 FragmentTransaction 的顺序不重要,除以下例外:
  • 必须最后调用 commit ().
  • 如果添加多个 fragment 到同一个容器,那么添加的顺序决定了它们在 view hierarchy 中显示的顺序.
当执行一个移除 fragment 的事务时,如果没有调用 addToBackStack (), 那么当事务提交后,那个 fragment 会被销毁,并且用户不能导航回到它。有鉴于此,当移除一个 fragment 时,如果调用了 addToBackStack (), 那么 fragment 会被停止,如果用户导航回来,它将会被恢复.

提示:对于每一个 fragment 事务,你可以应用一个事务动画,通过在提交事务之前调用 setTransition () 实现.

调用 commit () 并不立即执行事务。恰恰相反,它将事务安排排期,一旦准备好,就在 activity 的 UI 线程上运行 (主线程). 如果有必要,无论如何,你可以从你的 UI 线程调用 executePendingTransactio ns () 来立即执行由 commit () 提交的事务.  但这么做通常不必要,除非事务是其他线程中的 job 的一个从属.

警告: 你只能在 activity 保存它的状态 (当用户离开 activity) 之前使用 commit () 提交事务.

如果你试图在那个点之后提交,会抛出一个异常。这是因为如果 activity 需要被恢复,提交之后的状态可能会丢失。对于你觉得可以丢失提交的状况,使用 commitAllowingStateLoss ().

 

 

 

 

 

 

/**
* @author 张兴业
* 邮箱: xy-zhang#163.com
* android 开发进阶群: 278401545
*
*/

今天关于Android使用animator实现fragment的3D翻转效果animate的3d旋转工具的介绍到此结束,谢谢您的阅读,有关3D翻转效果介绍,Android动画分析、Android Fragment – 使用activity的loadermanager而不是Fragment.好吗?、Android Fragment 和 FragmentManager 的代码分析、Android FragmentManage FragmentTransaction 介绍等更多相关知识的信息可以在本站进行查询。

本文标签: