@Override
  public List<Animator> createAnimation() {
    List<Animator> animators = new ArrayList<Animator>();
    ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.6f, 1);
    scaleAnim.setDuration(1000);
    scaleAnim.setRepeatCount(-1);
    scaleAnim.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            scaleFloat = (Float) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    scaleAnim.start();

    ValueAnimator rotateAnim = ValueAnimator.ofFloat(0, 180, 360);
    rotateAnim.setDuration(1000);
    rotateAnim.setRepeatCount(-1);
    rotateAnim.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            degrees = (Float) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    rotateAnim.start();
    animators.add(scaleAnim);
    animators.add(rotateAnim);
    return animators;
  }
  private void setup(int duration) {
    // region saturation
    animationSaturation = ValueAnimator.ofFloat(0.2f, 1f);
    animationSaturation.setDuration(duration);
    animationSaturation.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            saturation = animation.getAnimatedFraction();
          }
        });
    // endregion

    // region contrast
    animationContrast = ValueAnimator.ofFloat(0, 1f);
    animationContrast.setDuration(duration * 3 / 4);
    animationContrast.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            ColorMatrix colorMatrix = setContrast(animation.getAnimatedFraction());
            colorMatrix.setSaturation(saturation);
            ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
            drawable.setColorFilter(colorFilter);
          }
        });
    // endregion

    // region alpha
    animationAlpha = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
    animationAlpha.setDuration(duration / 2);
    // endregion
  }
  @Override
  public void createAnimation() {
    float startX = getWidth() / 6;
    float startY = getWidth() / 6;
    for (int i = 0; i < 2; i++) {
      final int index = i;
      ValueAnimator translateXAnim =
          ValueAnimator.ofFloat(startX, getWidth() - startX, startX, getWidth() - startX, startX);
      if (i == 1) {
        translateXAnim =
            ValueAnimator.ofFloat(
                getWidth() - startX, startX, getWidth() - startX, startX, getWidth() - startX);
      }
      ValueAnimator translateYAnim =
          ValueAnimator.ofFloat(startY, startY, getHeight() - startY, getHeight() - startY, startY);
      if (i == 1) {
        translateYAnim =
            ValueAnimator.ofFloat(
                getHeight() - startY, getHeight() - startY, startY, startY, getHeight() - startY);
      }

      translateXAnim.setDuration(2000);
      translateXAnim.setInterpolator(new LinearInterpolator());
      translateXAnim.setRepeatCount(-1);
      translateXAnim.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              translateX[index] = (float) animation.getAnimatedValue();
              postInvalidate();
            }
          });
      translateXAnim.start();

      translateYAnim.setDuration(2000);
      translateYAnim.setInterpolator(new LinearInterpolator());
      translateYAnim.setRepeatCount(-1);
      translateYAnim.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              translateY[index] = (float) animation.getAnimatedValue();
              postInvalidate();
            }
          });
      translateYAnim.start();
    }
  }
Ejemplo n.º 4
0
  private void hideCard(int which) {
    if (isAnimating) return;
    List<Animator> animators = new ArrayList<>(mChildCount);
    final View displayingCard = getChildAt(which);
    int t = (int) (getMeasuredHeight() - (mChildCount - which) * mTitleBarHeightNoDisplay);
    ValueAnimator displayAnimator =
        ValueAnimator.ofFloat(ViewHelper.getY(displayingCard), t).setDuration(mDuration);
    displayAnimator.setTarget(displayingCard);
    final int finalT = t;
    displayAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator valueAnimator) {
            float value = (float) valueAnimator.getAnimatedValue();
            ViewHelper.setY(displayingCard, value);
            if (mDarkFrameLayout != null && isFade && value < finalT) {
              mDarkFrameLayout.fade((int) ((1 - value / finalT) * DarkFrameLayout.MAX_ALPHA));
            }
          }
        });
    animators.add(displayAnimator);
    for (int i = 0; i < mChildCount; i++) {
      if (i == 0 && isExistBackground) continue;
      if (i != which) {
        t = (int) (getMeasuredHeight() - (mChildCount - i) * mTitleBarHeightNoDisplay);
        animators.add(
            ObjectAnimator.ofFloat(getChildAt(i), "y", ViewHelper.getY(getChildAt(i)), t));
      }
    }
    AnimatorSet set = new AnimatorSet();
    set.addListener(
        new Animator.AnimatorListener() {
          @Override
          public void onAnimationStart(Animator animator) {
            isAnimating = true;
          }

          @Override
          public void onAnimationEnd(Animator animator) {
            isAnimating = false;
            isDisplaying = false;
          }

          @Override
          public void onAnimationCancel(Animator animator) {
            isAnimating = false;
            isDisplaying = false;
          }

          @Override
          public void onAnimationRepeat(Animator animator) {}
        });
    set.setInterpolator(mCloseAnimatorInterpolator);
    set.playTogether(animators);
    set.start();
    mDisplayingCard = -1;
    if (mOnDisplayOrHideListener != null)
      mOnDisplayOrHideListener.onHide(isExistBackground ? (which - 1) : which);
  }
  public void animateSubjectOut(final SubjectCard materia) {
    final List<View> toBeAnimated = new ArrayList<View>();
    boolean after = false;
    for (SubjectCard mtr : mSubjectCards) {
      if (after) toBeAnimated.add(mtr);
      if (mtr == materia) after = true;
    }
    toBeAnimated.add(mAddButton);
    final int numberToBeAnimated = toBeAnimated.size();

    int maxScroll = mScrollView.getChildAt(0).getHeight() - mScrollView.getHeight(),
        materiaHeight = materia.getHeight();
    final int initScroll = mScrollView.getScrollY(),
        scrollBy =
            ((maxScroll < initScroll + materiaHeight)
                    ? Math.max(maxScroll - materiaHeight, 0)
                    : initScroll)
                - initScroll;
    ValueAnimator listAnimator = ValueAnimator.ofFloat(0, -materiaHeight);
    listAnimator.setInterpolator(new DecelerateInterpolator(3.2f));
    listAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            float value = (Float) animation.getAnimatedValue();
            for (int i = 0; i < numberToBeAnimated; i++)
              ViewHelper.setTranslationY(toBeAnimated.get(i), value);
            ViewHelper.setScrollY(
                mScrollView, (int) (initScroll + scrollBy * animation.getAnimatedFraction()));
          }
        });
    listAnimator.addListener(
        new AnimatorListenerAdapter() {
          @Override
          public void onAnimationEnd(Animator animation) {
            mSubjectCards.remove(materia);
            mSubjectsLayout.removeView(materia);
            mSqlHelper.remove(materia.getData().getSqlID());
            updateTotal();
            mScrollView.setVerticalScrollBarEnabled(true);
            mScrollView.setOnTouchListener(null);
            for (View mtr : toBeAnimated) ViewHelper.setTranslationY(mtr, 0);
          }
        });
    listAnimator.setDuration(700);
    mScrollView.setVerticalScrollBarEnabled(false);
    mScrollView.setOnTouchListener(
        new View.OnTouchListener() {
          @Override
          public boolean onTouch(View v, MotionEvent event) {
            return true;
          }
        }); // disable user scrolling during the animation

    if (ViewHelper.getTranslationX(materia) == 0) materia.swipeRight(0, 0);
    listAnimator.setStartDelay(500);
    listAnimator.start();
  }
Ejemplo n.º 6
0
    @Override
    public void executeAnim(final View target, final int animType) {
      if (ExpandableStickyListHeadersListView.ANIMATION_EXPAND == animType
          && target.getVisibility() == View.VISIBLE) {
        return;
      }
      if (ExpandableStickyListHeadersListView.ANIMATION_COLLAPSE == animType
          && target.getVisibility() != View.VISIBLE) {
        return;
      }
      if (mOriginalViewHeightPool.get(target) == null) {
        mOriginalViewHeightPool.put(target, target.getHeight());
      }
      final int viewHeight = mOriginalViewHeightPool.get(target);
      float animStartY =
          animType == ExpandableStickyListHeadersListView.ANIMATION_EXPAND ? 0f : viewHeight;
      float animEndY =
          animType == ExpandableStickyListHeadersListView.ANIMATION_EXPAND ? viewHeight : 0f;
      final ViewGroup.LayoutParams lp = target.getLayoutParams();
      ValueAnimator animator = ValueAnimator.ofFloat(animStartY, animEndY);
      animator.setDuration(200);
      target.setVisibility(View.VISIBLE);
      animator.addListener(
          new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {}

            @Override
            public void onAnimationEnd(Animator animator) {
              if (animType == ExpandableStickyListHeadersListView.ANIMATION_EXPAND) {
                target.setVisibility(View.VISIBLE);
              } else {
                target.setVisibility(View.GONE);
              }
              target.getLayoutParams().height = viewHeight;
            }

            @Override
            public void onAnimationCancel(Animator animator) {}

            @Override
            public void onAnimationRepeat(Animator animator) {}
          });
      animator.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
              lp.height = ((Float) valueAnimator.getAnimatedValue()).intValue();
              target.setLayoutParams(lp);
              target.requestLayout();
            }
          });
      animator.start();
    }
  @Override
  public void createAnimation() {
    ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.3f, 1);
    scaleAnim.setDuration(1000);
    scaleAnim.setRepeatCount(-1);
    scaleAnim.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            scaleFloat1 = (float) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    scaleAnim.start();

    ValueAnimator scaleAnim2 = ValueAnimator.ofFloat(1, 0.6f, 1);
    scaleAnim2.setDuration(1000);
    scaleAnim2.setRepeatCount(-1);
    scaleAnim2.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            scaleFloat2 = (float) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    scaleAnim2.start();

    ValueAnimator rotateAnim = ValueAnimator.ofFloat(0, 180, 360);
    rotateAnim.setDuration(1000);
    rotateAnim.setRepeatCount(-1);
    rotateAnim.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            degrees = (float) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    rotateAnim.start();
  }
 public void animateColorPercent(float percent, int duration) {
   ValueAnimator valueAnimator = ValueAnimator.ofFloat(lastPercent, percent);
   valueAnimator.addUpdateListener(
       new ValueAnimator.AnimatorUpdateListener() {
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
           setColorPercent((float) animation.getAnimatedValue());
         }
       });
   valueAnimator.setDuration(duration);
   valueAnimator.start();
 }
  /**
   * Animate change of color
   *
   * @param event Event to process
   */
  public void startAnimateColorChange(@NonNull final DecoEvent event) {
    cancelAnimation();
    event.notifyStartListener();
    mVisible = true;

    mDrawMode = event.getEventType();
    mPercentComplete = 0f;

    final boolean changeColors = event.isColorSet();
    if (changeColors) {
      mColorAnimate = new ColorAnimate(mSeriesItem.getColor(), event.getColor());
      mSeriesItem.setColor(event.getColor());
    } else {
      Log.w(TAG, "Must set new color to start CHANGE_COLOR event");
      return;
    }

    final float maxValue = 1.0f;
    mValueAnimator = ValueAnimator.ofFloat(0, maxValue);

    mValueAnimator.setDuration(event.getEffectDuration());
    if (event.getInterpolator() != null) {
      mValueAnimator.setInterpolator(event.getInterpolator());
    } else {
      mValueAnimator.setInterpolator(new LinearInterpolator());
    }

    mValueAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator valueAnimator) {
            mPercentComplete = Float.valueOf(valueAnimator.getAnimatedValue().toString());

            for (SeriesItem.SeriesItemListener seriesItemListener : mSeriesItem.getListeners()) {
              seriesItemListener.onSeriesItemDisplayProgress(mPercentComplete);
            }
          }
        });

    mValueAnimator.addListener(
        new AnimatorListenerAdapter() {
          @Override
          public void onAnimationEnd(Animator animation) {
            event.notifyEndListener();
          }
        });

    mValueAnimator.start();
  }
  /**
   * Execute an Animation effect by starting the Value Animator
   *
   * @param event Event to process effect
   * @throws IllegalStateException No effect set in event
   */
  public void startAnimateEffect(@NonNull final DecoEvent event) throws IllegalStateException {
    if (event.getEffectType() == null) {
      throw new IllegalStateException("Unable to execute null effect type");
    }

    // All effects run from 0.0 .. 1.0f in duration
    final float maxValue = 1.0f;

    cancelAnimation();
    event.notifyStartListener();

    mVisible = true;
    mDrawMode = event.getEventType();
    mEffect = new DecoDrawEffect(event.getEffectType(), mPaint, event.getDisplayText());
    mEffect.setRotationCount(event.getEffectRotations());

    mPercentComplete = 0f;

    mValueAnimator = ValueAnimator.ofFloat(0, maxValue);
    mValueAnimator.setDuration(event.getEffectDuration());
    Interpolator interpolator =
        (event.getInterpolator() != null) ? event.getInterpolator() : new LinearInterpolator();
    mValueAnimator.setInterpolator(interpolator);

    mValueAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator valueAnimator) {
            mPercentComplete = Float.valueOf(valueAnimator.getAnimatedValue().toString());
            for (SeriesItem.SeriesItemListener seriesItemListener : mSeriesItem.getListeners()) {
              seriesItemListener.onSeriesItemDisplayProgress(mPercentComplete);
            }
          }
        });

    mValueAnimator.addListener(
        new AnimatorListenerAdapter() {
          @Override
          public void onAnimationEnd(Animator animation) {
            event.notifyEndListener();
            mDrawMode = DecoEvent.EventType.EVENT_MOVE;
            mVisible = mEffect.postExecuteVisibility();
            mEffect = null;
          }
        });

    mValueAnimator.start();
  }
 public AnimationBuilder custom(final AnimationListener.Update update, float... values) {
   for (final View view : views) {
     ValueAnimator valueAnimator = ValueAnimator.ofFloat(getValues(values));
     if (update != null)
       valueAnimator.addUpdateListener(
           new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
               //noinspection unchecked
               update.update(view, (Float) animation.getAnimatedValue());
             }
           });
     add(valueAnimator);
   }
   return this;
 }
  private void handleActionUp() {
    if (isOutOfRange) {
      // When user drag it back, we should call onReset().
      if (GeometryUtil.getDistanceBetween2Points(mDragCenter, mInitCenter) < resetDistance) {
        if (mListener != null) mListener.onReset(isOutOfRange);
        return;
      }

      // Otherwise
      disappeared();
    } else {

      // 手指抬起时,弹回动画
      mAnim = ValueAnimator.ofFloat(1.0f);
      mAnim.setInterpolator(new OvershootInterpolator(4.0f));

      final PointF startPoint = new PointF(mDragCenter.x, mDragCenter.y);
      final PointF endPoint = new PointF(mStickCenter.x, mStickCenter.y);
      mAnim.addUpdateListener(
          new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              float fraction = animation.getAnimatedFraction();
              PointF pointByPercent =
                  GeometryUtil.getPointByPercent(startPoint, endPoint, fraction);
              updateDragCenter((float) pointByPercent.x, (float) pointByPercent.y);
            }
          });
      mAnim.addListener(
          new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
              if (mListener != null) mListener.onReset(isOutOfRange);
            }
          });
      if (GeometryUtil.getDistanceBetween2Points(startPoint, endPoint) < 10) {
        mAnim.setDuration(10);
      } else {
        mAnim.setDuration(500);
      }
      mAnim.start();
    }
  }
Ejemplo n.º 13
0
  public void show(final View view) {
    pushedView = view;
    if (this.getParent() != null) return;
    synchronized (Snackbar.class) {
      if (!next.contains(this)) next.add(this);
      if (next.indexOf(this) == 0) {
        View decor = ((Activity) getContext()).getWindow().getDecorView();
        ((ViewGroup) decor.findViewById(android.R.id.content))
            .addView(
                this, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

        ViewHelper.setAlpha(content, 0);
        AnimUtils.flyIn(content, null);
        if (view != null) {
          ValueAnimator animator = ValueAnimator.ofFloat(0, -1);
          animator.setDuration(200);
          animator.setInterpolator(new DecelerateInterpolator());
          animator.addUpdateListener(
              new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                  MarginLayoutParams lp = (MarginLayoutParams) content.getLayoutParams();
                  Log.e(
                      "snackbar " + Snackbar.this.hashCode(),
                      ""
                          + ((content.getHeight() + lp.bottomMargin)
                              * (Float) valueAnimator.getAnimatedValue()));
                  ViewHelper.setTranslationY(
                      view,
                      (content.getHeight() + lp.bottomMargin)
                          * (Float) valueAnimator.getAnimatedValue());
                  if (pushedView.getParent() != null)
                    ((View) pushedView.getParent()).postInvalidate();
                }
              });
          animator.start();
        }
        if (duration != INFINITE) handler.postDelayed(hideRunnable, duration);
      }
    }
  }
  /**
   * Kick off an animation to hide or show the arc. This results in an animation where both the
   * width of the line used for the arc and the transparency of the arc is altered over the duration
   * provided
   *
   * @param event Event to process
   * @param showArc True to show the arc, false to hide
   */
  public void startAnimateHideShow(@NonNull final DecoEvent event, final boolean showArc) {
    cancelAnimation();
    event.notifyStartListener();

    mDrawMode = event.getEventType();
    mPercentComplete = showArc ? 1.0f : 0f;
    mVisible = true;

    final float maxValue = 1.0f;
    mValueAnimator = ValueAnimator.ofFloat(0, maxValue);

    mValueAnimator.setDuration(event.getEffectDuration());
    mValueAnimator.setInterpolator(new LinearInterpolator());

    mValueAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator valueAnimator) {

            float current = Float.valueOf(valueAnimator.getAnimatedValue().toString());
            mPercentComplete = showArc ? (maxValue - current) : current;

            for (SeriesItem.SeriesItemListener seriesItemListener : mSeriesItem.getListeners()) {
              seriesItemListener.onSeriesItemDisplayProgress(mPercentComplete);
            }
          }
        });

    mValueAnimator.addListener(
        new AnimatorListenerAdapter() {
          @Override
          public void onAnimationEnd(Animator animation) {
            if (event.getEventType() != DecoEvent.EventType.EVENT_EFFECT) {
              event.notifyEndListener();
            }
          }
        });

    mValueAnimator.start();
  }
  @Override
  public void createAnimation() {
    int[] delays = new int[] {120, 240, 360};
    for (int i = 0; i < 3; i++) {
      final int index = i;

      ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.3f, 1);
      scaleAnim.setDuration(750);
      scaleAnim.setRepeatCount(-1); // 循环
      scaleAnim.setStartDelay(delays[i]);
      scaleAnim.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              // 每次值value值变化的时候 重设对应 位置圆的scale值
              scaleFloats[index] = (float) animation.getAnimatedValue();
              postInvalidate(); // 通知重绘
            }
          });
      scaleAnim.start();
    }
  }
Ejemplo n.º 16
0
 public void hide() {
   synchronized (Snackbar.class) {
     if (getParent() == null) return;
     handler.removeCallbacks(hideRunnable);
     if (onDismissedListener != null) onDismissedListener.onDismissed();
     AnimUtils.flyOut(
         content,
         new AnimatorListenerAdapter() {
           @Override
           public void onAnimationEnd(Animator animator) {
             hideInternal();
           }
         });
     if (pushedView != null) {
       ValueAnimator animator = ValueAnimator.ofFloat(-1, 0);
       animator.setDuration(200);
       animator.setInterpolator(new DecelerateInterpolator());
       animator.addUpdateListener(
           new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator valueAnimator) {
               MarginLayoutParams lp = (MarginLayoutParams) content.getLayoutParams();
               Log.e(
                   "snackbar " + Snackbar.this.hashCode(),
                   ""
                       + ((content.getHeight() + lp.bottomMargin)
                           * (Float) valueAnimator.getAnimatedValue()));
               ViewHelper.setTranslationY(
                   pushedView,
                   (content.getHeight() + lp.bottomMargin)
                       * (Float) valueAnimator.getAnimatedValue());
               if (pushedView.getParent() != null)
                 ((View) pushedView.getParent()).postInvalidate();
             }
           });
       animator.start();
     }
   }
 }
 /** 回滚状态动画 */
 private void startRollBackAnimation(long duration) {
   ValueAnimator rollBackAnim = ValueAnimator.ofFloat(curRadius, originRadius);
   rollBackAnim.addUpdateListener(
       new ValueAnimator.AnimatorUpdateListener() {
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
           float value = (float) animation.getAnimatedValue();
           curRadius = (int) value;
           postInvalidate();
         }
       });
   rollBackAnim.setInterpolator(new BounceInterpolator()); // 反弹效果
   rollBackAnim.addListener(
       new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
           super.onAnimationEnd(animation);
           DraggableFlagView.this.clearAnimation();
         }
       });
   rollBackAnim.setDuration(duration);
   rollBackAnim.start();
 }
Ejemplo n.º 18
0
 @Override
 public List<Animator> createAnimation() {
   List<Animator> animators = new ArrayList<>();
   long[] delays = new long[] {100, 200, 300, 400, 500};
   for (int i = 0; i < 5; i++) {
     final int index = i;
     ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.4f, 1);
     scaleAnim.setDuration(1000);
     scaleAnim.setRepeatCount(-1);
     scaleAnim.setStartDelay(delays[i]);
     scaleAnim.addUpdateListener(
         new ValueAnimator.AnimatorUpdateListener() {
           @Override
           public void onAnimationUpdate(ValueAnimator animation) {
             scaleYFloats[index] = (float) animation.getAnimatedValue();
             postInvalidate();
           }
         });
     scaleAnim.start();
     animators.add(scaleAnim);
   }
   return animators;
 }
  @Override
  public void createAnimation() {
    int[] durations = {720, 1020, 1280, 1420, 1450, 1180, 870, 1450, 1060};
    int[] delays = {-60, 250, -170, 480, 310, 30, 460, 780, 450};

    for (int i = 0; i < 9; i++) {
      final int index = i;
      ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.5f, 1);
      scaleAnim.setDuration(durations[i]);
      scaleAnim.setRepeatCount(-1);
      scaleAnim.setStartDelay(delays[i]);
      scaleAnim.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              scaleFloats[index] = (float) animation.getAnimatedValue();
              postInvalidate();
            }
          });
      scaleAnim.start();

      ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 210, 122, 255);
      alphaAnim.setDuration(durations[i]);
      alphaAnim.setRepeatCount(-1);
      alphaAnim.setStartDelay(delays[i]);
      alphaAnim.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              alphas[index] = (int) animation.getAnimatedValue();
              postInvalidate();
            }
          });
      alphaAnim.start();
    }
  }
  @Override
  public void createAnimation() {
    long[] delays = new long[] {0, 200, 400};
    for (int i = 0; i < 3; i++) {
      final int index = i;
      ValueAnimator scaleAnim = ValueAnimator.ofFloat(0, 1);
      scaleAnim.setInterpolator(new LinearInterpolator());
      scaleAnim.setDuration(1000);
      scaleAnim.setRepeatCount(-1);
      scaleAnim.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              scaleFloats[index] = (float) animation.getAnimatedValue();
              postInvalidate();
            }
          });
      scaleAnim.setStartDelay(delays[i]);
      scaleAnim.start();

      ValueAnimator alphaAnim = ValueAnimator.ofInt(0, 255);
      scaleAnim.setInterpolator(new LinearInterpolator());
      alphaAnim.setDuration(1000);
      alphaAnim.setRepeatCount(-1);
      alphaAnim.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              alphaInts[index] = (int) animation.getAnimatedValue();
              postInvalidate();
            }
          });
      scaleAnim.setStartDelay(delays[i]);
      alphaAnim.start();
    }
  }
Ejemplo n.º 21
0
  public static class SplashView extends View {

    private ValueAnimator fadeAndScaleAnimator = ValueAnimator.ofFloat(0, 1f).setDuration(4000);
    private ObjectAnimator rotationAnimator =
        ObjectAnimator.ofFloat(this, "rotation", 0, 90).setDuration(1000);

    public boolean hasfired;

    private int mWidth, mHeight;
    private float top, right, left, bottom;
    private float drawBoxH, drawBoxW;
    private Paint barPaint;
    private Paint backgroundPaint;

    public SplashView(Context context) {
      super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      super.onDraw(
          canvas); // To change body of overridden methods use File | Settings | File Templates.

      canvas.drawRect(0, 0, mWidth, mHeight, backgroundPaint);
      float barWidth = (drawBoxW - (drawBoxW / 10)) / 3;
      float gap = drawBoxH / 30;

      float movement = drawBoxH / 2 * fadeAndScaleAnimator.getAnimatedFraction();

      canvas.drawRect(left, top, left + barWidth, bottom, barPaint);
      canvas.drawRect(left + barWidth + 5, top, left + barWidth * 2, bottom, barPaint);
      canvas.drawRect(
          left + barWidth * 2 + 5, top + movement, left + barWidth * 3, bottom, barPaint);
      canvas.rotate(rotationAnimator.getAnimatedFraction());
    }

    public void start() {
      initpaints();
      fadeAndScaleAnimator.setInterpolator(new OvershootInterpolator(1.15f));
      fadeAndScaleAnimator.start();
      fadeAndScaleAnimator.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              invalidate();
              if (animation.getAnimatedFraction() > .8f && !hasfired) {
                hasfired = true;
                rotationAnimator.start();
              }
            }
          });
      rotationAnimator.setInterpolator(new DecelerateInterpolator());

      rotationAnimator.addUpdateListener(
          new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
              invalidate();
            }
          });
    }

    @Override
    protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
      super.onSizeChanged(xNew, yNew, xOld, yOld);
      mWidth = xNew;
      mHeight = yNew;
      drawBoxW = mWidth / 2;
      drawBoxH = mHeight / 2;

      float centerX = mWidth / 2;
      float centerY = mHeight / 2;

      top = centerY - (drawBoxH / 2);
      left = centerX - (drawBoxW / 2);
      right = centerX + (drawBoxW / 2);
      bottom = centerY + (drawBoxH / 2);
    }

    private void initpaints() {
      barPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      barPaint.setStyle(Paint.Style.FILL);
      barPaint.setColor(Color.rgb(0, 0, 0));
      barPaint.setAntiAlias(true);

      backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      backgroundPaint.setStyle(Paint.Style.FILL);
      backgroundPaint.setColor(Color.rgb(255, 255, 255));
      backgroundPaint.setAntiAlias(true);
    }
  }
Ejemplo n.º 22
0
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float v = (value - min) / (max - min);
    float v2 = (value2 - min) / (max - min);

    if (event.getAction() == MotionEvent.ACTION_DOWN) {
      int thumbX =
          (int)
              (v * (getWidth() - getPaddingLeft() - getPaddingRight() - thumbRadius * 2)
                  + getPaddingLeft()
                  + thumbRadius);
      int thumbX2 =
          (int)
              (v2 * (getWidth() - getPaddingLeft() - getPaddingRight() - thumbRadius2 * 2)
                  + getPaddingLeft()
                  + thumbRadius2);
      if (Math.abs(event.getX() - thumbX) < Math.abs(event.getX() - thumbX2)) {
        draggedThumb = 1;
        if (radiusAnimator != null) radiusAnimator.end();
        radiusAnimator = ValueAnimator.ofFloat(thumbRadius, THUMB_RADIUS_DRAGGED);
        radiusAnimator.setDuration(200);
        radiusAnimator.setInterpolator(interpolator);
        radiusAnimator.addUpdateListener(
            new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                thumbRadius = (float) animation.getAnimatedValue();
                postInvalidate();
              }
            });
        radiusAnimator.start();
      } else {
        draggedThumb = 2;
        if (radiusAnimator != null) radiusAnimator.end();
        radiusAnimator = ValueAnimator.ofFloat(thumbRadius2, THUMB_RADIUS_DRAGGED);
        radiusAnimator.setDuration(200);
        radiusAnimator.setInterpolator(interpolator);
        radiusAnimator.addUpdateListener(
            new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                thumbRadius2 = (float) animation.getAnimatedValue();
                postInvalidate();
              }
            });
        radiusAnimator.start();
      }
      ViewParent parent = getParent();
      if (parent != null) parent.requestDisallowInterceptTouchEvent(true);
    } else if (event.getAction() == MotionEvent.ACTION_CANCEL
        || event.getAction() == MotionEvent.ACTION_UP) {
      if (draggedThumb == 1) {
        if (style == Style.Discrete) {
          float val = (float) Math.floor((value - min + step / 2) / step) * step + min;
          if (valueAnimator != null) valueAnimator.cancel();
          valueAnimator = ValueAnimator.ofFloat(value, val);
          valueAnimator.setDuration(200);
          valueAnimator.setInterpolator(interpolator);
          valueAnimator.addUpdateListener(
              new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                  value = (float) animation.getAnimatedValue();
                  int thumbX =
                      (int)
                          ((value - min)
                                  / (max - min)
                                  * (getWidth() - getPaddingLeft() - getPaddingRight())
                              + getPaddingLeft());
                  int thumbY = getHeight() / 2;
                  int radius = rippleDrawable.getRadius();
                  rippleDrawable.setBounds(
                      thumbX - radius, thumbY - radius, thumbX + radius, thumbY + radius);
                  postInvalidate();
                }
              });
          valueAnimator.start();
        }
        if (radiusAnimator != null) radiusAnimator.end();
        radiusAnimator = ValueAnimator.ofFloat(thumbRadius, THUMB_RADIUS);
        radiusAnimator.setDuration(200);
        radiusAnimator.setInterpolator(interpolator);
        radiusAnimator.addUpdateListener(
            new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                thumbRadius = (float) animation.getAnimatedValue();
                postInvalidate();
              }
            });
        radiusAnimator.start();
      } else {
        if (style == Style.Discrete) {
          float val2 = (float) Math.floor((value2 - min + step / 2) / step) * step + min;
          if (valueAnimator != null) valueAnimator.cancel();
          valueAnimator = ValueAnimator.ofFloat(value2, val2);
          valueAnimator.setDuration(200);
          valueAnimator.setInterpolator(interpolator);
          valueAnimator.addUpdateListener(
              new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                  value2 = (float) animation.getAnimatedValue();
                  int thumbX =
                      (int)
                          ((value2 - min)
                                  / (max - min)
                                  * (getWidth() - getPaddingLeft() - getPaddingRight())
                              + getPaddingLeft());
                  int thumbY = getHeight() / 2;
                  int radius = rippleDrawable.getRadius();
                  rippleDrawable.setBounds(
                      thumbX - radius, thumbY - radius, thumbX + radius, thumbY + radius);
                  postInvalidate();
                }
              });
          valueAnimator.start();
        }
        if (radiusAnimator != null) radiusAnimator.end();
        radiusAnimator = ValueAnimator.ofFloat(thumbRadius2, THUMB_RADIUS);
        radiusAnimator.setDuration(200);
        radiusAnimator.setInterpolator(interpolator);
        radiusAnimator.addUpdateListener(
            new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                thumbRadius2 = (float) animation.getAnimatedValue();
                postInvalidate();
              }
            });
        radiusAnimator.start();
      }
      draggedThumb = -1;
      ViewParent parent = getParent();
      if (parent != null) parent.requestDisallowInterceptTouchEvent(false);
    }

    if (draggedThumb == 1) {
      v = (event.getX() - getPaddingLeft()) / (getWidth() - getPaddingLeft() - getPaddingRight());
      v = Math.max(0, Math.min(v, 1));
    } else if (draggedThumb == 2) {
      v2 = (event.getX() - getPaddingLeft()) / (getWidth() - getPaddingLeft() - getPaddingRight());
      v2 = Math.max(0, Math.min(v2, 1));
    }

    if (v > v2) {
      draggedThumb = 3 - draggedThumb;
      float t = v;
      v = v2;
      v2 = t;
    }
    float newValue = v * (max - min) + min;
    float newValue2 = v2 * (max - min) + min;

    if (rippleDrawable != null) {
      rippleDrawable.setHotspot(event.getX(), event.getY());
      int thumbY = getHeight() / 2;
      int radius = rippleDrawable.getRadius();
      if (draggedThumb == 1) {
        int thumbX =
            (int) (v * (getWidth() - getPaddingLeft() - getPaddingRight()) + getPaddingLeft());
        rippleDrawable.setBounds(
            thumbX - radius, thumbY - radius, thumbX + radius, thumbY + radius);
      } else if (draggedThumb == 2) {
        int thumbX2 =
            (int) (v2 * (getWidth() - getPaddingLeft() - getPaddingRight()) + getPaddingLeft());
        rippleDrawable.setBounds(
            thumbX2 - radius, thumbY - radius, thumbX2 + radius, thumbY + radius);
      }
    }

    postInvalidate();
    if (newValue != value && onValueChangedListener != null) {
      if (style == Style.Discrete) {
        int sv = stepValue(newValue);
        int sv2 = stepValue(newValue2);
        if (stepValue(value) != sv || stepValue(value2) != sv2)
          onValueChangedListener.onValueChanged(this, sv, sv2);
      } else {
        onValueChangedListener.onValueChanged(this, newValue, newValue2);
      }
      value = newValue;
    }
    super.onTouchEvent(event);
    return true;
  }
Ejemplo n.º 23
0
  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    boolean hit = e2.getY() > content.getTop() && getParent() != null;

    if (hit && swipeToDismiss && animator == null) {
      swipe = e2.getX() - e1.getX();
      ViewHelper.setTranslationX(content, swipe);
      ViewHelper.setAlpha(content, Math.max(0, 1 - 2 * Math.abs(swipe) / content.getWidth()));
      postInvalidate();
      if (Math.abs(swipe) > content.getWidth() / 4) {
        handler.removeCallbacks(hideRunnable);
        animator = ObjectAnimator.ofFloat(swipe, content.getWidth() / 2.0f * Math.signum(swipe));
        animator.setDuration(200);
        animator.addUpdateListener(
            new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float s = (Float) valueAnimator.getAnimatedValue();
                ViewHelper.setTranslationX(content, s);
                float alpha =
                    Math.max(
                        0,
                        1
                            - 2
                                * Math.abs((Float) valueAnimator.getAnimatedValue())
                                / content.getWidth());
                ViewHelper.setAlpha(content, alpha);
                postInvalidate();
              }
            });
        animator.start();
        animator.addListener(
            new AnimatorListenerAdapter() {
              @Override
              public void onAnimationEnd(Animator animation) {
                hideInternal();
                animator = null;
              }
            });
        if (pushedView != null) {
          ValueAnimator animator = ValueAnimator.ofFloat(-1, 0);
          animator.setDuration(200);
          animator.setInterpolator(new DecelerateInterpolator());
          animator.addUpdateListener(
              new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                  MarginLayoutParams lp = (MarginLayoutParams) content.getLayoutParams();
                  Log.e(
                      "snackbar " + Snackbar.this.hashCode(),
                      ""
                          + ((content.getHeight() + lp.bottomMargin)
                              * (Float) valueAnimator.getAnimatedValue()));
                  ViewHelper.setTranslationY(
                      pushedView,
                      (content.getHeight() + lp.bottomMargin)
                          * (Float) valueAnimator.getAnimatedValue());
                  if (pushedView.getParent() != null)
                    ((View) pushedView.getParent()).postInvalidate();
                }
              });
          animator.start();
        }
      }
      return true;
    }
    return false;
  }
Ejemplo n.º 24
0
  @Override
  public List<Animator> createAnimation() {
    List<Animator> animators = new ArrayList<>();
    float startT = getWidth() / 11;
    ValueAnimator translationAnim = ValueAnimator.ofFloat(getWidth() - startT, getWidth() / 2);
    translationAnim.setDuration(650);
    translationAnim.setInterpolator(new LinearInterpolator());
    translationAnim.setRepeatCount(-1);
    translationAnim.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            translateX = (float) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    translationAnim.start();

    ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 122);
    alphaAnim.setDuration(650);
    alphaAnim.setRepeatCount(-1);
    alphaAnim.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            alpha = (int) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    alphaAnim.start();

    ValueAnimator rotateAnim1 = ValueAnimator.ofFloat(0, 45, 0);
    rotateAnim1.setDuration(650);
    rotateAnim1.setRepeatCount(-1);
    rotateAnim1.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            degrees1 = (float) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    rotateAnim1.start();

    ValueAnimator rotateAnim2 = ValueAnimator.ofFloat(0, -45, 0);
    rotateAnim2.setDuration(650);
    rotateAnim2.setRepeatCount(-1);
    rotateAnim2.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator animation) {
            degrees2 = (float) animation.getAnimatedValue();
            postInvalidate();
          }
        });
    rotateAnim2.start();

    animators.add(translationAnim);
    animators.add(alphaAnim);
    animators.add(rotateAnim1);
    animators.add(rotateAnim2);
    return animators;
  }
  /** Create the animation of filling the chart by using a valueAnimator to adjust values */
  public void startAnimateMove(@NonNull final DecoEvent event) {
    mIsPaused = false;
    mDrawMode = event.getEventType();
    mVisible = true;

    cancelAnimation();
    mEventCurrent = event;

    final boolean changeColors = event.isColorSet();
    if (changeColors) {
      mColorAnimate = new ColorAnimate(mSeriesItem.getColor(), event.getColor());
      mSeriesItem.setColor(event.getColor());
    }
    float position = event.getEndPosition();

    event.notifyStartListener();

    mPositionStart = mPositionCurrentEnd;
    mPositionEnd = position;

    long animationDuration = event.getEffectDuration();

    if ((animationDuration == 0) || (Math.abs(mPositionEnd - mPositionStart) < 0.01)) {
      cancelAnimation();
      mPositionCurrentEnd = mPositionEnd;
      mEventCurrent = null;
      mPercentComplete = 1.0f;
      for (SeriesItem.SeriesItemListener seriesItemListener : mSeriesItem.getListeners()) {
        seriesItemListener.onSeriesItemAnimationProgress(1.0f, mPositionEnd);
      }
      event.notifyEndListener();
      return;
    }

    if (animationDuration < 0) {
      /**
       * If an animation duration is not set we calculate it using a formula of the proportion of a
       * revolution multiplied by the default time for a full revolution. This ensures that the
       * speed of the move is consistent for all ranges
       */
      animationDuration =
          (Math.abs(
              (int)
                  (mSeriesItem.getSpinDuration()
                      * ((mPositionStart - mPositionEnd) / mSeriesItem.getMaxValue()))));
    }

    mValueAnimator = ValueAnimator.ofFloat(mPositionStart, position);
    mValueAnimator.setDuration(animationDuration);

    /**
     * Note: When setting the Interpolator the default is {@link
     * android.view.animation.AccelerateDecelerateInterpolator}
     *
     * <p>However, if you call setInterpolator(null) then the default is not used, rather: {@link
     * LinearInterpolator}
     */
    if (event.getInterpolator() != null) {
      mValueAnimator.setInterpolator(event.getInterpolator());
    } else {
      if (mSeriesItem.getInterpolator() != null) {
        mValueAnimator.setInterpolator(mSeriesItem.getInterpolator());
      }
    }

    mValueAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator valueAnimator) {
            float current = Float.valueOf(valueAnimator.getAnimatedValue().toString());
            mPercentComplete = (current - mPositionStart) / (mPositionEnd - mPositionStart);
            mPositionCurrentEnd = current;

            /**
             * Notify the listeners of position update. This will be the OrbView itself and possibly
             * the user who is using a listener to update the progress in an alternative manner, ie.
             * displaying text progress %
             */
            for (SeriesItem.SeriesItemListener seriesItemListener : mSeriesItem.getListeners()) {
              seriesItemListener.onSeriesItemAnimationProgress(
                  mPercentComplete, mPositionCurrentEnd);
            }
          }
        });

    mValueAnimator.addListener(
        new AnimatorListenerAdapter() {
          @Override
          public void onAnimationEnd(Animator animation) {
            if (changeColors) {
              mColorAnimate = null;
            }

            event.notifyEndListener();
          }
        });

    mValueAnimator.start();
  }
Ejemplo n.º 26
0
  private void displayCard(int which) {
    if (isDisplaying || isAnimating) return;
    if (isFade && mDarkFrameLayout != null) mDarkFrameLayout.fade(true);
    List<Animator> animators = new ArrayList<>(mChildCount);
    final float distance = ViewHelper.getY(getChildAt(which)) - mMarginTop;
    ValueAnimator displayAnimator =
        ValueAnimator.ofFloat(ViewHelper.getY(getChildAt(which)), mMarginTop)
            .setDuration(mDuration);
    displayAnimator.setTarget(getChildAt(which));
    final View displayingView = getChildAt(which);
    displayAnimator.addUpdateListener(
        new ValueAnimator.AnimatorUpdateListener() {
          @Override
          public void onAnimationUpdate(ValueAnimator valueAnimator) {
            float value = (float) valueAnimator.getAnimatedValue();
            ViewHelper.setY(displayingView, value);
            if (mDarkFrameLayout != null && isFade) {
              mDarkFrameLayout.fade(
                  (int) ((1 - (value - mMarginTop) / distance) * DarkFrameLayout.MAX_ALPHA));
            }
          }
        });
    animators.add(displayAnimator);
    int n = isExistBackground ? (mChildCount - 1) : mChildCount;
    for (int i = 0, j = 1; i < mChildCount; i++) {
      if (i == 0 && isExistBackground) continue;
      if (i != which) {
        animators.add(
            ObjectAnimator.ofFloat(
                    getChildAt(i),
                    "y",
                    ViewHelper.getY(getChildAt(i)),
                    getMeasuredHeight() - mTitleBarHeightDisplay * (n - j))
                .setDuration(mDuration));
        j++;
      }
    }
    AnimatorSet set = new AnimatorSet();
    set.addListener(
        new Animator.AnimatorListener() {
          @Override
          public void onAnimationStart(Animator animator) {
            isAnimating = true;
          }

          @Override
          public void onAnimationEnd(Animator animator) {
            isAnimating = false;
          }

          @Override
          public void onAnimationCancel(Animator animator) {
            isAnimating = false;
          }

          @Override
          public void onAnimationRepeat(Animator animator) {}
        });
    set.setInterpolator(mOpenAnimatorInterpolator);
    set.playTogether(animators);
    set.start();
    isDisplaying = true;
    mDisplayingCard = which;
    if (mOnDisplayOrHideListener != null)
      mOnDisplayOrHideListener.onDisplay(isExistBackground ? (which - 1) : which);
  }