Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Precise control over Androids VectorDrawable animations

Tags:

UPDATE: Solution found! Scroll down for my accepted answer!

I want to animate multiple elements of one image and link the animation to ViewPagers position (so multiple elements are morphing or flying in/out depending on the current page being dragged).

So, is there a way to precisely control the current frame of the animation? For example let's assume i have this set:

<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android">     <objectAnimator         android:interpolator="@android:anim/decelerate_interpolator"         android:duration="800"         android:propertyName="scaleY"         android:valueFrom="0"         android:valueTo="1" />     <objectAnimator         android:interpolator="@android:anim/decelerate_interpolator"         android:duration="800"         android:propertyName="scaleX"         android:valueFrom="0"         android:valueTo="1" />     <objectAnimator         android:interpolator="@android:anim/decelerate_interpolator"         android:duration="800"         android:propertyName="rotation"         android:valueFrom="0"         android:valueTo="360" /> </set> 

Animated vector file:

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"     android:drawable="@drawable/pre_signup_1" >     <target         android:name="plus_button"         android:animation="@anim/pre_signup_1_plus_container" />     <target         android:name="plus"         android:animation="@anim/pre_signup_1_plus_sign" /> </animated-vector> 

Java code to run the animation:

ImageView mImage1 = (ImageView) findViewById(R.id.image_1); AnimatedVectorDrawableCompat animated = (AnimatedVectorDrawableCompat) mImage1.getDrawable();  animated.start(); 

Is there a way to control the animation like setCurrentDuration(400) which will presumably set the current state of the animation to it's half? Maybe there is a way to split that vector drawable into layers and animate them programmatically? Thanks in advance!

like image 487
Arthur Avatar asked May 03 '16 11:05

Arthur


People also ask

What are the type of animation offered by Android?

The animations are basically of three types as follows: Property Animation. View Animation. Drawable Animation.

Can we do animation in Android?

On Android 4.4 (API level 19) and higher, you can use the transition framework to create animations when you swap the layout within the current activity or fragment. All you need to do is specify the starting and ending layout, and what type of animation you want to use.

How do you use animated vector drawable?

Load the Animated Vector Drawable in Android Studioxml file into the res/drawable folder of your Android Studio project. As it is Vector Drawable, you could put any width and height you want. If you put wrap_content , it will be per the size of the Vector Drawable, which in our case is 24dp . Now, you're done!


1 Answers

Looks like it is possible to access paths and groups inside VectorDrawableCompat and animate/morph them however you want!

After a some research I ended up duplicating the following classes from the android.support.graphics.drawable package: AndroidResources, PathParser, TypedArrayUtils, VectorDrawableCommon and VectorDrawableCompat.

Next we need to make the following method and classes public inside of the VectorDrawableCompat class: getTargetByName, VGroup and VFullPath.

Next in the VectorDrawableCompat class remove the block that checks for Android version (Build.VERSION.SDK_INT >= 23). Don't know why, but if you don't do it, the animating won't work on android API 23 and up (need more research).

I may have missed a couple of private methods, but it's just a matter of making them public if you run into problems.

So, now we have access to the layers of our VectorDrawable! Here is a small example of scaling a vector group depending on the ViewPager's position:

<?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android"     android:width="276dp"     android:height="359dp"     android:viewportWidth="276"     android:viewportHeight="359">      <group         android:pivotX="205.5"         android:pivotY="214.5"         android:name="my_group">         <path             android:strokeColor="#4D394B"             android:strokeWidth="7"             android:strokeLineJoin="bevel"             android:fillColor="#1ED761"             android:pathData="M206.5,180 C186.9,180,171,195.9,171,215.5 S186.9,251,206.5,251 C226.1,251,242,235.1,242,215.5 S226.1,180,206.5,180 Z" />         <path             android:fillColor="#4D394B"             android:pathData="M210,211 L210,190 L202,190 L202,211 L181,211 L181,219 L202,219 L202,241 L210,241 L210,219 L232,219 L232,211 Z" />     </group> </vector> 

And this is the code used to animate the group:

ImageView myImageView; VectorDrawableCompat.VGroup myVectorGroup;  @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_welcome);      myImageView = (ImageView) findViewById(R.id.image_1);      VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(getResources(), R.drawable.my_vector_drawable, null);     vectorDrawable.setAllowCaching(false); // Important to allow image updates     myVectorGroup = (VectorDrawableCompat.VGroup) vectorDrawable.getTargetByName("my_group");      myImageView.setImageDrawable(vectorDrawable);      mViewPager = (ViewPager) findViewById(R.id.pager);     mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {         @Override         public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {             if(myVectorGroup != null && position < 1) {                 myVectorGroup.setScaleX(1f - positionOffset);                 myVectorGroup.setScaleY(1f - positionOffset);                  myImageView.invalidate();             }         }     }); } 

I need some more testing to determine compatibility, but it works for now!

like image 123
Arthur Avatar answered Oct 22 '22 00:10

Arthur