在Android中动画移动一个View的位置,采用Scroller类实现

今天说最近自己遇到的一个问题,就是要用动画效果来移动一个VIew的位置。

这个具体的情况是,需要做一个SlidingMenu的app,之前找了一个开源的,但不知道为什么,用起来app的运行效率很低,会有卡顿的现象。无奈只要自己写了。

SlidingMenu核心的就是可以滑动拉开左侧和右侧的菜单。刚开始考虑用TranslationAnimation来做。不过TranslationAnimation并不是真的移动一个View的坐标,在网上找了找,需要在Animation结束的时候,重新去layout下View的坐标,经过测试,这个方式可以达到预期效果。代码如下:

final int xOffset = leftFrameLayout.getWidth();
        TranslateAnimation translateAnimation = new TranslateAnimation(0, xOffset, 0, 0);

        translateAnimation.setDuration(200);
        translateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                //To change body of implemented methods use File | Settings | File Templates.
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                int left = xOffset;
                int top = centerFrameLayout.getTop();
                int width = centerFrameLayout.getWidth();
                int height = centerFrameLayout.getHeight();
                centerFrameLayout.clearAnimation();
                centerFrameLayout.layout(left, top, left + width, top + height);

                leftFrameLayout.bringToFront();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                //To change body of implemented methods use File | Settings | File Templates.
            }
        });
        centerFrameLayout.startAnimation(translateAnimation);
貌似没什么问题了,不过我的界面中,当显示SldingMenu的侧边栏的时候,里面有个输入框,点击输入框弹出键盘的时候,会导致界面重新layout,这时候中间被移动的view,就又给自动移动回来了,看来用
centerFrameLayout.layout
无法解决键盘弹出时候的重绘。

这时考虑到使用Scroller类来进行动画移动。也是参考了网上的例子,将我中间部分的FrameLayout搞成一个自定义类,代码如下:

public class ScrollableFrameLayout extends FrameLayout {
    private Scroller scroller;

    public ScrollableFrameLayout(Context context) {
        super(context);
        init();
    }

    public ScrollableFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ScrollableFrameLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init(){
        scroller = new Scroller(getContext());
    }

    @Override
    public void scrollTo(int x, int y) {
        super.scrollTo(x, y);
        postInvalidate();
    }

    @Override
    public void computeScroll() {
        if (!scroller.isFinished()) {
            if (scroller.computeScrollOffset()) {
                int oldX = getScrollX();
                int oldY = getScrollY();
                int x = scroller.getCurrX();
                int y = scroller.getCurrY();
                if (oldX != x || oldY != y) {
                    scrollTo(x, y);
                }
                // Keep on drawing until the animation has finished.
                invalidate();
            } else {
                clearChildrenCache();
            }
        } else {
            clearChildrenCache();
        }
    }

   public void smoothScrollTo(int dx, int duration) {

        int oldScrollX = getScrollX();
        scroller.startScroll(oldScrollX, getScrollY(), dx, getScrollY(), duration);
        invalidate();
    }

    private void enableChildrenCache() {
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final View layout = (View) getChildAt(i);
            layout.setDrawingCacheEnabled(true);
        }
    }

    private void clearChildrenCache() {
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final View layout = (View) getChildAt(i);
            layout.setDrawingCacheEnabled(false);
        }
    }

}
然后在需要移动这个类的地方调用:

int xOffset = rightFrameLayout.getWidth();

        centerFrameLayout.bringToFront();

        centerFrameLayout.smoothScrollTo(-xOffset, SCROLL_DURATION);

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                rightFrameLayout.setVisibility(View.INVISIBLE);
            }
        }, SCROLL_DURATION);

问题完美解决

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值