I'm trying to understand if menu icon animation should work in the new Navigationview, the same way action items animation works or any other view for that matter, that is used on any app layout.
The code below doesn't work for me. I'm using for testing the code sample released by Android for the new support library. Same animation code works nicely on the toolbar. Also tried the older API for animation (followed that link: Animated Icon for ActionItem)
I guess I'm missing something...
thanks ahead.
Code:
Xml:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:background="@color/lightPrimaryColor">
<include layout="@layout/include_list_viewpager"/>
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="start"
android:fitsSystemWindows="true"
android:background="@color/lightPrimaryColor"
app:headerLayout="@layout/nav_header"
app:theme="@style/menu_item_style"
app:menu="@menu/drawer_view"/>
</android.support.v4.widget.DrawerLayout>
drawer_view:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:class="http://schemas.android.com/tools"
class:actionViewClass="android.widget.ProgressBar">
<group android:checkableBehavior="single"
android:id="@+id/drawer_menu">
<!-- <item
android:id="@+id/nav_my_lists"
android:title="@string/title_shopping_lists"
android:icon="@drawable/ic_event"
app:showAsAction="always"/> -->
<item
android:id="@+id/nav_examp_lists"
android:icon="@drawable/refresh1"
android:title="@string/example"
app:showAsAction="always"
android:layoutDirection="rtl"/>
<item
android:id="@+id/nav_split_lists"
android:title="@string/split"
android:icon="@drawable/refresh2"
app:showAsAction="always"
app:actionViewClass="android.widget.ImageView"/>
<item
android:id="@+id/nav_change_net"
android:title="@string/change"
android:icon="@drawable/refresh3"
app:showAsAction="always"
android:layoutDirection="rtl"/>
</group>
</menu>
java:
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
mDrawerLayout.closeDrawers();
switch (menuItem.getItemId()) {
case R.id.nav_my_lists:
anim = AnimatorInflater.loadAnimator(getApplication(), R.animator.rotation);
anim.setTarget(menuItem.getIcon());
anim.setDuration(2000);
//anim.setStartDelay(10);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
Toast.makeText(getApplication(), "Started...", Toast.LENGTH_SHORT).show();
}
});
anim.start();
boolean run = anim.isRunning();
String title = menuItem.getTitle().toString();
loadShoppingList(title);
return true;
It is possible. You don't need set custom View for that.
private AnimationDrawableWrapper drawableWrapper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
Menu menu = navigationView.getMenu();
MenuItem menuItem = menu.findItem(R.id.your_icon);
Drawable icon = menuItem.getIcon();
drawableWrapper = new AnimationDrawableWrapper(getResources(), icon);
menuItem.setIcon(drawableWrapper);
}
public void startRotateIconAnimation() {
ValueAnimator animator = ObjectAnimator.ofInt(0, 360);
animator.addUpdateListener(animation -> {
int rotation = (int) animation.getAnimatedValue();
drawableWrapper.setRotation(rotation);
});
animator.start();
}
We can't animate drawable directly, so use DrawableWrapper(from android.support.v7 for API<21):
public class AnimationDrawableWrapper extends DrawableWrapper {
private float rotation;
private Rect bounds;
public AnimationDrawableWrapper(Resources resources, Drawable drawable) {
super(vectorToBitmapDrawableIfNeeded(resources, drawable));
bounds = new Rect();
}
@Override
public void draw(Canvas canvas) {
copyBounds(bounds);
canvas.save();
canvas.rotate(rotation, bounds.centerX(), bounds.centerY());
super.draw(canvas);
canvas.restore();
}
public void setRotation(float degrees) {
this.rotation = degrees % 360;
invalidateSelf();
}
/**
* Workaround for issues related to vector drawables rotation and scaling:
* https://code.google.com/p/android/issues/detail?id=192413
* https://code.google.com/p/android/issues/detail?id=208453
*/
private static Drawable vectorToBitmapDrawableIfNeeded(Resources resources, Drawable drawable) {
if (drawable instanceof VectorDrawable) {
Bitmap b = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
drawable.setBounds(0, 0, c.getWidth(), c.getHeight());
drawable.draw(c);
drawable = new BitmapDrawable(resources, b);
}
return drawable;
}
}
I took the idea for DrawableWrapper from here: https://stackoverflow.com/a/39108111/5541688
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With