1

Hi I need a floating bubble on top of my activity and I decided to use a service for that. Everything works well except that in Android 4.xx devices the imageView is not being animated. I have added listeners to the animation and the animation is run (it starts, repeats... and also the values change) but the imageView does not move. It works perfectly well on Android 5.x devices but not 4.x. Anybody has any idea why?

Here is the code:

public class SellFloatingBubbleService extends Service {
private WindowManager windowManager;
private ImageView imageView;

@Override
public void onCreate() {
    super.onCreate();
    imageView = new ImageView(this);
    imageView.setImageResource(R.drawable.tabbar_tooltip_v3);
    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

    final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
            LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT,
            LayoutParams.TYPE_PHONE,
            LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);
    layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
    layoutParams.y = (int) TypedValue.applyDimension(TypedValue
            .COMPLEX_UNIT_PX, getResources().getDimensionPixelOffset(R.dimen
            .sell_button_height), getResources().getDisplayMetrics());
    windowManager.addView(imageView, layoutParams);
    imageView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            stopSelf();
            return true;
        }
    });

    /**
     * When these animations will end they will revert and then play endlessly.
     */
    AnimatorSet bouncer = new AnimatorSet();
    ObjectAnimator animX = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 0.8f);
    animX.setRepeatMode(ValueAnimator.REVERSE);
    animX.setRepeatMode(-1);
    ObjectAnimator animY = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 0.8f);
    animY.setRepeatMode(ValueAnimator.REVERSE);
    animY.setRepeatCount(-1);
    bouncer.playTogether(animX, animY);
    bouncer.setDuration(1000);
    bouncer.setInterpolator(new AccelerateDecelerateInterpolator());
    bouncer.start();
}

@Override
public void onDestroy() {
    imageView.setVisibility(View.GONE);
    windowManager.removeView(imageView);
    super.onDestroy();
}

@Override
public IBinder onBind(Intent intent) {
    return null;
 }
}

I have tried the same animation on another view, not in a service and it works. I also tried replacing ObjectAnimator by the old animations and the problem is still the same.

Is there something wrong about the code?

vallllll
  • 2,731
  • 6
  • 43
  • 77

1 Answers1

1

Putting ImageView inside LinearLayout fixed the problem of the imageView not being animated. Here is the code:

public class SellFloatingBubbleService extends Service {

public static final int ANIMATION_DURATION = 500;
private WindowManager windowManager;
private ImageView imageView;
private int animationDistance;
private LinearLayout layout;

private static SellFloatingBubbleService instance = null;

public static boolean isInstanceCreated() {
    return instance != null;
}

@Override
public void onCreate() {
    super.onCreate();
    BusProvider.getInstance().post(new BubbleWillBeShownEvent());
    instance = this;
    /**
     * Animations do not work in Android 4.XX if view is not added inside a view group
     */
    layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);
    imageView = new ImageView(this);
    layout.addView(imageView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    imageView.setImageResource(R.drawable.tabbar_tooltip_v);
    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    animationDistance = (int) getResources().getDimension(R.dimen.sell_bubble_animation_height);
    final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
            LayoutParams.WRAP_CONTENT,
            (int) getResources().getDimension(R.dimen.sell_bubble_window_height),
            LayoutParams.TYPE_PHONE,
            LayoutParams.FLAG_NOT_TOUCH_MODAL, //touch events are transmitted to windows below
            PixelFormat.TRANSLUCENT);
    layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
    layoutParams.windowAnimations = android.R.style.Animation_Toast;
    int sellButtonHeight = getResources().getDimensionPixelOffset(R.dimen
            .sell_button_height);

    layoutParams.y = sellButtonHeight / 2;
    windowManager.addView(layout, layoutParams);
    createAndStartAnimation();
}

private void createAndStartAnimation() {
    /**
     * When these animations will end they will revert and then play endlessly.
     */

    float startValue = imageView.getY();
    float endValue = imageView.getY() - animationDistance;
    AnimatorSet animatorSet = new AnimatorSet();
    ObjectAnimator animYUp = ObjectAnimator.ofFloat(imageView, "y", startValue,
            endValue);
    animYUp.setRepeatMode(ValueAnimator.REVERSE);
    animYUp.setRepeatCount(ValueAnimator.INFINITE);
    animYUp.setDuration(ANIMATION_DURATION);
    animYUp.setInterpolator(new DecelerateInterpolator()); //decelerate interpolator for up

    ObjectAnimator animYDown = ObjectAnimator.ofFloat(imageView, "y", endValue,
            startValue);
    animYDown.setRepeatCount(ValueAnimator.INFINITE);
    animYDown.setDuration(ANIMATION_DURATION);
    animYDown.setInterpolator(new AccelerateInterpolator()); //accelerate interpolator for down
    animatorSet.play(animYDown).after(animYUp);
    animatorSet.start();
}

@Override
public void onDestroy() {
    BusProvider.getInstance().post(new BubbleWillBeHiddenEvent());
    instance = null;
    imageView.setVisibility(View.INVISIBLE);
    windowManager.removeView(layout);
    super.onDestroy();
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}
vallllll
  • 2,731
  • 6
  • 43
  • 77