如何在动作栏通过Appcompat更改其内容时添加动画? [英] How to add animation while actionbar are changing their content with Appcompat?

查看:47
本文介绍了如何在动作栏通过Appcompat更改其内容时添加动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看Google的Material Design指南,我想添加动画操作栏.我的目标是做这样的事情:

如何为操作栏的内容添加过渡?我正在使用Appcompat保持向后兼容性.

解决方案

更新:

我已经创建了一个,以及演示应用程序此处.


最初接受的答案:

这是一个功能更广泛的解决方案,它正是MenuItem淡出Google云端硬盘,Google文档,Google表格和Google幻灯片的方式.

优点在于,当用户从屏幕的左边缘滑入以手动打开抽屉时,或者在打开抽屉以将其关闭时向右滑动时,动画状态与抽屉的显示方式集成在一起正在打开/关闭.


ProgressAnimator.java :这是实现的内容,它将基于float的渐进值(0f〜1f)转换为Android Animator的值理解.

 公共类ProgressAnimator实现TimeAnimator.TimeListener {私人最终List< AnimationControl>animationControls = new ArrayList<>();私有final MenuItem mMenuItem;//TODO不应该在这里,添加动画结束监听器私有最终ImageView mImageView;私人最终TimeAnimator mTimeAnim;私有最终AnimatorSet mInternalAnimSet;public ProgressAnimator(Context context,MenuItem mMenuItem){如果(mMenuItem == null){mImageView = null;} 别的 {mImageView =(ImageView)LayoutInflater.from(context).inflate(R.layout.menu_animation,null).findViewById(R.id.menu_animation);mImageView.setImageDrawable(mMenuItem.getIcon());}this.mMenuItem = mMenuItem;this.mInternalAnimSet = new AnimatorSet();mTimeAnim = new TimeAnimator();mTimeAnim.setTimeListener(this);}公共无效的addAnimatorSet(AnimatorSet mAnimSet,浮点数开始,浮点数结束){animationControls.add(新的AnimationControl(mImageView,mAnimSet,开始,结束));}public void addAnimatorSet(Object target,AnimatorSet mAnimSet,浮点开始,浮点结束){animationControls.add(new AnimationControl(target,mAnimSet,start,end));}public void start(){ValueAnimator colorAnim = ObjectAnimator.ofInt(new Object(){私人int虚拟;public int getDummy(){返回假人}公共无效setDummy(int dummy){this.dummy =虚拟;}},"dummy",0,1);colorAnim.setDuration(Integer.MAX_VALUE);mInternalAnimSet.play(colorAnim).with(mTimeAnim);mInternalAnimSet.start();如果(mMenuItem!= null){mMenuItem.setActionView(mImageView);}对于(AnimationControl ctrl:animationControls){ctrl.start();}}公共无效end(){mTimeAnim.end();如果(mMenuItem!= null){mMenuItem.setActionView(null);}}公共无效updateProgress(浮动进度){对于(AnimationControl ctrl:animationControls){ctrl.updateProgress(progress);}}@Overridepublic void onTimeUpdate(TimeAnimator动画,很长的totalTime,很长的deltaTime){对于(AnimationControl ctrl:animationControls){ctrl.updateState();}}} 

AnimationControl.java :控制过渡的进度.

 公共类AnimationControl {私有AnimatorSet mAnimSet;私有对象目标;私人浮动开始;私有浮动端= 1.0f;私有浮动progressWidth;私人长时间;私人布尔值开始;专用长mStartDelay;私人长期运营;私人长mTotalDuration;public AnimationControl(AnimatorSet mAnimSet,浮点开始,浮点结束){this(null,mAnimSet,开始,结束);}public AnimationControl(对象目标,AnimatorSet mAnimSet,浮点数开始,浮点数结束){for(动画师动画师:mAnimSet.getChildAnimations()){if(!(ValueAnimator的animator实例)){抛出新的UnsupportedOperationException(仅支持ValueAnimator及其子类");}}this.target =目标;this.mAnimSet = mAnimSet;mStartDelay = mAnimSet.getStartDelay();mDuration = mAnimSet.getDuration();如果(mAnimSet.getDuration()> = 0){长持续时间= mAnimSet.getDuration();for(动画师动画师:mAnimSet.getChildAnimations()){animator.setDuration(duration);}} 别的 {for(动画师动画师:mAnimSet.getChildAnimations()){long endTime = animator.getStartDelay()+ animator.getDuration();如果(mDuration< endTime){mDuration = endTime;}}}mTotalDuration = mStartDelay + mDuration;this.start =开始;this.end = end;progressWidth = Math.abs(结束-开始);}public void start(){if(target!= null){for(动画师动画师:mAnimSet.getChildAnimations()){animator.setTarget(target);}}}公共无效updateProgress(浮动进度){如果(开始<结束&进度> =开始&&进步< =结束||开始>结束&&进步> =结束&&&进展< =开始){如果(开始<结束){时间=(长)(mTotalDuration *(进度-开始)/progressWidth);} 别的 {时间=(长)(mTotalDuration-mTotalDuration *(进度-结束)/progressWidth);}时间-= mStartDelay;如果(时间> 0){开始=真;}Log.e(getClass().getSimpleName(),"updateState:" + mTotalDuration +;" + time +"/" + start +"/" + end);} 别的 {//向前如果(开始<结束){if(进度<开始){时间= 0;}否则,如果(进度>结束){时间= mTotalDuration;}//落后} else if(开始>结束){如果(进度>开始){时间= 0;}否则,如果(进度>结束){时间= mTotalDuration;}}开始=假;}}公共无效updateState(){如果(开始){for(动画师动画师:mAnimSet.getChildAnimations()){ValueAnimator va =(ValueAnimator)动画师;长absTime =时间-va.getStartDelay();如果(absTime> 0){va.setCurrentPlayTime(absTime);}}}}} 

ProgressDrawerListener.java :这会监听 DrawerLayout 状态更新并设置所需的动画.

 公共类ProgressDrawerListener实现DrawerLayout.DrawerListener {私人最终List< ProgressAnimator>mAnimatingMenuItems = new ArrayList<>();专用最终工具栏mToolbar;私有最终ActionBarDrawerToggle mDrawerToggle;私有DrawerLayout.DrawerListener mDrawerListener;private MenuItemAnimation mMenuItemAnimation;私人动画mAnimation;私人布尔值开始;私有布尔值mOpened;私人活动mActivity;私有布尔值mInvalidateOptionOnOpenClose;public ProgressDrawerListener(工具栏mToolbar,ActionBarDrawerToggle mDrawerToggle){this.mToolbar = mToolbar;this.mDrawerToggle = mDrawerToggle;}@Overridepublic void onDrawerOpened(View view){mDrawerToggle.onDrawerOpened(view);clearAnimation();开始=假;如果(mDrawerListener!= null){mDrawerListener.onDrawerOpened(view);}mToolbar.getMenu().setGroupVisible(0,false);//并非总是需要TODOmOpened = true;mActivity.invalidateOptionsMenu();}@Overridepublic void onDrawerClosed(View view){mDrawerToggle.onDrawerClosed(view);clearAnimation();开始=假;如果(mDrawerListener!= null){mDrawerListener.onDrawerClosed(view);}mOpened = false;mActivity.invalidateOptionsMenu();}@Override公共无效的onDrawerStateChanged(int状态){mDrawerToggle.onDrawerStateChanged(state);开关(状态){案例DrawerLayout.STATE_DRAGGING:案例DrawerLayout.STATE_SETTLING:如果(mAnimatingMenuItems.size()> 0 ||开始){休息;}开始=真;setupAnimation();休息;案例DrawerLayout.STATE_IDLE:clearAnimation();开始=假;休息;}如果(mDrawerListener!= null){mDrawerListener.onDrawerStateChanged(state);}}私人void setupAnimation(){mToolbar.getMenu().setGroupVisible(0,true);//并非总是需要TODOmAnimatingMenuItems.clear();for(int i = 0; i< mToolbar.getChildCount(); i ++){最终视图v = mToolbar.getChildAt(i);如果(v instanceof ActionMenuView){int menuItemCount = 0;int childCount =(((ActionMenuView)v).getChildCount();for(int j = 0; j< childCount; j ++){如果((((ActionMenuView)v).getChildAt(j)ActionMenuItemView的实例){menuItemCount ++;}}for(int j = 0; j< childCount; j ++){最终视图innerView =(((ActionMenuView)v).getChildAt(j);if(innerView instanceof ActionMenuItemView){MenuItem mMenuItem =(((ActionMenuItemView)innerView).getItemData();ProgressAnimator offsetAnimator =新的ProgressAnimator(mToolbar.getContext(),mMenuItem);if(mMenuItemAnimation!= null){mMenuItemAnimation.setupAnimation(mMenuItem,offsetAnimator,j,menuItemCount);}if(mAnimation!= null){mAnimation.setupAnimation(offsetAnimator);}offsetAnimator.start();mAnimatingMenuItems.add(offsetAnimator);}}}}onDrawerSlide(null,mOpened?1f:0f);Log.e(getClass().getSimpleName(),"setupAnimation:" + mAnimatingMenuItems.size());//去做}@Overridepublic void onDrawerSlide(View view,float slideOffset){对于(ProgressAnimator ani:mAnimatingMenuItems){ani.updateProgress(slideOffset);}if(view == null){返回;}mDrawerToggle.onDrawerSlide(view,slideOffset);如果(mDrawerListener!= null){mDrawerListener.onDrawerSlide(view,slideOffset);}}私人无效clearAnimation(){对于(ProgressAnimator ani:mAnimatingMenuItems){ani.end();}mAnimatingMenuItems.clear();}公共无效setDrawerListener(DrawerLayout.DrawerListener mDrawerListener){this.mDrawerListener = mDrawerListener;}public MenuItemAnimation getMenuItemAnimation(){返回mMenuItemAnimation;}公共无效setMenuItemAnimation(MenuItemAnimation mMenuItemAnimation){this.mMenuItemAnimation = mMenuItemAnimation;}公共动画getAnimation(){返回mAnimation;}public void setAnimation(Animation mAnimation){this.mAnimation = mAnimation;}公共无效setmInvalidateOptionOnOpenClose(活动活动,布尔invalidateOptionOnOpenClose){mActivity =活动性;mInvalidateOptionOnOpenClose = invalidateOptionOnOpenClose;}公共接口MenuItemAnimation {公共无效setupAnimation(MenuItem mMenuItem,ProgressAnimator offsetAnimator,int itemIndex,int menuCount);}公共接口动画{公共无效setupAnimation(ProgressAnimator offsetAnimator);} 

}

在活动"中设置:以下示例代码在打开状态和关闭状态之间的两个不同菜单选项之间切换.如果需要自己的 DrawerListener ,则可以选择添加 offsetDrawerListener.setDrawerListener(DrawerListener).

  @Override受保护的void onCreate(Bundle savedInstanceState){//其他初始化mProgressDrawerListener = new ProgressDrawerListener(toolbar,mDrawerToggle);mProgressDrawerListener.setmInvalidateOptionOnOpenClose(this,true);mOpenAnimation =新的ProgressDrawerListener.MenuItemAnimation(){@Overridepublic void setupAnimation(MenuItem mMenuItem,ProgressAnimator offsetAnimator,int itemIndex,int menuCount){MainActivity.this.setupAnimation(true,offsetAnimator,itemIndex);}};mCloseAnimation =新的ProgressDrawerListener.MenuItemAnimation(){@Overridepublic void setupAnimation(MenuItem mMenuItem,ProgressAnimator offsetAnimator,int itemIndex,int menuCount){MainActivity.this.setupAnimation(false,offsetAnimator,itemIndex);}};mDrawerLayout.setDrawerListener(mProgressDrawerListener);}//在这里自定义动画私有void setupAnimation(布尔值打开,ProgressAnimator offsetAnimator,int itemIndex){AnimatorSet set = new AnimatorSet();set.playTogether(ObjectAnimator.ofFloat(null,"alpha",1.0f,0f),ObjectAnimator.ofFloat(null,"scaleX",1.0f,0f));set.setStartDelay(itemIndex * 200);set.setDuration(1000-itemIndex * 200);//不是播放动画的实际时间if(open){offsetAnimator.addAnimatorSet(set,0,1);} 别的 {offsetAnimator.addAnimatorSet(set,1,0);}}@Overridepublic boolean onCreateOptionsMenu(Menu menu){//仅在操作栏中显示与此屏幕相关的项目//如果未显示抽屉.否则,让抽屉//决定要在操作栏中显示的内容.if(mDrawerLayout.isDrawerOpen(findViewById(R.id.drawerList))){getMenuInflater().inflate(R.menu.drawer,menu);mProgressDrawerListener.setMenuItemAnimation(mCloseAnimation);} 别的 {getMenuInflater().inflate(R.menu.main,menu);mProgressDrawerListener.setMenuItemAnimation(mOpenAnimation);mDrawerLayout.setDrawerListener(mProgressDrawerListener);}返回super.onCreateOptionsMenu(menu);} 

menu_animation.xml :这是为了使自定义 ActionView 具有与 MenuIem

使用的视图相同的布局.

 <?xml version ="1.0" encoding ="utf-8"?>< ImageView xmlns:android ="http://schemas.android.com/apk/res/android"android:id ="@ + id/menu_animation"android:layout_width ="match_parent"android:layout_height ="match_parent"android:minWidth ="@ * android:dimen/action_button_min_width"android:padding ="8dp"style ="@ style/Widget.AppCompat.ActionBar"/> 

I'm looking at Google's Material Design guidelines and I want add animated action bar. My goal is do something like this:

How can I add transition for action bar's content? I'm using Appcompat to keep backward compatibility.

解决方案

Update:

I've created an open source library that provides transition/animation support to both View and MenuItem:

MenuItem transition

View transition

Instructions:

On Android Studio, add the code below to Gradle dependencies:

compile 'com.github.kaichunlin.transition:core:0.8.1'

Sample code with explanations:

  protected void onCreate(Bundle savedInstanceState) {
    //...
    //standard onCreate() stuff that creates set configs toolbar, mDrawerLayout & mDrawerToggle

    //Use the appropriate adapter that extends MenuBaseAdapter:
    DrawerListenerAdapter mDrawerListenerAdapter = new DrawerListenerAdapter(mDrawerToggle, R.id.drawerList);
    mDrawerListenerAdapter.setDrawerLayout(mDrawerLayout);

    //Add desired transition to the adapter, MenuItemTransitionBuilder is used to build the transition:
    //Creates a shared configuration that: applies alpha, the transition effect is applied in a cascading manner (v.s. simultaneously), MenuItems will resets to enabled when transiting, and invalidates menu on transition completion 
    MenuItemTransitionBuilder builder = MenuItemTransitionBuilder.transit(toolbar).alpha(1f, 0.5f).scale(1f, 0f).cascade(0.3f).visibleOnStartAnimation(true).invalidateOptionOnStopTransition(this, true);
    MenuItemTransition mShrinkClose = builder.translationX(0, 30).build();
    MenuItemTransition mShrinkOpen = builder.reverse().translationX(0, 30).build();
    mDrawerListenerAdapter.setupOptions(this, new MenuOptionConfiguration(mShrinkOpen, R.menu.drawer), new MenuOptionConfiguration(mShrinkClose, R.menu.main));
  }

  //Let the adapter manage the creation of options menu:
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
      mDrawerListenerAdapter.onCreateOptionsMenu(this, menu);

      return super.onCreateOptionsMenu(menu);
  }

Source of the activity implementing the above is here, and a demo app here.


Originally Accepted Answer:

Here's a solution that's more versatile and is exactly how the MenuItem fade-out of Google Drive, Google Docs, Google Sheets, and Google Slides work.

The advantage is that when the user slide in from the left edge of the screen to open the drawer manually, or slide right when the drawer is opened to close it, the animation state is integrated with how the drawer is being opened/closed.


ProgressAnimator.java: This is the meat of the implementation, it translates a float based progression value (0f~1f) into a value that Android Animator understands.

public class ProgressAnimator implements TimeAnimator.TimeListener {
    private final List<AnimationControl> animationControls = new ArrayList<>();
    private final MenuItem mMenuItem; //TODO shouldn't be here, add animation end listener
    private final ImageView mImageView;
    private final TimeAnimator mTimeAnim;
    private final AnimatorSet mInternalAnimSet;

    public ProgressAnimator(Context context, MenuItem mMenuItem) {
    if (mMenuItem == null) {
        mImageView = null;
    } else {
        mImageView = (ImageView) LayoutInflater.from(context).inflate(R.layout.menu_animation, null).findViewById(R.id.menu_animation);
        mImageView.setImageDrawable(mMenuItem.getIcon());
    }
    this.mMenuItem = mMenuItem;
    this.mInternalAnimSet = new AnimatorSet();

    mTimeAnim = new TimeAnimator();
    mTimeAnim.setTimeListener(this);
    }

    public void addAnimatorSet(AnimatorSet mAnimSet, float start, float end) {
    animationControls.add(new AnimationControl(mImageView, mAnimSet, start, end));
    }

    public void addAnimatorSet(Object target, AnimatorSet mAnimSet, float start, float end) {
    animationControls.add(new AnimationControl(target, mAnimSet, start, end));
    }

    public void start() {
    ValueAnimator colorAnim = ObjectAnimator.ofInt(new Object() {
        private int dummy;

        public int getDummy() {
        return dummy;
        }

        public void setDummy(int dummy) {
        this.dummy = dummy;
        }
    }, "dummy", 0, 1);
    colorAnim.setDuration(Integer.MAX_VALUE);
    mInternalAnimSet.play(colorAnim).with(mTimeAnim);
    mInternalAnimSet.start();
    if (mMenuItem != null) {
        mMenuItem.setActionView(mImageView);
    }
    for (AnimationControl ctrl : animationControls) {
        ctrl.start();
    }
    }

    public void end() {
    mTimeAnim.end();
    if (mMenuItem != null) {
        mMenuItem.setActionView(null);
    }
    }

    public void updateProgress(float progress) {
    for (AnimationControl ctrl : animationControls) {
        ctrl.updateProgress(progress);
    }
    }

    @Override
    public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
    for (AnimationControl ctrl : animationControls) {
        ctrl.updateState();
    }
    }
}

AnimationControl.java: Controls the progression of transition.

public class AnimationControl {
    private AnimatorSet mAnimSet;
    private Object target;
    private float start;
    private float end = 1.0f;
    private float progressWidth;
    private long time;
    private boolean started;
    private long mStartDelay;
    private long mDuration;
    private long mTotalDuration;

    public AnimationControl(AnimatorSet mAnimSet, float start, float end) {
    this(null, mAnimSet, start, end);
    }

    public AnimationControl(Object target, AnimatorSet mAnimSet, float start, float end) {
    for (Animator animator : mAnimSet.getChildAnimations()) {
        if (!(animator instanceof ValueAnimator)) {
        throw new UnsupportedOperationException("Only ValueAnimator and its subclasses are supported");
        }
    }
    this.target = target;
    this.mAnimSet = mAnimSet;
    mStartDelay = mAnimSet.getStartDelay();
    mDuration = mAnimSet.getDuration();
    if (mAnimSet.getDuration() >= 0) {
        long duration = mAnimSet.getDuration();
        for (Animator animator : mAnimSet.getChildAnimations()) {
        animator.setDuration(duration);
        }
    } else {
        for (Animator animator : mAnimSet.getChildAnimations()) {
        long endTime = animator.getStartDelay() + animator.getDuration();
        if (mDuration < endTime) {
            mDuration = endTime;
        }
        }
    }
    mTotalDuration = mStartDelay + mDuration;
    this.start = start;
    this.end = end;
    progressWidth = Math.abs(end - start);
    }

    public void start() {
    if (target != null) {
        for (Animator animator : mAnimSet.getChildAnimations()) {
        animator.setTarget(target);
        }
    }
    }

    public void updateProgress(float progress) {
    if (start < end && progress >= start && progress <= end || start > end && progress >= end && progress <= start) {
        if (start < end) {
        time = (long) (mTotalDuration * (progress - start) / progressWidth);
        } else {
        time = (long) (mTotalDuration - mTotalDuration * (progress - end) / progressWidth);
        }
        time -= mStartDelay;
        if (time > 0) {
        started = true;
        }
        Log.e(getClass().getSimpleName(), "updateState: " + mTotalDuration + ";" + time+"/"+start+"/"+end);
    } else {
        //forward
        if (start < end) {
        if (progress < start) {
            time = 0;
        } else if (progress > end) {
            time = mTotalDuration;
        }
        //backward
        } else if (start > end) {
        if (progress > start) {
            time = 0;
        } else if (progress > end) {
            time = mTotalDuration;
        }
        }
        started = false;
    }
    }

    public void updateState() {
    if (started) {
        for (Animator animator : mAnimSet.getChildAnimations()) {
        ValueAnimator va = (ValueAnimator) animator;
        long absTime = time - va.getStartDelay();
        if (absTime > 0) {
            va.setCurrentPlayTime(absTime);
        }
        }
    }
    }
}

ProgressDrawerListener.java: This listens for DrawerLayout state update and setup the required animation.

public class ProgressDrawerListener implements DrawerLayout.DrawerListener {
private final List<ProgressAnimator> mAnimatingMenuItems = new ArrayList<>();
private final Toolbar mToolbar;
private final ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout.DrawerListener mDrawerListener;
private MenuItemAnimation mMenuItemAnimation;
private Animation mAnimation;
private boolean started;
private boolean mOpened;
private Activity mActivity;
private boolean mInvalidateOptionOnOpenClose;

public ProgressDrawerListener(Toolbar mToolbar, ActionBarDrawerToggle mDrawerToggle) {
    this.mToolbar = mToolbar;
    this.mDrawerToggle = mDrawerToggle;
}

@Override
public void onDrawerOpened(View view) {
    mDrawerToggle.onDrawerOpened(view);
    clearAnimation();
    started = false;

    if (mDrawerListener != null) {
        mDrawerListener.onDrawerOpened(view);
    }
    mToolbar.getMenu().setGroupVisible(0, false); //TODO not always needed
    mOpened=true;
    mActivity.invalidateOptionsMenu();
}

@Override
public void onDrawerClosed(View view) {
    mDrawerToggle.onDrawerClosed(view);
    clearAnimation();
    started = false;

    if (mDrawerListener != null) {
        mDrawerListener.onDrawerClosed(view);
    }
    mOpened=false;
    mActivity.invalidateOptionsMenu();
}

@Override
public void onDrawerStateChanged(int state) {
    mDrawerToggle.onDrawerStateChanged(state);
    switch (state) {
        case DrawerLayout.STATE_DRAGGING:
        case DrawerLayout.STATE_SETTLING:
            if (mAnimatingMenuItems.size() > 0 || started) {
                break;
            }
            started = true;

            setupAnimation();
            break;
        case DrawerLayout.STATE_IDLE:
            clearAnimation();
            started = false;
            break;
    }

    if (mDrawerListener != null) {
        mDrawerListener.onDrawerStateChanged(state);
    }
}

private void setupAnimation() {
    mToolbar.getMenu().setGroupVisible(0, true); //TODO not always needed
    mAnimatingMenuItems.clear();
    for (int i = 0; i < mToolbar.getChildCount(); i++) {
        final View v = mToolbar.getChildAt(i);
        if (v instanceof ActionMenuView) {
            int menuItemCount = 0;
            int childCount = ((ActionMenuView) v).getChildCount();
            for (int j = 0; j < childCount; j++) {
                if (((ActionMenuView) v).getChildAt(j) instanceof ActionMenuItemView) {
                    menuItemCount++;
                }
            }
            for (int j = 0; j < childCount; j++) {
                final View innerView = ((ActionMenuView) v).getChildAt(j);
                if (innerView instanceof ActionMenuItemView) {
                    MenuItem mMenuItem = ((ActionMenuItemView) innerView).getItemData();
                    ProgressAnimator offsetAnimator = new ProgressAnimator(mToolbar.getContext(), mMenuItem);

                    if(mMenuItemAnimation!=null) {
                        mMenuItemAnimation.setupAnimation(mMenuItem, offsetAnimator, j, menuItemCount);
                    }
                    if(mAnimation!=null) {
                        mAnimation.setupAnimation(offsetAnimator);
                    }

                    offsetAnimator.start();
                    mAnimatingMenuItems.add(offsetAnimator);
                }
            }
        }
    }
    onDrawerSlide(null, mOpened ? 1f : 0f);
    Log.e(getClass().getSimpleName(), "setupAnimation: "+mAnimatingMenuItems.size()); //TODO
}

@Override
public void onDrawerSlide(View view, float slideOffset) {
    for (ProgressAnimator ani : mAnimatingMenuItems) {
        ani.updateProgress(slideOffset);
    }

    if(view==null) {
        return;
    }
    mDrawerToggle.onDrawerSlide(view, slideOffset);

    if (mDrawerListener != null) {
        mDrawerListener.onDrawerSlide(view, slideOffset);
    }
}

private void clearAnimation() {
    for (ProgressAnimator ani : mAnimatingMenuItems) {
        ani.end();
    }
    mAnimatingMenuItems.clear();
}

public void setDrawerListener(DrawerLayout.DrawerListener mDrawerListener) {
    this.mDrawerListener = mDrawerListener;
}

public MenuItemAnimation getMenuItemAnimation() {
    return mMenuItemAnimation;
}

public void setMenuItemAnimation(MenuItemAnimation mMenuItemAnimation) {
    this.mMenuItemAnimation = mMenuItemAnimation;
}

public Animation getAnimation() {
    return mAnimation;
}

public void setAnimation(Animation mAnimation) {
    this.mAnimation = mAnimation;
}

public void setmInvalidateOptionOnOpenClose(Activity activity, boolean invalidateOptionOnOpenClose) {
    mActivity=activity;
    mInvalidateOptionOnOpenClose = invalidateOptionOnOpenClose;
}

public interface MenuItemAnimation {

    public void setupAnimation(MenuItem mMenuItem, ProgressAnimator offsetAnimator, int itemIndex, int menuCount);
}

public interface Animation {

    public void setupAnimation(ProgressAnimator offsetAnimator);
}

}

Set up in Activity: The example code below switches between two different menu options between opened and closed state. Optionally add offsetDrawerListener.setDrawerListener(DrawerListener) if you need to have your own DrawerListener.:

@Override
protected void onCreate(Bundle savedInstanceState) {
    //other init

    mProgressDrawerListener =new ProgressDrawerListener(toolbar, mDrawerToggle);
    mProgressDrawerListener.setmInvalidateOptionOnOpenClose(this, true);
    mOpenAnimation = new ProgressDrawerListener.MenuItemAnimation() {
        @Override
        public void setupAnimation(MenuItem mMenuItem, ProgressAnimator offsetAnimator, int itemIndex, int menuCount) {
            MainActivity.this.setupAnimation(true, offsetAnimator, itemIndex);
        }
    };
    mCloseAnimation = new ProgressDrawerListener.MenuItemAnimation() {
        @Override
        public void setupAnimation(MenuItem mMenuItem, ProgressAnimator offsetAnimator, int itemIndex, int menuCount) {
            MainActivity.this.setupAnimation(false, offsetAnimator, itemIndex);
        }
    };
    mDrawerLayout.setDrawerListener(mProgressDrawerListener);
}

//customize your animation here
private void setupAnimation(boolean open, ProgressAnimator offsetAnimator, int itemIndex) {
    AnimatorSet set = new AnimatorSet();
    set.playTogether(
            ObjectAnimator.ofFloat(null, "alpha", 1.0f, 0f),
            ObjectAnimator.ofFloat(null, "scaleX", 1.0f, 0f)
    );
    set.setStartDelay(itemIndex * 200);
    set.setDuration(1000 - itemIndex * 200); //not the actual time the animation will be played
    if(open) {
        offsetAnimator.addAnimatorSet(set, 0, 1);
    } else {
        offsetAnimator.addAnimatorSet(set, 1, 0);
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Only show items in the action bar relevant to this screen
    // if the drawer is not showing. Otherwise, let the drawer
    // decide what to show in the action bar.
    if(mDrawerLayout.isDrawerOpen(findViewById(R.id.drawerList))) {
        getMenuInflater().inflate(R.menu.drawer, menu);
        mProgressDrawerListener.setMenuItemAnimation(
                mCloseAnimation);
    } else {
        getMenuInflater().inflate(R.menu.main, menu);
        mProgressDrawerListener.setMenuItemAnimation(
                mOpenAnimation);
        mDrawerLayout.setDrawerListener(mProgressDrawerListener);
    }

    return super.onCreateOptionsMenu(menu);
}

menu_animation.xml: This is to get the custom ActionView to have the same layout as the view used by MenuIem

<?xml version="1.0" encoding="utf-8"?>
    <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/menu_animation"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:minWidth="@*android:dimen/action_button_min_width"
        android:padding="8dp"
        style="@style/Widget.AppCompat.ActionBar" />

这篇关于如何在动作栏通过Appcompat更改其内容时添加动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆