示例#1
0
  public SoundLevels(final Context context, final AttributeSet attrs, final int defStyle) {
    super(context, attrs, defStyle);

    // Safe source, replaced with system one when attached.
    mLevelSource = new AudioLevelSource();
    mLevelSource.setSpeechLevel(0);

    final TypedArray a =
        context.obtainStyledAttributes(attrs, R.styleable.SoundLevels, defStyle, 0);

    mMaximumLevelSize = a.getDimensionPixelOffset(R.styleable.SoundLevels_maxLevelRadius, 0);
    mMinimumLevelSize = a.getDimensionPixelOffset(R.styleable.SoundLevels_minLevelRadius, 0);
    mMinimumLevel = mMinimumLevelSize / mMaximumLevelSize;

    mPrimaryLevelPaint = new Paint();
    mPrimaryLevelPaint.setColor(a.getColor(R.styleable.SoundLevels_primaryColor, Color.BLACK));
    mPrimaryLevelPaint.setFlags(Paint.ANTI_ALIAS_FLAG);

    a.recycle();

    // This animator generates ticks that invalidate the
    // view so that the animation is synced with the global animation loop.
    // TODO: We could probably remove this in favor of using postInvalidateOnAnimation
    // which might improve things further.
    mSpeechLevelsAnimator = new TimeAnimator();
    mSpeechLevelsAnimator.setRepeatCount(ObjectAnimator.INFINITE);
    mSpeechLevelsAnimator.setTimeListener(
        new TimeListener() {
          @Override
          public void onTimeUpdate(
              final TimeAnimator animation, final long totalTime, final long deltaTime) {
            invalidate();
          }
        });
  }
示例#2
0
 private void startSpeechLevelsAnimator() {
   if (DEBUG) {
     Log.d(TAG, "startAnimator()");
   }
   if (!mSpeechLevelsAnimator.isStarted()) {
     mSpeechLevelsAnimator.start();
   }
 }
示例#3
0
 private void stopSpeechLevelsAnimator() {
   if (DEBUG) {
     Log.d(TAG, "stopAnimator()");
   }
   if (mSpeechLevelsAnimator.isStarted()) {
     mSpeechLevelsAnimator.end();
   }
 }
示例#4
0
 @Override
 public void run() {
   if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
     mTimeAnimator.end();
     mRubberbanding = false;
     mClosing = false;
   }
 }
示例#5
0
  // Rubberbands the panel to hold its contents.
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    if (DEBUG)
      LOG(
          "onMeasure(%d, %d) -> (%d, %d)",
          widthMeasureSpec, heightMeasureSpec, getMeasuredWidth(), getMeasuredHeight());

    // Did one of our children change size?
    int newHeight = getMeasuredHeight();
    if (newHeight != mFullHeight) {
      mFullHeight = newHeight;
      // If the user isn't actively poking us, let's rubberband to the content
      if (!mTracking
          && !mRubberbanding
          && !mTimeAnimator.isStarted()
          && mExpandedHeight > 0
          && mExpandedHeight != mFullHeight) {
        mExpandedHeight = mFullHeight;
      }
    }
    heightMeasureSpec =
        MeasureSpec.makeMeasureSpec(
            (int) mExpandedHeight, MeasureSpec.AT_MOST); // MeasureSpec.getMode(heightMeasureSpec));
    setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
  }
示例#6
0
 public void setExpandedHeight(float height) {
   if (DEBUG) LOG("setExpandedHeight(%.1f)", height);
   mRubberbanding = false;
   if (mTimeAnimator.isRunning()) {
     post(mStopAnimator);
   }
   setExpandedHeightInternal(height);
   mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
 }
示例#7
0
 private void runPeekAnimation() {
   if (DEBUG) LOG("peek to height=%.1f", mPeekHeight);
   if (mTimeAnimator.isStarted()) {
     return;
   }
   if (mPeekAnimator == null) {
     mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", mPeekHeight).setDuration(250);
   }
   mPeekAnimator.start();
 }
示例#8
0
 public void collapse() {
   // TODO: abort animation or ongoing touch
   if (DEBUG) LOG("collapse: " + this);
   if (!isFullyCollapsed()) {
     mTimeAnimator.cancel();
     mClosing = true;
     // collapse() should never be a rubberband, even if an animation is already running
     mRubberbanding = false;
     fling(-mSelfCollapseVelocityPx, /*always=*/ true);
   }
 }
示例#9
0
  public PanelView(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTimeAnimator = new TimeAnimator();
    mTimeAnimator.setTimeListener(mAnimationCallback);
  }
示例#10
0
  private void animationTick(long dtms) {
    if (!mTimeAnimator.isStarted()) {
      // XXX HAX to work around bug in TimeAnimator.end() not resetting its last time
      mTimeAnimator = new TimeAnimator();
      mTimeAnimator.setTimeListener(mAnimationCallback);

      if (mPeekAnimator != null) mPeekAnimator.cancel();

      mTimeAnimator.start();

      mRubberbanding =
          mRubberbandingEnabled // is it enabled at all?
              && mExpandedHeight > getFullHeight() // are we past the end?
              && mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture?
      if (mRubberbanding) {
        mClosing = true;
      } else if (mVel == 0) {
        // if the panel is less than halfway open, close it
        mClosing = (mFinalTouchY / getFullHeight()) < 0.5f;
      } else {
        mClosing = mExpandedHeight > 0 && mVel < 0;
      }
    } else if (dtms > 0) {
      final float dt = dtms * 0.001f; // ms -> s
      if (DEBUG) LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
      if (DEBUG) LOG("tick: before: h=%d", (int) mExpandedHeight);

      final float fh = getFullHeight();
      boolean braking = false;
      if (BRAKES) {
        if (mClosing) {
          braking = mExpandedHeight <= mCollapseBrakingDistancePx;
          mAccel = braking ? 10 * mCollapseAccelPx : -mCollapseAccelPx;
        } else {
          braking = mExpandedHeight >= (fh - mExpandBrakingDistancePx);
          mAccel = braking ? 10 * -mExpandAccelPx : mExpandAccelPx;
        }
      } else {
        mAccel = mClosing ? -mCollapseAccelPx : mExpandAccelPx;
      }

      mVel += mAccel * dt;

      if (braking) {
        if (mClosing && mVel > -mBrakingSpeedPx) {
          mVel = -mBrakingSpeedPx;
        } else if (!mClosing && mVel < mBrakingSpeedPx) {
          mVel = mBrakingSpeedPx;
        }
      } else {
        if (mClosing && mVel > -mFlingCollapseMinVelocityPx) {
          mVel = -mFlingCollapseMinVelocityPx;
        } else if (!mClosing && mVel > mFlingGestureMaxOutputVelocityPx) {
          mVel = mFlingGestureMaxOutputVelocityPx;
        }
      }

      float h = mExpandedHeight + mVel * dt;

      if (mRubberbanding && h < fh) {
        h = fh;
      }

      if (DEBUG) LOG("tick: new h=%d closing=%s", (int) h, mClosing ? "true" : "false");

      setExpandedHeightInternal(h);

      mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);

      if (mVel == 0
          || (mClosing && mExpandedHeight == 0)
          || ((mRubberbanding || !mClosing) && mExpandedHeight == fh)) {
        post(mStopAnimator);
      }
    }
  }