Example usage for android.graphics.drawable Drawable setBounds

List of usage examples for android.graphics.drawable Drawable setBounds

Introduction

In this page you can find the example usage for android.graphics.drawable Drawable setBounds.

Prototype

public void setBounds(int left, int top, int right, int bottom) 

Source Link

Document

Specify a bounding rectangle for the Drawable.

Usage

From source file:com.handmark.pulltorefresh.library.internal.LoadingLayout.java

private void rotateArrow() {
    final Drawable drawable = mHeaderArrow.getDrawable();
    final Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
            Config.ARGB_8888);/*from  w w w. jav  a  2 s  . c  o m*/
    final Canvas canvas = new Canvas(bitmap);
    canvas.save();
    canvas.rotate(180.0f, canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f);
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    drawable.draw(canvas);
    canvas.restore();
    mHeaderArrow.setImageBitmap(bitmap);
}

From source file:app.abhijit.iter.MainActivity.java

private void setupGettingStartedHint() {
    TextView gettingStartedHint = (TextView) findViewById(R.id.hint_getting_started);
    int lineHeight = gettingStartedHint.getLineHeight();
    Drawable hamburgerIcon = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_hamburger, null);
    hamburgerIcon.setBounds(0, 0, lineHeight, lineHeight);
    SpannableStringBuilder hintText = new SpannableStringBuilder();
    hintText.append(getResources().getString(R.string.hint_getting_started_1)).append(" ");
    hintText.setSpan(new ImageSpan(hamburgerIcon), hintText.length() - 1, hintText.length(), 0);
    hintText.append(getResources().getString(R.string.hint_getting_started_2));
    gettingStartedHint.setText(hintText);
}

From source file:org.ohmage.app.MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    mNavigationItems = getResources().getStringArray(R.array.navigation_items);
    mNavigationIcons = getResources().obtainTypedArray(R.array.navigation_icons);

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerList = (ListView) findViewById(R.id.left_drawer);

    // Set the adapter for the list view
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.simple_list_item_activated_1,
            mNavigationItems) {/*from  ww w.j av  a  2 s .  co  m*/

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // Set the left drawable of the text view to be the icon for that item
            TextView view = (TextView) super.getView(position, convertView, parent);
            Drawable d = getResources().getDrawable(mNavigationIcons.getResourceId(position, -1));

            if (d != null && view != null) {
                int bounds = getResources().getDimensionPixelSize(R.dimen.navigation_icon_bounds);
                d.setBounds(0, 0, bounds, bounds);
                view.setCompoundDrawables(d, null, null, null);
            }
            return view;
        }
    };

    mDrawerList.setAdapter(adapter);

    // Set the list's click listener
    mDrawerList.setOnItemClickListener(this);
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open,
            R.string.drawer_close);

    // Set the drawer toggle as the DrawerListener
    mDrawerLayout.setDrawerListener(mDrawerToggle);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);

    if (savedInstanceState == null) {
        if (getIntent().getBooleanExtra(EXTRA_VIEW_STREAMS, false)) {
            setFragment(getString(R.string.streams));
        } else {
            if (!handleNewIntent(getIntent())) {
                setFragment(0);
            }
        }
    }
}

From source file:com.geekandroid.sdk.base.BaseActivity.java

private Drawable getDrawable(TextView textView, int resId, int p, int b) {

    int padding = convertDp(p);
    int bounds = convertDp(b);

    Drawable drawable = getResources().getDrawable(resId);

    if (drawable != null) {
        if (bounds <= 0) {
            Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), resId);
            int height = bitmap.getHeight();
            int width = bitmap.getWidth();
            drawable.setBounds(0, 0, width, height);
        } else {/*from w ww  .  j  ava 2s  . co m*/
            drawable.setBounds(0, 0, bounds, bounds);
        }
    }
    if (padding > 0) {
        textView.setCompoundDrawablePadding(padding);
    }
    return drawable;
}

From source file:tv.acfun.video.CommentsActivity.java

private void initCommentsBar() {
    mCommentBar = findViewById(R.id.comments_bar);
    mBtnSend = (ImageButton) findViewById(R.id.comments_send_btn);
    mCommentText = (EditText) findViewById(R.id.comments_edit);
    mBtnEmotion = findViewById(R.id.comments_emotion_btn);
    mEmotionGrid = (GridView) findViewById(R.id.emotions);
    mBtnSend.setOnClickListener(this);
    mBtnEmotion.setOnClickListener(this);
    mEmotionGrid.setAdapter(mEmotionAdapter);
    mEmotionGrid.setOnItemClickListener(new OnItemClickListener() {

        @Override//from  ww w  . j  a  va  2s . c  om
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            int index = mCommentText.getSelectionEnd();
            Editable text = mCommentText.getText();
            String emotion = parent.getItemAtPosition(position).toString();
            text.insert(index, emotion);
            EmotionView v = (EmotionView) parent.getAdapter().getView(position, null, null);
            Drawable drawable = TextViewUtils.convertViewToDrawable(v);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth() / 2, drawable.getIntrinsicHeight() / 2);
            text.setSpan(new ImageSpan(drawable), index, index + emotion.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

    });
}

From source file:com.iangclifton.auid.horizontaliconview.HorizontalIconView.java

@Override
protected void onDraw(Canvas canvas) {
    if (mDrawables == null || mDrawables.isEmpty()) {
        return;//from   w  ww  .ja  v a 2  s  .  c  om
    }

    final int width = getWidth();
    final int paddingBottom = getPaddingBottom();
    final int paddingLeft = getPaddingLeft();
    final int paddingTop = getPaddingTop();

    // Determine edges of visible content
    final int leftEdge = getScrollX();
    final int rightEdge = leftEdge + width;

    int left = paddingLeft;
    int top = paddingTop;
    mSkippedIconCount = 0;

    final int iconCount = mDrawables.size();
    for (int i = 0; i < iconCount; i++) {
        if (left + mIconSize < leftEdge) {
            // Icon is too far left to be seen
            left = left + mIconSize + mIconSpacing;
            mSkippedIconCount++;
            continue;
        }

        if (left > rightEdge) {
            // All remaining icons are right of the view
            break;
        }

        // Get a reference to the icon to be drawn
        final Drawable icon = mDrawables.get(i);
        icon.setBounds(left, top, left + mIconSize, top + mIconSize);
        icon.draw(canvas);

        // Icon was drawn, so track position
        final int drawnPosition = i - mSkippedIconCount;
        if (drawnPosition + 1 > mIconPositions.size()) {
            final Rect rect = icon.copyBounds();
            mIconPositions.add(rect);
        } else {
            final Rect rect = mIconPositions.get(drawnPosition);
            icon.copyBounds(rect);
        }

        // Update left position
        left = left + mIconSize + mIconSpacing;
    }

    if (mEdgeEffectLeft != null) {
        if (!mEdgeEffectLeft.isFinished()) {
            final int restoreCount = canvas.save();
            final int height = getHeight() - paddingTop - paddingBottom;

            canvas.rotate(270);
            canvas.translate(-height + paddingTop, Math.min(0, leftEdge));
            mEdgeEffectLeft.setSize(height, getWidth());
            if (mEdgeEffectLeft.draw(canvas)) {
                postInvalidateOnAnimation();
            }
            canvas.restoreToCount(restoreCount);
        }
        if (!mEdgeEffectRight.isFinished()) {
            final int restoreCount = canvas.save();
            final int height = getHeight() - paddingTop - paddingBottom;

            canvas.rotate(90);
            canvas.translate(-paddingTop, -(Math.max(mScrollRange, leftEdge) + width));
            mEdgeEffectRight.setSize(height, width);
            if (mEdgeEffectRight.draw(canvas)) {
                postInvalidateOnAnimation();
            }
            canvas.restoreToCount(restoreCount);
        }
    }
}

From source file:de.dreier.mytargets.utils.transitions.FabTransform.java

@Override
public Animator createAnimator(@NonNull final ViewGroup sceneRoot, final TransitionValues startValues,
        final TransitionValues endValues) {
    if (startValues == null || endValues == null) {
        return null;
    }/*from   w  w w . ja  va2 s .co m*/

    final Rect startBounds = (Rect) startValues.values.get(PROP_BOUNDS);
    final Rect endBounds = (Rect) endValues.values.get(PROP_BOUNDS);

    final boolean fromFab = endBounds.width() > startBounds.width();
    final View view = endValues.view;
    final Rect dialogBounds = fromFab ? endBounds : startBounds;
    final Rect fabBounds = fromFab ? startBounds : endBounds;
    final Interpolator fastOutSlowInInterpolator = new FastOutSlowInInterpolator();
    final long duration = getDuration();
    final long halfDuration = duration / 2;
    final long twoThirdsDuration = duration * 2 / 3;

    if (!fromFab) {
        // Force measure / layout the dialog back to it's original bounds
        view.measure(makeMeasureSpec(startBounds.width(), View.MeasureSpec.EXACTLY),
                makeMeasureSpec(startBounds.height(), View.MeasureSpec.EXACTLY));
        view.layout(startBounds.left, startBounds.top, startBounds.right, startBounds.bottom);
    }

    final int translationX = startBounds.centerX() - endBounds.centerX();
    final int translationY = startBounds.centerY() - endBounds.centerY();
    if (fromFab) {
        view.setTranslationX(translationX);
        view.setTranslationY(translationY);
    }

    // Add a color overlay to fake appearance of the FAB
    final ColorDrawable fabColor = new ColorDrawable(color);
    fabColor.setBounds(0, 0, dialogBounds.width(), dialogBounds.height());
    if (!fromFab) {
        fabColor.setAlpha(0);
    }
    view.getOverlay().add(fabColor);

    // Add an icon overlay again to fake the appearance of the FAB
    final Drawable fabIcon = ContextCompat.getDrawable(sceneRoot.getContext(), icon).mutate();
    final int iconLeft = (dialogBounds.width() - fabIcon.getIntrinsicWidth()) / 2;
    final int iconTop = (dialogBounds.height() - fabIcon.getIntrinsicHeight()) / 2;
    fabIcon.setBounds(iconLeft, iconTop, iconLeft + fabIcon.getIntrinsicWidth(),
            iconTop + fabIcon.getIntrinsicHeight());
    if (!fromFab) {
        fabIcon.setAlpha(0);
    }
    view.getOverlay().add(fabIcon);

    // Circular clip from/to the FAB size
    final Animator circularReveal;
    if (fromFab) {
        circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2,
                view.getHeight() / 2, startBounds.width() / 2,
                (float) Math.hypot(endBounds.width() / 2, endBounds.height() / 2));
        circularReveal.setInterpolator(new FastOutLinearInInterpolator());
    } else {
        circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2,
                view.getHeight() / 2, (float) Math.hypot(startBounds.width() / 2, startBounds.height() / 2),
                endBounds.width() / 2);
        circularReveal.setInterpolator(new LinearOutSlowInInterpolator());

        // Persist the end clip i.e. stay at FAB size after the reveal has run
        circularReveal.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                view.setOutlineProvider(new ViewOutlineProvider() {
                    @Override
                    public void getOutline(View view, Outline outline) {
                        final int left = (view.getWidth() - fabBounds.width()) / 2;
                        final int top = (view.getHeight() - fabBounds.height()) / 2;
                        outline.setOval(left, top, left + fabBounds.width(), top + fabBounds.height());
                        view.setClipToOutline(true);
                    }
                });
            }
        });
    }
    circularReveal.setDuration(duration);

    // Translate to end position along an arc
    final Animator translate = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y,
            fromFab ? getPathMotion().getPath(translationX, translationY, 0, 0)
                    : getPathMotion().getPath(0, 0, -translationX, -translationY));
    translate.setDuration(duration);
    translate.setInterpolator(fastOutSlowInInterpolator);

    // Fade contents of non-FAB view in/out
    List<Animator> fadeContents = null;
    if (view instanceof ViewGroup) {
        final ViewGroup vg = ((ViewGroup) view);
        fadeContents = new ArrayList<>(vg.getChildCount());
        for (int i = vg.getChildCount() - 1; i >= 0; i--) {
            final View child = vg.getChildAt(i);
            final Animator fade = ObjectAnimator.ofFloat(child, View.ALPHA, fromFab ? 1f : 0f);
            if (fromFab) {
                child.setAlpha(0f);
            }
            fade.setDuration(twoThirdsDuration);
            fade.setInterpolator(fastOutSlowInInterpolator);
            fadeContents.add(fade);
        }
    }

    // Fade in/out the fab color & icon overlays
    final Animator colorFade = ObjectAnimator.ofInt(fabColor, "alpha", fromFab ? 0 : 255);
    final Animator iconFade = ObjectAnimator.ofInt(fabIcon, "alpha", fromFab ? 0 : 255);
    if (!fromFab) {
        colorFade.setStartDelay(halfDuration);
        iconFade.setStartDelay(halfDuration);
    }
    colorFade.setDuration(halfDuration);
    iconFade.setDuration(halfDuration);
    colorFade.setInterpolator(fastOutSlowInInterpolator);
    iconFade.setInterpolator(fastOutSlowInInterpolator);

    // Work around issue with elevation shadows. At the end of the return transition the shared
    // element's shadow is drawn twice (by each activity) which is jarring. This workaround
    // still causes the shadow to snap, but it's better than seeing it double drawn.
    Animator elevation = null;
    if (!fromFab) {
        elevation = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, -view.getElevation());
        elevation.setDuration(duration);
        elevation.setInterpolator(fastOutSlowInInterpolator);
    }

    // Run all animations together
    final AnimatorSet transition = new AnimatorSet();
    transition.playTogether(circularReveal, translate, colorFade, iconFade);
    transition.playTogether(fadeContents);
    if (elevation != null) {
        transition.play(elevation);
    }
    if (fromFab) {
        transition.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // Clean up
                view.getOverlay().clear();
            }
        });
    }
    return new NoPauseAnimator(transition);
}

From source file:com.amitupadhyay.aboutexample.ui.transitions.FabTransform.java

@Override
public Animator createAnimator(final ViewGroup sceneRoot, final TransitionValues startValues,
        final TransitionValues endValues) {
    if (startValues == null || endValues == null)
        return null;

    final Rect startBounds = (Rect) startValues.values.get(PROP_BOUNDS);
    final Rect endBounds = (Rect) endValues.values.get(PROP_BOUNDS);

    final boolean fromFab = endBounds.width() > startBounds.width();
    final View view = endValues.view;
    final Rect dialogBounds = fromFab ? endBounds : startBounds;
    final Rect fabBounds = fromFab ? startBounds : endBounds;
    final Interpolator fastOutSlowInInterpolator = AnimUtils
            .getFastOutSlowInInterpolator(sceneRoot.getContext());
    final long duration = getDuration();
    final long halfDuration = duration / 2;
    final long twoThirdsDuration = duration * 2 / 3;

    if (!fromFab) {
        // Force measure / layout the dialog back to it's original bounds
        view.measure(makeMeasureSpec(startBounds.width(), View.MeasureSpec.EXACTLY),
                makeMeasureSpec(startBounds.height(), View.MeasureSpec.EXACTLY));
        view.layout(startBounds.left, startBounds.top, startBounds.right, startBounds.bottom);
    }/*  w ww .  j a  v  a2  s . c om*/

    final int translationX = startBounds.centerX() - endBounds.centerX();
    final int translationY = startBounds.centerY() - endBounds.centerY();
    if (fromFab) {
        view.setTranslationX(translationX);
        view.setTranslationY(translationY);
    }

    // Add a color overlay to fake appearance of the FAB
    final ColorDrawable fabColor = new ColorDrawable(color);
    fabColor.setBounds(0, 0, dialogBounds.width(), dialogBounds.height());
    if (!fromFab)
        fabColor.setAlpha(0);
    view.getOverlay().add(fabColor);

    // Add an icon overlay again to fake the appearance of the FAB
    final Drawable fabIcon = ContextCompat.getDrawable(sceneRoot.getContext(), icon).mutate();
    final int iconLeft = (dialogBounds.width() - fabIcon.getIntrinsicWidth()) / 2;
    final int iconTop = (dialogBounds.height() - fabIcon.getIntrinsicHeight()) / 2;
    fabIcon.setBounds(iconLeft, iconTop, iconLeft + fabIcon.getIntrinsicWidth(),
            iconTop + fabIcon.getIntrinsicHeight());
    if (!fromFab)
        fabIcon.setAlpha(0);
    view.getOverlay().add(fabIcon);

    // Circular clip from/to the FAB size
    final Animator circularReveal;
    if (fromFab) {
        circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2,
                view.getHeight() / 2, startBounds.width() / 2,
                (float) Math.hypot(endBounds.width() / 2, endBounds.height() / 2));
        circularReveal.setInterpolator(AnimUtils.getFastOutLinearInInterpolator(sceneRoot.getContext()));
    } else {
        circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2,
                view.getHeight() / 2, (float) Math.hypot(startBounds.width() / 2, startBounds.height() / 2),
                endBounds.width() / 2);
        circularReveal.setInterpolator(AnimUtils.getLinearOutSlowInInterpolator(sceneRoot.getContext()));

        // Persist the end clip i.e. stay at FAB size after the reveal has run
        circularReveal.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                view.setOutlineProvider(new ViewOutlineProvider() {
                    @Override
                    public void getOutline(View view, Outline outline) {
                        final int left = (view.getWidth() - fabBounds.width()) / 2;
                        final int top = (view.getHeight() - fabBounds.height()) / 2;
                        outline.setOval(left, top, left + fabBounds.width(), top + fabBounds.height());
                        view.setClipToOutline(true);
                    }
                });
            }
        });
    }
    circularReveal.setDuration(duration);

    // Translate to end position along an arc
    final Animator translate = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y,
            fromFab ? getPathMotion().getPath(translationX, translationY, 0, 0)
                    : getPathMotion().getPath(0, 0, -translationX, -translationY));
    translate.setDuration(duration);
    translate.setInterpolator(fastOutSlowInInterpolator);

    // Fade contents of non-FAB view in/out
    List<Animator> fadeContents = null;
    if (view instanceof ViewGroup) {
        final ViewGroup vg = ((ViewGroup) view);
        fadeContents = new ArrayList<>(vg.getChildCount());
        for (int i = vg.getChildCount() - 1; i >= 0; i--) {
            final View child = vg.getChildAt(i);
            final Animator fade = ObjectAnimator.ofFloat(child, View.ALPHA, fromFab ? 1f : 0f);
            if (fromFab) {
                child.setAlpha(0f);
            }
            fade.setDuration(twoThirdsDuration);
            fade.setInterpolator(fastOutSlowInInterpolator);
            fadeContents.add(fade);
        }
    }

    // Fade in/out the fab color & icon overlays
    final Animator colorFade = ObjectAnimator.ofInt(fabColor, "alpha", fromFab ? 0 : 255);
    final Animator iconFade = ObjectAnimator.ofInt(fabIcon, "alpha", fromFab ? 0 : 255);
    if (!fromFab) {
        colorFade.setStartDelay(halfDuration);
        iconFade.setStartDelay(halfDuration);
    }
    colorFade.setDuration(halfDuration);
    iconFade.setDuration(halfDuration);
    colorFade.setInterpolator(fastOutSlowInInterpolator);
    iconFade.setInterpolator(fastOutSlowInInterpolator);

    // Work around issue with elevation shadows. At the end of the return transition the shared
    // element's shadow is drawn twice (by each activity) which is jarring. This workaround
    // still causes the shadow to snap, but it's better than seeing it double drawn.
    Animator elevation = null;
    if (!fromFab) {
        elevation = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, -view.getElevation());
        elevation.setDuration(duration);
        elevation.setInterpolator(fastOutSlowInInterpolator);
    }

    // Run all animations together
    final AnimatorSet transition = new AnimatorSet();
    transition.playTogether(circularReveal, translate, colorFade, iconFade);
    transition.playTogether(fadeContents);
    if (elevation != null)
        transition.play(elevation);
    if (fromFab) {
        transition.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // Clean up
                view.getOverlay().clear();
            }
        });
    }
    return new AnimUtils.NoPauseAnimator(transition);
}

From source file:com.github.pedrovgs.nox.NoxView.java

/**
 * Draws a NoxItem drawable during the onDraw method given a canvas object and all the
 * information needed to draw the Drawable passed as parameter.
 *///from w  ww  .j  a v  a  2s. c  o m
private void drawNoxItemDrawable(Canvas canvas, int left, int top, Drawable drawable) {
    if (drawable != null) {
        int itemSize = (int) noxConfig.getNoxItemSize();
        drawable.setBounds(left, top, left + itemSize, top + itemSize);
        drawable.draw(canvas);
    }
}

From source file:com.hitomi.circlemenu.transtion.FabTransform.java

@Override
public Animator createAnimator(final ViewGroup sceneRoot, final TransitionValues startValues,
        final TransitionValues endValues) {
    if (startValues == null || endValues == null)
        return null;

    final Rect startBounds = (Rect) startValues.values.get(PROP_BOUNDS);
    final Rect endBounds = (Rect) endValues.values.get(PROP_BOUNDS);

    final boolean fromFab = endBounds.width() > startBounds.width();
    final View view = endValues.view;
    final Rect dialogBounds = fromFab ? endBounds : startBounds;
    final Rect fabBounds = fromFab ? startBounds : endBounds;
    final Interpolator fastOutSlowInInterpolator = AnimUtils
            .getFastOutSlowInInterpolator(sceneRoot.getContext());
    final long duration = getDuration();
    final long halfDuration = duration / 2;
    final long twoThirdsDuration = duration * 2 / 3;

    if (!fromFab) {
        // Force measure / layout the dialog back to it'page_two original bounds
        view.measure(makeMeasureSpec(startBounds.width(), View.MeasureSpec.EXACTLY),
                makeMeasureSpec(startBounds.height(), View.MeasureSpec.EXACTLY));
        view.layout(startBounds.left, startBounds.top, startBounds.right, startBounds.bottom);
    }// w  w w .  ja v  a  2  s .c om

    final int translationX = startBounds.centerX() - endBounds.centerX();
    final int translationY = startBounds.centerY() - endBounds.centerY();
    if (fromFab) {
        view.setTranslationX(translationX);
        view.setTranslationY(translationY);
    }

    // Add a color overlay to fake appearance of the FAB
    final ColorDrawable fabColor = new ColorDrawable(color);
    fabColor.setBounds(0, 0, dialogBounds.width(), dialogBounds.height());
    if (!fromFab)
        fabColor.setAlpha(0);
    view.getOverlay().add(fabColor);

    // Add an icon overlay again to fake the appearance of the FAB
    final Drawable fabIcon = ContextCompat.getDrawable(sceneRoot.getContext(), icon).mutate();
    final int iconLeft = (dialogBounds.width() - fabIcon.getIntrinsicWidth()) / 2;
    final int iconTop = (dialogBounds.height() - fabIcon.getIntrinsicHeight()) / 2;
    fabIcon.setBounds(iconLeft, iconTop, iconLeft + fabIcon.getIntrinsicWidth(),
            iconTop + fabIcon.getIntrinsicHeight());
    if (!fromFab)
        fabIcon.setAlpha(0);
    view.getOverlay().add(fabIcon);

    // Circular clip from/to the FAB size
    final Animator circularReveal;
    if (fromFab) {
        circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2,
                view.getHeight() / 2, startBounds.width() / 2,
                (float) Math.hypot(endBounds.width() / 2, endBounds.height() / 2));
        circularReveal.setInterpolator(AnimUtils.getFastOutLinearInInterpolator(sceneRoot.getContext()));
    } else {
        circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2,
                view.getHeight() / 2, (float) Math.hypot(startBounds.width() / 2, startBounds.height() / 2),
                endBounds.width() / 2);
        circularReveal.setInterpolator(AnimUtils.getLinearOutSlowInInterpolator(sceneRoot.getContext()));

        // Persist the end clip i.e. stay at FAB size after the reveal has run
        circularReveal.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                view.setOutlineProvider(new ViewOutlineProvider() {
                    @Override
                    public void getOutline(View view, Outline outline) {
                        final int left = (view.getWidth() - fabBounds.width()) / 2;
                        final int top = (view.getHeight() - fabBounds.height()) / 2;
                        outline.setOval(left, top, left + fabBounds.width(), top + fabBounds.height());
                        view.setClipToOutline(true);
                    }
                });
            }
        });
    }
    circularReveal.setDuration(duration);

    // Translate to end position along an arc
    final Animator translate = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y,
            fromFab ? getPathMotion().getPath(translationX, translationY, 0, 0)
                    : getPathMotion().getPath(0, 0, -translationX, -translationY));
    translate.setDuration(duration);
    translate.setInterpolator(fastOutSlowInInterpolator);

    // Fade contents of non-FAB view in/out
    List<Animator> fadeContents = null;
    if (view instanceof ViewGroup) {
        final ViewGroup vg = ((ViewGroup) view);
        fadeContents = new ArrayList<>(vg.getChildCount());
        for (int i = vg.getChildCount() - 1; i >= 0; i--) {
            final View child = vg.getChildAt(i);
            final Animator fade = ObjectAnimator.ofFloat(child, View.ALPHA, fromFab ? 1f : 0f);
            if (fromFab) {
                child.setAlpha(0f);
            }
            fade.setDuration(twoThirdsDuration);
            fade.setInterpolator(fastOutSlowInInterpolator);
            fadeContents.add(fade);
        }
    }

    // Fade in/out the fab color & icon overlays
    final Animator colorFade = ObjectAnimator.ofInt(fabColor, "alpha", fromFab ? 0 : 255);
    final Animator iconFade = ObjectAnimator.ofInt(fabIcon, "alpha", fromFab ? 0 : 255);
    if (!fromFab) {
        colorFade.setStartDelay(halfDuration);
        iconFade.setStartDelay(halfDuration);
    }
    colorFade.setDuration(halfDuration);
    iconFade.setDuration(halfDuration);
    colorFade.setInterpolator(fastOutSlowInInterpolator);
    iconFade.setInterpolator(fastOutSlowInInterpolator);

    // Work around issue with elevation shadows. At the end of the return transition the shared
    // element'page_two shadow is drawn twice (by each activity) which is jarring. This workaround
    // still causes the shadow to snap, but it'page_two better than seeing it double drawn.
    Animator elevation = null;
    if (!fromFab) {
        elevation = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, -view.getElevation());
        elevation.setDuration(duration);
        elevation.setInterpolator(fastOutSlowInInterpolator);
    }

    // Run all animations together
    final AnimatorSet transition = new AnimatorSet();
    transition.playTogether(circularReveal, translate, colorFade, iconFade);
    transition.playTogether(fadeContents);
    if (elevation != null)
        transition.play(elevation);
    if (fromFab) {
        transition.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // Clean up
                view.getOverlay().clear();
            }
        });
    }
    return new AnimUtils.NoPauseAnimator(transition);
}