gt:         switch (specMode) {
context: /**
   *  * Copyright 2016 andy
   *
   * 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.thinkman.thinkutils.view;
  
  import android.animation.ValueAnimator;
  import android.annotation.TargetApi;
  import android.content.Context;
  import android.content.res.TypedArray;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.graphics.Paint;
  import android.graphics.Path;
  import android.graphics.Point;
  import android.os.Build;
  import android.os.Bundle;
  import android.os.Parcelable;
  import android.util.AttributeSet;
  import android.view.View;
  import android.view.animation.LinearInterpolator;
  import android.widget.Checkable;
  
  import com.thinkman.thinkutils.R;
  import com.thinkman.thinkutils.commonutils.DisplayUtil;
  
  /**
   * Author : andy
   * Date   : 16/1/21 11:28
   * Email  : andyxialm@gmail.com
   * Github : github.com/andyxialm
   * Description : A custom CheckBox with animation for Android
   */
  
  public class SmoothCheckBox extends View implements Checkable {
      private static final String KEY_INSTANCE_STATE = "InstanceState";
  
      private static final int COLOR_TICK      = Color.WHITE;
      private static final int COLOR_UNCHECKED = Color.WHITE;
      private static final int COLOR_CHECKED   = Color.parseColor("#FB4846");
      private static final int COLOR_FLOOR_UNCHECKED = Color.parseColor("#DFDFDF");
  
      private static final int DEF_DRAW_SIZE     = 25;
      private static final int DEF_ANIM_DURATION = 300;
  
      private Paint mPaint, mTickPaint, mFloorPaint;
      private Point[] mTickPoints;
      private Point mCenterPoint;
      private Path mTickPath;
  
      private float mLeftLineDistance, mRightLineDistance, mDrewDistance;
      private float mScaleVal = 1.0f, mFloorScale = 1.0f;
      private int mWidth, mAnimDuration, mStrokeWidth;
      private int mCheckedColor, mUnCheckedColor, mFloorColor, mFloorUnCheckedColor;
  
      private boolean mChecked;
      private boolean mTickDrawing;
      private OnCheckedChangeListener mListener;
  
      public SmoothCheckBox(Context context) {
          this(context, null);
      }
  
      public SmoothCheckBox(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      public SmoothCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
          super(context, attrs, defStyleAttr);
          init(attrs);
      }
  
      @TargetApi(Build.VERSION_CODES.LOLLIPOP)
      public SmoothCheckBox(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
          super(context, attrs, defStyleAttr, defStyleRes);
          init(attrs);
      }
  
      private void init(AttributeSet attrs) {
  
          TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.SmoothCheckBox);
          int tickColor = ta.getColor(R.styleable.SmoothCheckBox_scb_color_tick, COLOR_TICK);
          mAnimDuration = ta.getInt(R.styleable.SmoothCheckBox_scb_duration, DEF_ANIM_DURATION);
          mFloorColor = ta.getColor(R.styleable.SmoothCheckBox_scb_color_unchecked_stroke, COLOR_FLOOR_UNCHECKED);
          mCheckedColor = ta.getColor(R.styleable.SmoothCheckBox_scb_color_checked, COLOR_CHECKED);
          mUnCheckedColor = ta.getColor(R.styleable.SmoothCheckBox_scb_color_unchecked, COLOR_UNCHECKED);
          mStrokeWidth = ta.getDimensionPixelSize(R.styleable.SmoothCheckBox_scb_stroke_width, DisplayUtil.dip2px(getContext(), 0));
          ta.recycle();
  
          mFloorUnCheckedColor = mFloorColor;
          mTickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
          mTickPaint.setStyle(Paint.Style.STROKE);
          mTickPaint.setStrokeCap(Paint.Cap.ROUND);
          mTickPaint.setColor(tickColor);
  
          mFloorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
          mFloorPaint.setStyle(Paint.Style.FILL);
          mFloorPaint.setColor(mFloorColor);
  
          mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
          mPaint.setStyle(Paint.Style.FILL);
          mPaint.setColor(mCheckedColor);
  
          mTickPath = new Path();
          mCenterPoint = new Point();
          mTickPoints = new Point[3];
          mTickPoints[0] = new Point();
          mTickPoints[1] = new Point();
          mTickPoints[2] = new Point();
  
          if (isFocusable()) {
              setOnClickListener(new OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      toggle();
                      mTickDrawing = false;
                      mDrewDistance = 0;
                      if (isChecked()) {
                          startCheckedAnimation();
                      } else {
                          startUnCheckedAnimation();
                      }
                  }
              });
          }
      }
  
      @Override
      protected Parcelable onSaveInstanceState() {
          Bundle bundle = new Bundle();
          bundle.putParcelable(KEY_INSTANCE_STATE, super.onSaveInstanceState());
          bundle.putBoolean(KEY_INSTANCE_STATE, isChecked());
          return bundle;
      }
  
      @Override
      protected void onRestoreInstanceState(Parcelable state) {
          if (state instanceof Bundle) {
              Bundle bundle = (Bundle) state;
              boolean isChecked = bundle.getBoolean(KEY_INSTANCE_STATE);
              setChecked(isChecked);
              super.onRestoreInstanceState(bundle.getParcelable(KEY_INSTANCE_STATE));
              return;
          }
          super.onRestoreInstanceState(state);
      }
  
      @Override
      public boolean isChecked() {
          return mChecked;
      }
  
      @Override
      public void toggle() {
          this.setChecked(!isChecked());
      }
  
      public void showChecked(boolean checked) {
          mChecked = checked;
          reset();
          invalidate();
      }
  
      public void showChecked(boolean checked, boolean animate) {
          if (animate) {
              mTickDrawing = false;
              mChecked = checked;
              mDrewDistance = 0f;
              if (checked) {
                  startCheckedAnimation();
              } else {
                  startUnCheckedAnimation();
              }
          } else {
              this.showChecked(checked);
          }
      }
  
      @Override
      public void setChecked(boolean checked) {
          mChecked = checked;
          reset();
          invalidate();
          if (mListener != null) {
              mListener.onCheckedChanged(SmoothCheckBox.this, mChecked);
          }
      }
  
      /**
       * checked with animation
       * @param checked checked
       * @param animate change with animation
       */
      public void setChecked(boolean checked, boolean animate) {
          if (animate) {
              mTickDrawing = false;
              mChecked = checked;
              mDrewDistance = 0f;
              if (checked) {
                  startCheckedAnimation();
              } else {
                  startUnCheckedAnimation();
              }
              if (mListener != null) {
                  mListener.onCheckedChanged(SmoothCheckBox.this, mChecked);
              }
  
          } else {
              this.setChecked(checked);
          }
      }
  
      private void reset() {
          mTickDrawing = true;
          mFloorScale = 1.0f;
          mScaleVal = isChecked() ? 0f : 1.0f;
          mFloorColor = isChecked() ? mCheckedColor : mFloorUnCheckedColor;
          mDrewDistance = isChecked() ? (mLeftLineDistance + mRightLineDistance) : 0;
      }
  
      private int measureSize(int measureSpec) {
          int defSize = DisplayUtil.dip2px(getContext(), DEF_DRAW_SIZE);
          int specSize = MeasureSpec.getSize(measureSpec);
          int specMode = MeasureSpec.getMode(measureSpec);
  
          int result = 0;
  