public void setProgressRotation(float rotation) {
   if (mProgressDrawable.isRunning()) {
     stop();
   }
   mProgressDrawable.showArrow(true);
   mProgressDrawable.showArrowOnFirstStart(true);
   mProgressDrawable.setProgressRotation(rotation);
 }
  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    final float density = getContext().getResources().getDisplayMetrics().density;
    mDiameter = Math.min(getMeasuredWidth(), getMeasuredHeight());
    if (mDiameter <= 0) {
      mDiameter = (int) density * DEFAULT_CIRCLE_DIAMETER;
    }
    if (getBackground() == null && mCircleBackgroundEnabled) {
      final int shadowYOffset = (int) (density * Y_OFFSET);
      final int shadowXOffset = (int) (density * X_OFFSET);
      mShadowRadius = (int) (density * SHADOW_RADIUS);

      if (elevationSupported()) {
        mBgCircle = new ShapeDrawable(new OvalShape());
        ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
      } else {
        OvalShape oval = new OvalShadow(mShadowRadius, mDiameter - mShadowRadius * 2);
        mBgCircle = new ShapeDrawable(oval);
        ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, mBgCircle.getPaint());
        mBgCircle
            .getPaint()
            .setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset, KEY_SHADOW_COLOR);
        final int padding = (int) mShadowRadius;
        // set padding so the inner image sits correctly within the shadow.
        setPadding(padding, padding, padding, padding);
      }
      mBgCircle.getPaint().setColor(mBackGroundColor);
      setBackgroundDrawable(mBgCircle);
    }
    mProgressDrawable.setBackgroundColor(mBackGroundColor);
    mProgressDrawable.setColorSchemeColors(mColors);
    mProgressDrawable.setSizeParameters(
        mDiameter,
        mDiameter,
        mInnerRadius <= 0 ? (mDiameter - mProgressStokeWidth * 2) / 4 : mInnerRadius,
        mProgressStokeWidth,
        mArrowWidth < 0 ? mProgressStokeWidth * 4 : mArrowWidth,
        mArrowHeight < 0 ? mProgressStokeWidth * 2 : mArrowHeight);
    if (isShowArrow()) {
      mProgressDrawable.showArrowOnFirstStart(true);
      mProgressDrawable.setArrowScale(1f);
      mProgressDrawable.showArrow(true);
    }
    super.setImageDrawable(null);
    super.setImageDrawable(mProgressDrawable);
    mProgressDrawable.setAlpha(255);
    mProgressDrawable.setStartEndTrim(0f, 0.75f);
  }
  @Override
  public void onUIPositionChange(
      PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) {

    float percent = Math.min(1f, ptrIndicator.getCurrentPercent());

    if (status == PtrFrameLayout.PTR_STATUS_PREPARE) {
      mDrawable.setAlpha((int) (255 * percent));
      mDrawable.showArrow(true);

      float strokeStart = ((percent) * .8f);
      mDrawable.setStartEndTrim(0f, Math.min(0.8f, strokeStart));
      mDrawable.setArrowScale(Math.min(1f, percent));

      // magic
      float rotation = (-0.25f + .4f * percent + percent * 2) * .5f;
      mDrawable.setProgressRotation(rotation);
      invalidate();
    }
  }
예제 #4
0
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    final int action = MotionEventCompat.getActionMasked(ev);

    if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
      mReturningToStart = false;
    }

    if (!isEnabled() || mReturningToStart || canChildScrollUp()) {
      // Fail fast if we're not in a state where a swipe is possible
      return false;
    }

    switch (action) {
      case MotionEvent.ACTION_DOWN:
        mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
        mIsBeingDragged = false;
        break;

      case MotionEvent.ACTION_MOVE:
        {
          final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
          if (pointerIndex < 0) {
            Log.e(LOG_TAG, "Got ACTION_MOVE event but have an invalid active pointer id.");
            return false;
          }

          final float y = MotionEventCompat.getY(ev, pointerIndex);
          final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE;
          if (mIsBeingDragged) {
            mProgress.showArrow(true);
            float originalDragPercent = overscrollTop / mTotalDragDistance;
            if (originalDragPercent < 0) {
              return false;
            }
            float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
            float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;
            float extraOS = Math.abs(overscrollTop) - mTotalDragDistance;
            float slingshotDist =
                mUsingCustomStart ? mSpinnerFinalOffset - mOriginalOffsetTop : mSpinnerFinalOffset;
            float tensionSlingshotPercent =
                Math.max(0, Math.min(extraOS, slingshotDist * 2) / slingshotDist);
            float tensionPercent =
                (float) ((tensionSlingshotPercent / 4) - Math.pow((tensionSlingshotPercent / 4), 2))
                    * 2f;
            float extraMove = (slingshotDist) * tensionPercent * 2;

            int targetY = mOriginalOffsetTop + (int) ((slingshotDist * dragPercent) + extraMove);
            // where 1.0f is a full circle
            if (mCircleView.getVisibility() != View.VISIBLE) {
              mCircleView.setVisibility(View.VISIBLE);
            }
            if (!mScale) {
              ViewCompat.setScaleX(mCircleView, 1f);
              ViewCompat.setScaleY(mCircleView, 1f);
            }
            if (overscrollTop < mTotalDragDistance) {
              if (mScale) {
                setAnimationProgress(overscrollTop / mTotalDragDistance);
              }
              if (mProgress.getAlpha() > STARTING_PROGRESS_ALPHA
                  && !isAnimationRunning(mAlphaStartAnimation)) {
                // Animate the alpha
                startProgressAlphaStartAnimation();
              }
              float strokeStart = adjustedPercent * .8f;
              mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
              mProgress.setArrowScale(Math.min(1f, adjustedPercent));
            } else {
              if (mProgress.getAlpha() < MAX_ALPHA && !isAnimationRunning(mAlphaMaxAnimation)) {
                // Animate the alpha
                startProgressAlphaMaxAnimation();
              }
            }
            float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f;
            mProgress.setProgressRotation(rotation);
            setTargetOffsetTopAndBottom(
                targetY - mCurrentTargetOffsetTop, true /* requires update */);
          }
          break;
        }
      case MotionEventCompat.ACTION_POINTER_DOWN:
        {
          final int index = MotionEventCompat.getActionIndex(ev);
          mActivePointerId = MotionEventCompat.getPointerId(ev, index);
          break;
        }

      case MotionEventCompat.ACTION_POINTER_UP:
        onSecondaryPointerUp(ev);
        break;

      case MotionEvent.ACTION_UP:
      case MotionEvent.ACTION_CANCEL:
        {
          if (mActivePointerId == INVALID_POINTER) {
            if (action == MotionEvent.ACTION_UP) {
              Log.e(LOG_TAG, "Got ACTION_UP event but don't have an active pointer id.");
            }
            return false;
          }
          final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
          final float y = MotionEventCompat.getY(ev, pointerIndex);
          final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE;
          mIsBeingDragged = false;
          if (overscrollTop > mTotalDragDistance) {
            setRefreshing(true, true /* notify */);
          } else {
            // cancel refresh
            mRefreshing = false;
            mProgress.setStartEndTrim(0f, 0f);
            Animation.AnimationListener listener = null;
            if (!mScale) {
              listener =
                  new Animation.AnimationListener() {

                    @Override
                    public void onAnimationStart(Animation animation) {}

                    @Override
                    public void onAnimationEnd(Animation animation) {
                      if (!mScale) {
                        startScaleDownAnimation(null);
                      }
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {}
                  };
            }
            animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener);
            mProgress.showArrow(false);
          }
          mActivePointerId = INVALID_POINTER;
          return false;
        }
    }

    return true;
  }