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代码。