TranslateAnimation перемещает вид, но без анимации

Я разрабатываю floatie, похожий на chatHead в facebook или floatie в OneNote.

После того, как я его создал, мне нужно иметь возможность перемещать его, касаясь значка, но когда я перестаю перетаскивать и отпускаю палец, я хочу, чтобы значок вернулся к левому краю экрана.

С помощью TranslateAnimation это работает, но без анимации. Значок появляется на левом краю, когда я снова касаюсь значка.

Это соответствующий код:

    trackerHead.setOnTouchListener(new View.OnTouchListener() {
        private int initialX;
        private int initialY;
        private float initialTouchX;
        private float initialTouchY;

        @Override public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    initialX = params.x;
                    initialY = params.y;
                    initialTouchX = event.getRawX();
                    initialTouchY = event.getRawY();
                    return true;
                case MotionEvent.ACTION_UP:
                    TranslateAnimation animation = new TranslateAnimation(
                            TranslateAnimation.ABSOLUTE, params.x,
                            TranslateAnimation.ABSOLUTE, initialX,
                            TranslateAnimation.ABSOLUTE, params.y,
                            TranslateAnimation.ABSOLUTE, params.y);
                    animation.setDuration(4000);
                    animation.setRepeatCount(1);
                    animation.setInterpolator(new AccelerateInterpolator());
                    trackerHead.startAnimation(animation);
                    params.x = initialX;
                    return true;
                case MotionEvent.ACTION_MOVE:
                    params.x = initialX + (int) (event.getRawX() - initialTouchX);
                    params.y = initialY + (int) (event.getRawY() - initialTouchY);
                    windowManager.updateViewLayout(trackerHead, params);
                    return true;
            }
            return false;
        }
    });

где trackerHead — это ImageView, который добавляется на экран с помощью WindowManager.

Когда MotionEvent.ACTION_UP получен, я хочу, чтобы значок плавно возвращался к левому краю экрана.

Визуально, когда я перетаскиваю значок, а затем отпускаю палец, значок остается на том же месте. Когда я снова касаюсь его, значок быстро появляется у левого края, что является очевидной причиной «params.x = initialX;» инструкция.

Любая помощь, пожалуйста? Спасибо, Хайме.


person jstuardo    schedule 30.11.2015    source источник
comment
У меня также есть решение с аниматорами вместо MoveAnimator, если хотите.   -  person tim    schedule 08.12.2015


Ответы (1)


Я реализовал аналогичную функцию. Я черпал вдохновение из bubbles для Android и Magnet, но я изменил его по вашему запросу.

//your imageView
private ImageView trackerHead;
private boolean isBeingDragged;
private WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                        WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                PixelFormat.TRANSLUCENT
        );

//Constructor or entry for your WindowManager service
public void onCreate() {
    super.onCreate();

    windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
    animator = new MoveAnimator();
    this.trackerHead.setOnTouchListener(this);
    windowManager.addView(trackerHead, params);
}

@Override
public boolean onTouch(View view, MotionEvent event) {
    float x = event.getRaw  X();
    float y = event.getRawY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            animator.stop();
            isBeingDragged = true;
            break;
        case MotionEvent.ACTION_UP:
            isBeingDragged = false;
            stickToLeftWall();
            break;
        case MotionEvent.ACTION_MOVE:
            if (isBeingDragged) {
                move(x - lastXPose, y - lastYPose);
            }
            break;
    }

    lastXPose = x;
    lastYPose = y;

    return false;
}

private void stickToLeftWall() {
    animator.start(this, 0); 
}

Класс MoveAnimator можно разместить как внутренний класс.

class MoveAnimator implements Runnable {

    private Handler handler = new Handler(Looper.getMainLooper());
    private float destinationX;
    private float destinationY;
    private long startingTime;

    private void start(float x, float y) {
        this.destinationX = x;
        this.destinationY = y;
        startingTime = System.currentTimeMillis();
        handler.post(this);
    }

    @Override
    public void run() {
        if (trackerHead != null && trackerHead.getParent() != null) {
            float progress = Math.min(1, (System.currentTimeMillis() - startingTime) / 400f);
            float deltaX = (destinationX - mLayoutParams.x) * progress;
            float deltaY = (destinationY - mLayoutParams.y) * progress;
            move(deltaX, deltaY);
            if (progress < 1) {
                handler.post(this);
            }
        }
    }

    private void stop() {
        handler.removeCallbacks(this);
    }
}

Здесь важна функция stickToLeftWall. Это позволит вашему ImageView всегда возвращаться к 0 по оси X. Однако, если хотите, вы можете получить screenWidth вашего устройства и рассчитать ближайшую стену, к которой должен привязываться ваш ImageView.

Я предлагаю вам взглянуть на предоставленный код Github.

person tim    schedule 06.12.2015