Example usage for android.view.animation DecelerateInterpolator DecelerateInterpolator

List of usage examples for android.view.animation DecelerateInterpolator DecelerateInterpolator

Introduction

In this page you can find the example usage for android.view.animation DecelerateInterpolator DecelerateInterpolator.

Prototype

public DecelerateInterpolator(float factor) 

Source Link

Document

Constructor

Usage

From source file:com.marlonjones.voidlauncher.CellLayout.java

public CellLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    // A ViewGroup usually does not draw, but CellLayout needs to draw a rectangle to show
    // the user where a dragged item will land when dropped.
    setWillNotDraw(false);//from   w  w w  .j  a v  a 2  s.  c o m
    setClipToPadding(false);
    mLauncher = Launcher.getLauncher(context);

    DeviceProfile grid = mLauncher.getDeviceProfile();

    mCellWidth = mCellHeight = -1;
    mFixedCellWidth = mFixedCellHeight = -1;
    mWidthGap = mOriginalWidthGap = 0;
    mHeightGap = mOriginalHeightGap = 0;
    mMaxGap = Integer.MAX_VALUE;

    mCountX = grid.inv.numColumns;
    mCountY = grid.inv.numRows;
    mOccupied = new GridOccupancy(mCountX, mCountY);
    mTmpOccupied = new GridOccupancy(mCountX, mCountY);

    mPreviousReorderDirection[0] = INVALID_DIRECTION;
    mPreviousReorderDirection[1] = INVALID_DIRECTION;

    mFolderLeaveBehind.delegateCellX = -1;
    mFolderLeaveBehind.delegateCellY = -1;

    setAlwaysDrawnWithCacheEnabled(false);
    final Resources res = getResources();
    mHotseatScale = (float) grid.hotseatIconSizePx / grid.iconSizePx;

    mBackground = (TransitionDrawable) res.getDrawable(
            FeatureFlags.LAUNCHER3_LEGACY_WORKSPACE_DND ? R.drawable.bg_screenpanel : R.drawable.bg_celllayout);
    mBackground.setCallback(this);
    mBackground.setAlpha((int) (mBackgroundAlpha * 255));

    mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * grid.iconSizePx);

    // Initialize the data structures used for the drag visualization.
    mEaseOutInterpolator = new DecelerateInterpolator(2.5f); // Quint ease out
    mDragCell[0] = mDragCell[1] = -1;
    for (int i = 0; i < mDragOutlines.length; i++) {
        mDragOutlines[i] = new Rect(-1, -1, -1, -1);
    }
    mDragOutlinePaint.setColor(getResources().getColor(R.color.outline_color));

    // When dragging things around the home screens, we show a green outline of
    // where the item will land. The outlines gradually fade out, leaving a trail
    // behind the drag path.
    // Set up all the animations that are used to implement this fading.
    final int duration = res.getInteger(R.integer.config_dragOutlineFadeTime);
    final float fromAlphaValue = 0;
    final float toAlphaValue = (float) res.getInteger(R.integer.config_dragOutlineMaxAlpha);

    Arrays.fill(mDragOutlineAlphas, fromAlphaValue);

    for (int i = 0; i < mDragOutlineAnims.length; i++) {
        final InterruptibleInOutAnimator anim = new InterruptibleInOutAnimator(this, duration, fromAlphaValue,
                toAlphaValue);
        anim.getAnimator().setInterpolator(mEaseOutInterpolator);
        final int thisIndex = i;
        anim.getAnimator().addUpdateListener(new AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                final Bitmap outline = (Bitmap) anim.getTag();

                // If an animation is started and then stopped very quickly, we can still
                // get spurious updates we've cleared the tag. Guard against this.
                if (outline == null) {
                    if (LOGD) {
                        Object val = animation.getAnimatedValue();
                        Log.d(TAG, "anim " + thisIndex + " update: " + val + ", isStopped " + anim.isStopped());
                    }
                    // Try to prevent it from continuing to run
                    animation.cancel();
                } else {
                    mDragOutlineAlphas[thisIndex] = (Float) animation.getAnimatedValue();
                    CellLayout.this.invalidate(mDragOutlines[thisIndex]);
                }
            }
        });
        // The animation holds a reference to the drag outline bitmap as long is it's
        // running. This way the bitmap can be GCed when the animations are complete.
        anim.getAnimator().addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if ((Float) ((ValueAnimator) animation).getAnimatedValue() == 0f) {
                    anim.setTag(null);
                }
            }
        });
        mDragOutlineAnims[i] = anim;
    }

    mShortcutsAndWidgets = new ShortcutAndWidgetContainer(context);
    mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap, mCountX, mCountY);

    mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);

    mTouchFeedbackView = new ClickShadowView(context);
    addView(mTouchFeedbackView);
    addView(mShortcutsAndWidgets);
}

From source file:com.yisa.pray.views.swipe.SwipyRefreshLayout.java

/**
 * Constructor that is called when inflating SwipeRefreshLayout from XML.
 * /*from ww w.  j a  v a 2  s  .  c  o  m*/
 * @param context
 * @param attrs
 */
public SwipyRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    mMediumAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

    setWillNotDraw(false);
    mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);

    final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
    setEnabled(a.getBoolean(0, true));
    a.recycle();

    final TypedArray a2 = context.obtainStyledAttributes(attrs, R.styleable.SwipyRefreshLayout);
    SwipyRefreshLayoutDirection direction = SwipyRefreshLayoutDirection
            .getFromInt(a2.getInt(R.styleable.SwipyRefreshLayout_direction, 0));
    if (direction != SwipyRefreshLayoutDirection.BOTH) {
        mDirection = direction;
        mBothDirection = false;
    } else {
        mDirection = SwipyRefreshLayoutDirection.TOP;
        mBothDirection = true;
    }
    a2.recycle();

    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
    mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);

    createProgressView();
    ViewCompat.setChildrenDrawingOrderEnabled(this, true);
    // the absolute offset has to take into account that the circle starts
    // at an offset
    mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
    mTotalDragDistance = mSpinnerFinalOffset;
}

From source file:com.learn.mobile.customview.DSwipeRefreshLayout.java

/**
 * Constructor that is called when inflating SwipeRefreshLayout from XML.
 *
 * @param context/*from   w  w w  . j  a v a 2s  . com*/
 * @param attrs
 */
public DSwipeRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    mMediumAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

    setWillNotDraw(false);
    mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);

    final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
    setEnabled(a.getBoolean(0, true));
    a.recycle();

    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
    mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);

    createProgressView();
    ViewCompat.setChildrenDrawingOrderEnabled(this, true);
    // the absolute offset has to take into account that the circle starts at an offset
    mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
    mTotalDragDistance = mSpinnerFinalOffset;
}

From source file:com.jtech.view.RefreshLayout.java

/**
 * Constructor that is called when inflating SwipeRefreshLayout from XML.
 *
 * @param context//from w  ww  .j  av a  2s  . c o m
 * @param attrs
 */
public RefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    mMediumAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

    setWillNotDraw(false);
    mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);

    final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
    setEnabled(a.getBoolean(0, true));
    a.recycle();

    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
    mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);

    createProgressView();
    ViewCompat.setChildrenDrawingOrderEnabled(this, true);
    // the absolute offset has to take into account that the circle starts
    // at an offset
    mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
    mTotalDragDistance = mSpinnerFinalOffset;
    mNestedScrollingParentHelper = new NestedScrollingParentHelper(this);

    mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}

From source file:com.example.adminstrator.pullrefresh.SwipeRefreshLayout.java

/**
 * Constructor that is called when inflating SwipeRefreshLayout from XML.
 * @param context//from   w w  w  .  j a v a 2  s .  c om
 * @param attrs
 */
public SwipeRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    mMediumAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

    setWillNotDraw(false);
    mProgressBar = new RefreshProgressBar(getContext(), 0);
    mProgressBar.setTipText("", "?", "");
    mProgressBarBottom = new RefreshProgressBar(getContext(), 1);
    mProgressBarBottom.setTipText("", "?", "");
    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    mProgressBarHeight = (int) (metrics.density * PROGRESS_BAR_HEIGHT);
    mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
    mAccelerateInterpolator = new AccelerateInterpolator(ACCELERATE_INTERPOLATION_FACTOR);

    final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
    setEnabled(a.getBoolean(0, true));
    a.recycle();
    this.addView(mProgressBar, 0);
    this.addView(mProgressBarBottom, 0);
}

From source file:com.lastsoft.plog.GamesFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View rootView = inflater.inflate(R.layout.fragment_games, container, false);

    rootView.setTag(TAG);/*from  www  . j  av  a2 s.  com*/

    // BEGIN_INCLUDE(initializeRecyclerView)
    mCoordinatorLayout = (CoordinatorLayout) rootView.findViewById(R.id.coordinatorLayout);
    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
    mRecyclerView.setBackgroundColor(getResources().getColor(R.color.cardview_initial_background));
    pullToRefreshView = (SwipeRefreshLayout) rootView.findViewById(R.id.pull_to_refresh_listview);
    pullToRefreshView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {

        @Override
        public void onRefresh() {
            initDataset(true);
        }
    });

    RecyclerFastScroller fastScroller = (RecyclerFastScroller) rootView.findViewById(R.id.fastscroller);
    fastScroller.attachRecyclerView(mRecyclerView);
    //fastScroller = (VerticalRecyclerViewFastScroller) rootView.findViewById(R.id.fastscroller);

    // Connect the recycler to the scroller (to let the scroller scroll the list)
    //fastScroller.setRecyclerView(mRecyclerView, pullToRefreshView);

    // Connect the scroller to the recycler (to let the recycler scroll the scroller's handle)
    //mRecyclerView.setOnScrollListener(fastScroller.getOnScrollListener());

    addPlayer = (FloatingActionButton) rootView.findViewById(R.id.add_game);
    if (fromDrawer && playListType != 2) {
        //fastScroller.setRecyclerView(mRecyclerView, pullToRefreshView);
        mRecyclerView.setOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                boolean enable = false;
                boolean firstItemVisiblePull = recyclerView.getChildPosition(recyclerView.getChildAt(0)) == 0;
                boolean topOfFirstItemVisiblePull = recyclerView.getChildAt(0).getTop() == recyclerView
                        .getChildAt(0).getTop();
                ;
                enable = firstItemVisiblePull && topOfFirstItemVisiblePull;
                pullToRefreshView.setEnabled(enable);
            }
        });
        addPlayer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int viewXY[] = new int[2];
                v.getLocationOnScreen(viewXY);
                if (mListener != null) {
                    mListener.onFragmentInteraction("add_game", viewXY[0], viewXY[1]);
                }
            }
        });
    } else {
        if (!fromDrawer) {
            RelativeLayout gamesLayout = (RelativeLayout) rootView.findViewById(R.id.gamesLayout);
            final SwipeDismissBehavior<LinearLayout> behavior = new SwipeDismissBehavior();
            behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END);
            behavior.setStartAlphaSwipeDistance(1.0f);
            behavior.setSensitivity(0.15f);
            behavior.setListener(new SwipeDismissBehavior.OnDismissListener() {
                @Override
                public void onDismiss(final View view) {
                    GamesFragment myFragC1 = (GamesFragment) getFragmentManager().findFragmentByTag("games");
                    FragmentTransaction transaction = getFragmentManager().beginTransaction();
                    transaction.remove(myFragC1);
                    transaction.commitAllowingStateLoss();
                    getFragmentManager().executePendingTransactions();
                    mActivity.onBackPressed();
                }

                @Override
                public void onDragStateChanged(int i) {

                }
            });

            CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) gamesLayout
                    .getLayoutParams();
            params.setBehavior(behavior);

        }
        //fastScroller.setRecyclerView(mRecyclerView, null);
        pullToRefreshView.setEnabled(false);
        addPlayer.setVisibility(View.GONE);
    }

    mProgress = (LinearLayout) rootView.findViewById(R.id.progressContainer);
    mText = (TextView) rootView.findViewById(R.id.LoadingText);

    // LinearLayoutManager is used here, this will layout the elements in a similar fashion
    // to the way ListView would layout elements. The RecyclerView.LayoutManager defines how
    // elements are laid out.
    mLayoutManager = new LinearLayoutManager(mActivity);

    mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;

    if (savedInstanceState != null) {
        // Restore saved layout manager type.
        mCurrentLayoutManagerType = (LayoutManagerType) savedInstanceState.getSerializable(KEY_LAYOUT_MANAGER);
    }
    setRecyclerViewLayoutManager(mCurrentLayoutManagerType);

    //mAdapter = new CustomAdapter(mDataset, mDataset_Thumb);
    mAdapter = new GameAdapter(this, mActivity, mSearchQuery, fromDrawer, playListType, sortType, fragmentName,
            currentYear);
    // Set CustomAdapter as the adapter for RecyclerView.
    mRecyclerView.setAdapter(mAdapter);

    if (mSearch != null) {
        mSearch.setHint(
                getString(R.string.filter) + mAdapter.getItemCount() + getString(R.string.filter_games));
    }

    fabMargin = getResources().getDimensionPixelSize(R.dimen.fab_margin);
    mRecyclerView.addOnScrollListener(new MyRecyclerScroll() {
        @Override
        public void show() {
            addPlayer.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
        }

        @Override
        public void hide() {
            addPlayer.animate().translationY(addPlayer.getHeight() + fabMargin)
                    .setInterpolator(new AccelerateInterpolator(2)).start();
        }
    });

    if (mSearch != null) {
        mSearch.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
                // When user changed the Text
                mSearchQuery = cs.toString();
                //initDataset();
                mAdapter = new GameAdapter(GamesFragment.this, mActivity, mSearchQuery, fromDrawer,
                        playListType, sortType, fragmentName, currentYear);
                // Set CustomAdapter as the adapter for RecyclerView.
                mRecyclerView.setAdapter(mAdapter);

                if (mSearch != null) {
                    mSearch.setHint(getString(R.string.filter) + mAdapter.getItemCount()
                            + getString(R.string.filter_games));
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }

        });

        mCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!mSearch.getText().toString().equals("")) {
                    mSearchQuery = "";
                    mSearch.setText(mSearchQuery);
                    //mActivity.onBackPressed();
                }

                //fastScroller.scrollHider();

                InputMethodManager inputManager = (InputMethodManager) mActivity
                        .getSystemService(Context.INPUT_METHOD_SERVICE);

                inputManager.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(),
                        InputMethodManager.HIDE_NOT_ALWAYS);
                mSearch.clearFocus();
                mRecyclerView.requestFocus();

                initDataset(false);

                if (mSearch != null) {
                    mSearch.setHint(getString(R.string.filter) + mAdapter.getItemCount()
                            + getString(R.string.filter_games));
                }
            }
        });
    }

    Calendar calendar = Calendar.getInstance();
    int year = calendar.get(Calendar.YEAR);
    if (Game.findBaseGames("", sortType, year).size() == 0) {
        initDataset(false);
    } else {
        mText.setVisibility(View.GONE);
        mProgress.setVisibility(View.GONE);
        mRecyclerView.setVisibility(View.VISIBLE);
    }

    // END_INCLUDE(initializeRecyclerView)
    return rootView;
}

From source file:com.idrv.coach.ui.widget.SwipeRefresh.java

/**
 * Constructor that is called when inflating SwipeRefreshLayout from XML.
 *
 * @param context//  w ww . ja va  2 s.c o  m
 */
public SwipeRefresh(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    mMediumAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

    setWillNotDraw(false);
    mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);

    final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
    setEnabled(a.getBoolean(0, true));
    a.recycle();

    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
    mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);

    createProgressView();
    ViewCompat.setChildrenDrawingOrderEnabled(this, true);
    // the absolute offset has to take into account that the circle starts at an offset
    mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
    mTotalDragDistance = mSpinnerFinalOffset;
}

From source file:com.android.support.SwipeRefreshLayout.java

/**
 * Constructor that is called when inflating SwipeRefreshLayout from XML.
 *
 * @param context/*from  w  w  w  .ja v a  2  s.co  m*/
 * @param attrs
 */
public SwipeRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    mMediumAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

    setWillNotDraw(false);
    mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);

    final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
    setEnabled(a.getBoolean(0, true));
    a.recycle();

    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
    mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);

    createProgressView();
    ViewCompat.setChildrenDrawingOrderEnabled(this, true);
    // the absolute offset has to take into account that the circle starts at an offset
    mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
    mTotalDragDistance = mSpinnerFinalOffset;
    mNestedScrollingParentHelper = new NestedScrollingParentHelper(this);

    mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}

From source file:com.bcgtgjyb.huanwen.meizi.view.widget.MySwipeRefreshLayout.java

/**
 * Constructor that is called when inflating SwipeRefreshLayout from XML.
 *
 * @param context//from   ww w . ja v a 2 s . co  m
 * @param attrs
 */
public MySwipeRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    mMediumAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

    setWillNotDraw(false);
    mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);

    final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
    setEnabled(a.getBoolean(0, true));
    a.recycle();

    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
    mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);

    createProgressView();
    ViewCompat.setChildrenDrawingOrderEnabled(this, true);
    // the absolute offset has to take into account that the circle starts at an offset
    mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
    mTotalDragDistance = mSpinnerFinalOffset;
    mNestedScrollingParentHelper = new NestedScrollingParentHelper(this);

    mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}

From source file:cn.edu.bit.bookstore.bookstore_android.widget.PullToRefreshLayout.java

/**
 * Constructor that is called when inflating PullToRefreshLayout from XML.
 *
 * @param context//from  w ww . ja va  2 s  . co m
 * @param attrs
 */
public PullToRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    mMediumAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

    setWillNotDraw(false);
    mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);

    final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
    setEnabled(a.getBoolean(0, true));
    a.recycle();

    final DisplayMetrics metrics = getResources().getDisplayMetrics();
    mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);
    mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);

    createProgressView();
    ViewCompat.setChildrenDrawingOrderEnabled(this, true);
    // the absolute offset has to take into account that the circle starts at an offset
    mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
    mTotalDragDistance = mSpinnerFinalOffset;
    mNestedScrollingParentHelper = new NestedScrollingParentHelper(this);

    mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);
    setNestedScrollingEnabled(true);
}