蓝少泽

天生我材必有用,千金散去还复来。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

在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);


问题完美解决

 
posted on 2013-11-29 11:24  蓝少泽  阅读(579)  评论(0编辑  收藏  举报