content: 
  /*
   * Copyright 2014 Google Inc. All rights reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.agenthun.readingroutine.views;
  
  import android.animation.ObjectAnimator;
  import android.content.Context;
  import android.content.res.TypedArray;
  import android.graphics.Canvas;
  import android.graphics.drawable.Drawable;
  import android.graphics.drawable.NinePatchDrawable;
  import android.support.v4.view.ViewCompat;
  import android.util.AttributeSet;
  import android.util.Property;
  import android.widget.FrameLayout;
  
  import com.agenthun.readingroutine.R;
  
  public class DrawShadowFrameLayout extends FrameLayout {
      private Drawable mShadowDrawable;
      private NinePatchDrawable mShadowNinePatchDrawable;
      private int mShadowTopOffset;
      private boolean mShadowVisible;
      private int mWidth, mHeight;
      private ObjectAnimator mAnimator;
      private float mAlpha = 1f;
  
      public DrawShadowFrameLayout(Context context) {
          this(context, null, 0);
      }
  
      public DrawShadowFrameLayout(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      public DrawShadowFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
          super(context, attrs, defStyleAttr);
          final TypedArray a = context.obtainStyledAttributes(attrs,
                  R.styleable.DrawShadowFrameLayout, 0, 0);
  
          mShadowDrawable = a.getDrawable(R.styleable.DrawShadowFrameLayout_shadowDrawable);
          if (mShadowDrawable != null) {
              mShadowDrawable.setCallback(this);
              if (mShadowDrawable instanceof NinePatchDrawable) {
                  mShadowNinePatchDrawable = (NinePatchDrawable) mShadowDrawable;
              }
          }
  
          mShadowVisible = a.getBoolean(R.styleable.DrawShadowFrameLayout_shadowVisible, true);
          setWillNotDraw(!mShadowVisible || mShadowDrawable == null);
  
          a.recycle();
      }
  
      @Override
      protected void onSizeChanged(int w, int h, int oldw, int oldh) {
          super.onSizeChanged(w, h, oldw, oldh);
          mWidth = w;
          mHeight = h;
          updateShadowBounds();
      }
  
      private void updateShadowBounds() {
          if (mShadowDrawable != null) {
              mShadowDrawable.setBounds(0, mShadowTopOffset, mWidth, mHeight);
          }
      }
  
      @Override
      public void draw(Canvas canvas) {
          super.draw(canvas);
          if (mShadowDrawable != null && mShadowVisible) {
              if (mShadowNinePatchDrawable != null) {
                  mShadowNinePatchDrawable.getPaint().setAlpha((int) (255 * mAlpha));
              }
              mShadowDrawable.draw(canvas);
          }
      }
  
      public void setShadowTopOffset(int shadowTopOffset) {
          this.mShadowTopOffset = shadowTopOffset;
          updateShadowBounds();
          ViewCompat.postInvalidateOnAnimation(this);
      }
  
      public void setShadowVisible(boolean shadowVisible, boolean animate) {
          this.mShadowVisible = shadowVisible;
          if (mAnimator != null) {
              mAnimator.cancel();
              mAnimator = null;
          }
  
          if (animate && mShadowDrawable != null) {
              mAnimator = ObjectAnimator.ofFloat(this, SHADOW_ALPHA,
                      shadowVisible ? 0f : 1f,
                      shadowVisible ? 1f : 0f);
              mAnimator.setDuration(1000);
              mAnimator.start();
          }
  
          ViewCompat.postInvalidateOnAnimation(this);
          setWillNotDraw(!mShadowVisible || mShadowDrawable == null);
      }
  
      private static Property<DrawShadowFrameLayout, Float> SHADOW_ALPHA
              = new Property<DrawShadowFrameLayout, Float>(Float.class, "shadowAlpha") {
          @Override
          public Float get(DrawShadowFrameLayout dsfl) {
              return dsfl.mAlpha;
          }
  
          @Override
          public void set(DrawShadowFrameLayout dsfl, Float value) {
              dsfl.mAlpha = value;
              ViewCompat.postInvalidateOnAnimation(dsfl);
          }
      };
  }
  