@Override
 public void setImageDrawable(Drawable drawable) {
   if (mIcon != drawable) {
     mIcon = drawable;
     updateBackground();
   }
 }
 public void setShadowColorResource(int colorResId) {
   int shadowColor = getResources().getColor(colorResId);
   if (mShadowColor != shadowColor) {
     mShadowColor = shadowColor;
     updateBackground();
   }
 }
  private void createMenuButton() {
    mMenuButton = new FloatingActionButton(getContext());

    mMenuButton.mShowShadow = mMenuShowShadow;
    if (mMenuShowShadow) {
      mMenuButton.mShadowRadius = Util.dpToPx(getContext(), mMenuShadowRadius);
      mMenuButton.mShadowXOffset = Util.dpToPx(getContext(), mMenuShadowXOffset);
      mMenuButton.mShadowYOffset = Util.dpToPx(getContext(), mMenuShadowYOffset);
    }
    mMenuButton.setColors(mMenuColorNormal, mMenuColorPressed, mMenuColorRipple);
    mMenuButton.mShadowColor = mMenuShadowColor;
    mMenuButton.mFabSize = mMenuFabSize;
    mMenuButton.updateBackground();

    mMenuButton.setOnClickListener(
        new OnClickListener() {
          @Override
          public void onClick(View v) {
            toggle(mIsAnimated);
          }
        });

    mImageToggle = new ImageView(getContext());
    mImageToggle.setImageDrawable(mIcon);

    addView(mMenuButton, super.generateDefaultLayoutParams());
    addView(mImageToggle);

    createDefaultIconAnimation();
  }
 @Override
 public void setImageResource(int resId) {
   Drawable drawable = getResources().getDrawable(resId);
   if (mIcon != drawable) {
     mIcon = drawable;
     updateBackground();
   }
 }
 /**
  * Sets the shadow radius of the <b>FloatingActionButton</b> and invalidates its layout.
  *
  * @param dimenResId the resource identifier of the dimension
  */
 public void setShadowRadius(int dimenResId) {
   int shadowRadius = getResources().getDimensionPixelSize(dimenResId);
   if (mShadowRadius != shadowRadius) {
     mShadowRadius = shadowRadius;
     requestLayout();
     updateBackground();
   }
 }
 /**
  * Sets the shadow x offset of the <b>FloatingActionButton</b> and invalidates its layout.
  *
  * @param dimenResId the resource identifier of the dimension
  */
 public void setShadowXOffset(int dimenResId) {
   int shadowXOffset = getResources().getDimensionPixelSize(dimenResId);
   if (mShadowXOffset != shadowXOffset) {
     mShadowXOffset = shadowXOffset;
     requestLayout();
     updateBackground();
   }
 }
  /**
   * Sets the size of the <b>FloatingActionButton</b> and invalidates its layout.
   *
   * @param size size of the <b>FloatingActionButton</b>. Accepted values: SIZE_NORMAL, SIZE_MINI.
   */
  public void setButtonSize(int size) {
    if (size != SIZE_NORMAL && size != SIZE_MINI) {
      throw new IllegalArgumentException("Use @FabSize constants only!");
    }

    if (mFabSize != size) {
      mFabSize = size;
      updateBackground();
    }
  }
 @Override
 public void setElevation(float elevation) {
   if (Util.hasLollipop() && elevation > 0) {
     super.setElevation(elevation);
     if (!isInEditMode()) {
       mUsingElevation = true;
       mShowShadow = false;
     }
     updateBackground();
   }
 }
  /**
   * Change the indeterminate mode for the progress bar. In indeterminate mode, the progress is
   * ignored and the progress bar shows an infinite animation instead.
   *
   * @param indeterminate true to enable the indeterminate mode
   */
  public synchronized void setIndeterminate(boolean indeterminate) {
    if (!indeterminate) {
      mCurrentProgress = 0.0f;
    }

    mProgressBarEnabled = indeterminate;
    mShouldUpdateButtonPosition = true;
    mProgressIndeterminate = indeterminate;
    mLastTimeAnimated = SystemClock.uptimeMillis();
    setupProgressBounds();
    saveButtonOriginalPosition();
    updateBackground();
  }
  /**
   * Sets the shadow color and radius to mimic the native elevation.
   *
   * <p><b>API 21+</b>: Sets the native elevation of this view, in pixels. Updates margins to make
   * the view hold its position in layout across different platform versions.
   */
  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  public void setElevationCompat(float elevation) {
    mShadowColor = 0x26000000;
    mShadowRadius = Math.round(elevation / 2);
    mShadowXOffset = 0;
    mShadowYOffset = Math.round(mFabSize == SIZE_NORMAL ? elevation : elevation / 2);

    if (Util.hasLollipop()) {
      super.setElevation(elevation);
      mUsingElevationCompat = true;
      mShowShadow = false;
      updateBackground();

      ViewGroup.LayoutParams layoutParams = getLayoutParams();
      if (layoutParams != null) {
        setLayoutParams(layoutParams);
      }
    } else {
      mShowShadow = true;
      updateBackground();
    }
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    saveButtonOriginalPosition();

    if (mShouldProgressIndeterminate) {
      setIndeterminate(true);
      mShouldProgressIndeterminate = false;
    } else if (mShouldSetProgress) {
      setProgress(mProgress, mAnimateProgress);
      mShouldSetProgress = false;
    } else if (mShouldUpdateButtonPosition) {
      updateButtonPosition();
      mShouldUpdateButtonPosition = false;
    }
    super.onSizeChanged(w, h, oldw, oldh);

    setupProgressBounds();
    setupProgressBarPaints();
    updateBackground();
  }
  public synchronized void setProgress(int progress, boolean animate) {
    if (mProgressIndeterminate) return;

    mProgress = progress;
    mAnimateProgress = animate;

    if (!mButtonPositionSaved) {
      mShouldSetProgress = true;
      return;
    }

    mProgressBarEnabled = true;
    mShouldUpdateButtonPosition = true;
    setupProgressBounds();
    saveButtonOriginalPosition();
    updateBackground();

    if (progress < 0) {
      progress = 0;
    } else if (progress > mProgressMax) {
      progress = mProgressMax;
    }

    if (progress == mTargetProgress) {
      return;
    }

    mTargetProgress = mProgressMax > 0 ? (progress / (float) mProgressMax) * 360 : 0;
    mLastTimeAnimated = SystemClock.uptimeMillis();

    if (!animate) {
      mCurrentProgress = mTargetProgress;
    }

    invalidate();
  }
 /**
  * Sets the shadow x offset of the <b>FloatingActionButton</b> and invalidates its layout.
  *
  * <p>Must be specified in density-independent (dp) pixels, which are then converted into actual
  * pixels (px).
  *
  * @param shadowXOffsetDp shadow radius specified in density-independent (dp) pixels
  */
 public void setShadowXOffset(float shadowXOffsetDp) {
   mShadowXOffset = Util.dpToPx(getContext(), shadowXOffsetDp);
   requestLayout();
   updateBackground();
 }
 /**
  * Sets the shadow radius of the <b>FloatingActionButton</b> and invalidates its layout.
  *
  * <p>Must be specified in density-independent (dp) pixels, which are then converted into actual
  * pixels (px).
  *
  * @param shadowRadiusDp shadow radius specified in density-independent (dp) pixels
  */
 public void setShadowRadius(float shadowRadiusDp) {
   mShadowRadius = Util.dpToPx(getContext(), shadowRadiusDp);
   requestLayout();
   updateBackground();
 }
 public void setShowShadow(boolean show) {
   if (mShowShadow != show) {
     mShowShadow = show;
     updateBackground();
   }
 }
 public void setColorDisabled(int color) {
   if (color != mColorDisabled) {
     mColorDisabled = color;
     updateBackground();
   }
 }
 public void setColorRipple(int color) {
   if (color != mColorRipple) {
     mColorRipple = color;
     updateBackground();
   }
 }
 public void setColorNormal(int color) {
   if (mColorNormal != color) {
     mColorNormal = color;
     updateBackground();
   }
 }
 public void setShadowColor(int color) {
   if (mShadowColor != color) {
     mShadowColor = color;
     updateBackground();
   }
 }
 public synchronized void hideProgress() {
   mProgressBarEnabled = false;
   mShouldUpdateButtonPosition = true;
   updateBackground();
 }