How to animate background of ActionMode of the ActionBar?
Asked Answered
M

1

6

Background

It's possible to change the background of the actionbar, and even animate between two colors, as such:

public static void animateBetweenColors(final ActionBar actionBar, final int colorFrom, final int colorTo,
        final int durationInMs) {
    final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
    colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
        ColorDrawable colorDrawable = new ColorDrawable(colorFrom);

        @Override
        public void onAnimationUpdate(final ValueAnimator animator) {
            colorDrawable.setColor((Integer) animator.getAnimatedValue());
            actionBar.setBackgroundDrawable(colorDrawable);
        }
    });
    if (durationInMs >= 0)
        colorAnimation.setDuration(durationInMs);
    colorAnimation.start();
}

The problem

I can't find a way to get the view of the action mode, so that I could change its background on some cases (while it's showing).

What I tried

Only thing I found is a hack-y way which assumes that the id of the action mode will stay the same, and even this would work just for the view of the "done" button (the one that looks like an "V" and is actually more like "cancel").

I also found how to change it via themes, but that's not what I need, since I need to do it programmatically.

The question

How do I get the view of the actionMode, or, more precisely, how can I change its background using an animation?

Mnemonic answered 4/5, 2014 at 15:0 Comment(2)
CHECK THIS cyrilmottier.com/2012/11/27/actionbar-on-the-moveComplect
@ZohraKhan As I've already mentioned, I know how to change the background of the action bar. I want to know how to change the background of the ActionMode of it.Mnemonic
C
11

How do I get the view of the actionMode, or, more precisely, how can I change its background using an animation?

You have two choices, unfortunately neither of which involve native ActionMode APIs:

The ActionBarContextView is responsible for controlling the ActionMode

  1. Use Resources.getIdentifier to call Activity.findViewById and pass in the ID the system uses for the ActionBarContextView
  2. Use reflection to access to Field in ActionBarImpl

Here's an example of both:

Using Resources.getIdentifier:

private void animateActionModeViaFindViewById(int colorFrom, int colorTo, int duration) {
    final int amId = getResources().getIdentifier("action_context_bar", "id", "android");
    animateActionMode(findViewById(amId), colorFrom, colorTo, duration);
}

Using reflection:

private void animateActionModeViaReflection(int colorFrom, int colorTo, int duration) {
    final ActionBar actionBar = getActionBar();
    try {
        final Field contextView = actionBar.getClass().getDeclaredField("mContextView");
        animateActionMode((View) contextView.get(actionBar), colorFrom, colorTo, duration);
    } catch (final Exception ignored) {
        // Nothing to do
    }
}

private void animateActionMode(final View actionMode, final int from, int to, int duration) {
    final ValueAnimator va = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
    final ColorDrawable actionModeBackground = new ColorDrawable(from);
    va.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(final ValueAnimator animator) {
            actionModeBackground.setColor((Integer) animator.getAnimatedValue());
            actionMode.setBackground(actionModeBackground);
        }

    });
    va.setDuration(duration);
    va.start();
}

Results

Here's a gif of the results animating from Color.BLACK to Color.BLUE at a duration of 2500:

Example

Caseous answered 5/5, 2014 at 0:13 Comment(8)
Is it possible perhaps to use a custom view, that will use the default one ?Mnemonic
@androiddeveloper No, ActionMode.setCustomView only replaces the title layout.Caseous
The title layout? is this just the area of the text being shown ( "Text Selection" in your image) ?Mnemonic
@androiddeveloper Yep.Caseous
So it's pretty much useless... Is there any other way to overcome this?Mnemonic
@androiddeveloper No, not that I'm aware of.Caseous
You might forget about contextView.setAccessible(true);Zara
Resources.getIdentifier does not work for me, but reflection does. But remember the line: contextView.setAccessible(true); unless it throws IllegalAccessExceptions.Aloeswood

© 2022 - 2024 — McMap. All rights reserved.