2

我正在開發一個floatie,類似於Facebook中的chatHead或OneNote中的floatie。TranslateAnimation移動視圖,但沒有動畫

一旦我創建了它,我需要能夠通過觸摸圖標來移動它,但是當我停止拖動並鬆開手指時,我希望圖標返回到屏幕的左邊緣。

通過使用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的。

當收到MotionEvent.ACTION_UP時,我希望圖標平滑地返回到屏幕的左邊緣。

可見,當我拖動圖標,然後釋放手指時,圖標仍保持在同一位置。當我再次觸摸它時,圖標在左邊顯示得很快,這顯然是「params.x = initialX;」的原因指令。

請幫忙嗎? 謝謝 Jaime

+0

如果需要,我還可以使用Animators而不是MoveAnimator。 – tim

回答

5

我實現了一個類似的功能。 我從bubbles for AndroidMagnet中獲得了一些靈感,但我根據您的要求進行了調整。

//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在X軸上始終返回0。然而,如果你喜歡,你可以得到你的設備的screenWidth,並計算你的ImageView應該捕捉的最近的牆。

我建議你看看提供的Github代碼。