Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating Android Window along with the View

I am doing a custom android build, in which my Service adds a View on top of every app. Using the following code:

WindowManager mWM = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
mParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_PHONE, 
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
                PixelFormat.TRANSLUCENT);
mParams.height = 117;
mParams.width = 366;
View myView = inflater.inflate(R.layout.myView,null);
mWM.addView(myView, mParams);

I am able to add the view successfully. I am animating the view using

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 300);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX).start();

I am seeing the view animate, but not the window. The transparent window where the view used to be, is not animating. This is same behavior as described in Android Property Animation

Another disadvantage of the view animation system is that it only modified where the View was drawn, and not the actual View itself. For instance, if you animated a button to move across the screen, the button draws correctly, but the actual location where you can click the button does not change, so you have to implement your own logic to handle this.

How do i animate the window along with the view?

Thanks

like image 830
Anil Maddala Avatar asked Sep 27 '22 06:09

Anil Maddala


2 Answers

You have two options to achieve this (keeping the user's touch feedback coherent with the View's position):

  1. Create a transparent container (like a FrameLayout) big enough to contains your View plus its animation offset (in your case with an height of 366+300 px). In this way, you will add the container to the Window, while the View stays inside the container and can be animated/traslated.

  2. Move the absolute position of your View on the screen, creating a sort of custom animation; you just need to set the mParams.x value dynamically using a ValueAnimator or, if you want more bounciness, using a spring effect through the Rebound library. I suggest you the last one, it's really fancy!

Here's an (untested) example using Rebound:

SpringSystem springSystem = SpringSystem.create();
Spring spring = springSystem.createSpring();
final int originalPos = mParams.x;
final int offset = 300;
spring.addListener(new SimpleSpringListener() {

  @Override
  public void onSpringUpdate(Spring spring) {
    float value = (float) spring.getCurrentValue(); 
    mParams.x = originalPos + ((int) value*offset)
    mWM.updateViewLayout(myView, mParams);
  }
});
spring.setEndValue(1);

Remember that you need to add the Rebound's compile statement in your dependencies first:

// Gradle dependency on Rebound
dependencies {
  compile 'com.facebook.rebound:rebound:0.3.8'
}
like image 95
bonnyz Avatar answered Sep 30 '22 08:09

bonnyz


You could make it so that your window fills the entire screen by removing the height and width from the window params. If you want to control the view size, set it in your layout instead.


Otherwise, you can use a ValueAnimator and repeatedly call WindowManager's updateViewLayout:

ValueAnimator va = ValueAnimator.ofInt(mParams.x, 300);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    public void onAnimationUpdate(ValueAnimator animation) {
        Integer value = (Integer) animation.getAnimatedValue();
        mParams.x = value.intValue();
        mWM.updateViewLayout(myView, mParams);
    }
});
like image 36
tachyonflux Avatar answered Sep 30 '22 06:09

tachyonflux