예제 #1
1
  /**
   * Draw underline
   *
   * @param canvas The canvas
   */
  private void drawUnderline(Canvas canvas) {
    if (mShowUnderline) {
      View parent = (View) getParent();
      if (parent != null && (parent.getPaddingLeft() != 0 || parent.getPaddingRight() != 0)) {
        final int pPaddingLeft = parent.getPaddingLeft();
        final int pPaddingRight = parent.getPaddingRight();

        canvas.save();

        // allow drawing out of bounds
        Rect clipBounds = canvas.getClipBounds();
        clipBounds.inset(-(pPaddingLeft + pPaddingRight), 0);
        canvas.clipRect(clipBounds, Region.Op.REPLACE);

        if (mUnderlineGravity == UnderlineGravity.TOP) {
          // If on top ignore bottom padding
          canvas.drawRect(
              -pPaddingLeft,
              mUnderlinePaddingTop,
              getWidth() + pPaddingLeft + pPaddingRight,
              mUnderlineHeight + mUnderlinePaddingTop,
              mUnderlinePaint);
        } else {
          // If on bottom ignore top padding
          canvas.drawRect(
              -pPaddingLeft,
              getHeight() - mUnderlineHeight - mUnderlinePaddingBottom,
              getWidth() + pPaddingLeft + pPaddingRight,
              getHeight() - mUnderlinePaddingBottom,
              mUnderlinePaint);
        }

        canvas.restore();
      } else {
        if (mUnderlineGravity == UnderlineGravity.TOP) {
          // If on top ignore bottom padding
          canvas.drawRect(
              0,
              mUnderlinePaddingTop,
              getWidth(),
              mUnderlineHeight + mUnderlinePaddingTop,
              mUnderlinePaint);
        } else {
          // If on bottom ignore top padding
          canvas.drawRect(
              0,
              getHeight() - mUnderlineHeight - mUnderlinePaddingBottom,
              getWidth(),
              getHeight() - mUnderlinePaddingBottom,
              mUnderlinePaint);
        }
      }
    }
  }
  private void updateThumbPos(int posX) {
    int thumbWidth = mThumb.getIntrinsicWidth();
    int halfThumb = thumbWidth / 2;
    int start;
    if (isRtl()) {
      start = getWidth() - getPaddingRight() - mAddedTouchBounds;
      posX = start - posX - thumbWidth;
    } else {
      start = getPaddingLeft() + mAddedTouchBounds;
      posX = start + posX;
    }
    mThumb.copyBounds(mInvalidateRect);
    mThumb.setBounds(posX, mInvalidateRect.top, posX + thumbWidth, mInvalidateRect.bottom);
    if (isRtl()) {
      mScrubber.getBounds().right = start - halfThumb;
      mScrubber.getBounds().left = posX + halfThumb;
    } else {
      mScrubber.getBounds().left = start + halfThumb;
      mScrubber.getBounds().right = posX + halfThumb;
    }
    final Rect finalBounds = mTempRect;
    mThumb.copyBounds(finalBounds);
    if (!isInEditMode()) {
      mIndicator.move(finalBounds.centerX());
    }

    mInvalidateRect.inset(-mAddedTouchBounds, -mAddedTouchBounds);
    finalBounds.inset(-mAddedTouchBounds, -mAddedTouchBounds);
    mInvalidateRect.union(finalBounds);
    SeekBarCompat.setHotspotBounds(
        mRipple, finalBounds.left, finalBounds.top, finalBounds.right, finalBounds.bottom);
    invalidate(mInvalidateRect);
  }
 private boolean startDragging(MotionEvent ev, boolean ignoreTrackIfInScrollContainer) {
   final Rect bounds = mTempRect;
   mThumb.copyBounds(bounds);
   // Grow the current thumb rect for a bigger touch area
   bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds);
   mIsDragging = (bounds.contains((int) ev.getX(), (int) ev.getY()));
   if (!mIsDragging && mAllowTrackClick && !ignoreTrackIfInScrollContainer) {
     // If the user clicked outside the thumb, we compute the current position
     // and force an immediate drag to it.
     mIsDragging = true;
     mDragOffset = (bounds.width() / 2) - mAddedTouchBounds;
     updateDragging(ev);
     // As the thumb may have moved, get the bounds again
     mThumb.copyBounds(bounds);
     bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds);
   }
   if (mIsDragging) {
     setPressed(true);
     attemptClaimDrag();
     setHotspot(ev.getX(), ev.getY());
     mDragOffset = (int) (ev.getX() - bounds.left - mAddedTouchBounds);
     if (mPublicChangeListener != null) {
       mPublicChangeListener.onStartTrackingTouch(this);
     }
   }
   return mIsDragging;
 }
  @Override
  public void draw(@NonNull final Canvas canvas) {
    super.draw(canvas);

    // Only recalculate the close bounds if they are dirty
    if (mCloseBoundChanged) {
      mCloseBoundChanged = false;

      mClosableLayoutRect.set(0, 0, getWidth(), getHeight());
      // Create the bounds for our close regions.
      applyCloseRegionBounds(mClosePosition, mClosableLayoutRect, mCloseRegionBounds);

      // The inset rect applies padding around the visible closeButton.
      mInsetCloseRegionBounds.set(mCloseRegionBounds);
      mInsetCloseRegionBounds.inset(mCloseButtonPadding, mCloseButtonPadding);
      // The close button sits inside the close region with padding and gravity
      // in the same way the close region sits inside the whole ClosableLayout
      applyCloseButtonBounds(mClosePosition, mInsetCloseRegionBounds, mCloseButtonBounds);
      mCloseDrawable.setBounds(mCloseButtonBounds);
    }

    // Draw last so that this gets drawn as the top layer. This is also why we override
    // draw instead of onDraw.
    if (mCloseDrawable.isVisible()) {
      mCloseDrawable.draw(canvas);
    }
  }
예제 #5
0
  private Bitmap extentSnapshot(int doc, int gs, int spaceAround, boolean transparent) {
    final LogHelper log = new LogHelper();
    final Rect extent = getDisplayExtent();

    if (!extent.isEmpty()) {
      extent.inset(-spaceAround, -spaceAround);
      extent.intersect(0, 0, mView.getView().getWidth(), mView.getView().getHeight());
    }
    if (extent.isEmpty()) {
      return null;
    }

    final Bitmap viewBitmap = mView.snapshot(doc, gs, transparent);
    if (viewBitmap == null) {
      return null;
    }

    if (extent.width() == mView.getView().getWidth()
        && extent.height() == mView.getView().getHeight()) {
      log.r(viewBitmap.getByteCount());
      return viewBitmap;
    }

    final Bitmap realBitmap =
        Bitmap.createBitmap(viewBitmap, extent.left, extent.top, extent.width(), extent.height());

    viewBitmap.recycle();
    log.r(realBitmap.getByteCount());
    return realBitmap;
  }
  private void init() {
    if (mPaint == null) {
      mPaint = new Paint();
      mPaint.setColor(Color.WHITE);
      mPaint.setAntiAlias(true);
      mPaint.setStyle(Paint.Style.FILL);
    }

    int count = (mPoints - 1) * 4;
    posX = new float[count];
    posY = new float[count];

    Rect bounds = new Rect();
    bounds.set(getBounds());
    bounds.inset(mPadding, mPadding);

    // circumference
    float circ = (float) (Math.PI * (float) Math.min(bounds.width(), bounds.height()));
    float arcLength = circ / count;

    mSize = (float) ((arcLength) / (2 * Math.PI));

    double degrees = Math.toRadians((float) 360 / (float) count);
    for (int i = 0; i < count; i++) {
      posX[i] = (float) (bounds.exactCenterX() - (bounds.width() / 2) * Math.sin(degrees * i));
      posY[i] = (float) (bounds.exactCenterY() + (bounds.height() / 2) * Math.cos(degrees * i));
    }
  }
예제 #7
0
  private void drawBlurBackground(Canvas canvas) {
    if (mBlurredView != null) {
      if (prepare()) {
        if (mBlurredBackgroundColor != 0) {
          mBitmapToBlur.eraseColor(mBlurredBackgroundColor);
        }
        mBlurredView.draw(mBlurringCanvas);
        blur();

        NiceTabLayout tabLayout = (NiceTabLayout) getParent();

        if (tabLayout != null) {
          final int pPaddingLeft = tabLayout.getPaddingLeft();
          final int pPaddingRight = tabLayout.getPaddingRight();

          canvas.save();

          if (tabLayout.getPaddingLeft() != 0 || tabLayout.getPaddingRight() != 0) {
            // allow drawing out of bounds
            Rect clipBounds = canvas.getClipBounds();
            clipBounds.inset(-(pPaddingLeft + pPaddingRight), 0);
            canvas.clipRect(clipBounds, Region.Op.REPLACE);
          }

          canvas.translate(
              mBlurredView.getLeft() - getLeft() + tabLayout.getScrollX(),
              mBlurredView.getTop() - getTop());
          canvas.scale(mDownSampleFactor, mDownSampleFactor);
          canvas.drawBitmap(mBlurredBitmap, 0, 0, null);
          canvas.drawColor(mOverlayColor);
          canvas.restore();
        }
      }
    }
  }
예제 #8
0
  private void computeGlyphPath() {
    drawableArea.set(getBounds());
    drawableArea.inset(padding, padding);
    glyphPaint.getTextPath(glyph, 0, 1, 0, 0, glyphPath);
    // Add an extra path point to fix the icon remaining blank on a Galaxy Note 2 running 4.1.2.
    glyphPath.computeBounds(glyphPathBounds, false);
    final float centerX = glyphPathBounds.centerX();
    final float centerY = glyphPathBounds.centerY();
    glyphPath.moveTo(centerX, centerY);
    glyphPath.lineTo(centerX + 0.001f, centerY + 0.001f);
    final float areaWidthF = (float) drawableArea.width();
    final float areaHeightF = (float) drawableArea.height();
    final float scaleX = areaWidthF / glyphPathBounds.width();
    final float scaleY = areaHeightF / glyphPathBounds.height();
    final float scaleFactor = Math.min(scaleX, scaleY);
    glyphPathTransform.setScale(scaleFactor, scaleFactor);
    glyphPath.transform(glyphPathTransform);

    // TODO this two pass calculation irks me.
    // It has to be possible to push this into a single Matrix transform; what makes it hard is
    // that the origin of Text is not top-left, but baseline-left so need to account for that.
    glyphPath.computeBounds(glyphPathBounds, false);
    final float areaLeftF = (float) drawableArea.left;
    final float areaTopF = (float) drawableArea.top;
    float transX = areaLeftF - glyphPathBounds.left;
    transX += 0.5f * Math.abs(areaWidthF - glyphPathBounds.width());
    float transY = areaTopF - glyphPathBounds.top;
    transY += 0.5f * Math.abs(areaHeightF - glyphPathBounds.height());
    glyphPath.offset(transX, transY);

    invalidateSelf();
  }
예제 #9
0
 @Override
 public int getSize(
     Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
   paint.getTextBounds(mText, 0, mText.length(), mRect);
   mRect.inset(-1, -1);
   return (int) (paint.measureText(mText) + 0.5);
 }
예제 #10
0
  void updateDstRect() {
    if (mApplyGravity) {
      if (mIsCircular) {
        final int minDimen = Math.min(mBitmapWidth, mBitmapHeight);
        gravityCompatApply(mGravity, minDimen, minDimen, getBounds(), mDstRect);

        // inset the drawing rectangle to the largest contained square,
        // so that a circle will be drawn
        final int minDrawDimen = Math.min(mDstRect.width(), mDstRect.height());
        final int insetX = Math.max(0, (mDstRect.width() - minDrawDimen) / 2);
        final int insetY = Math.max(0, (mDstRect.height() - minDrawDimen) / 2);
        mDstRect.inset(insetX, insetY);
        mCornerRadius = 0.5f * minDrawDimen;
      } else {
        gravityCompatApply(mGravity, mBitmapWidth, mBitmapHeight, getBounds(), mDstRect);
      }
      mDstRectF.set(mDstRect);

      if (mBitmapShader != null) {
        // setup shader matrix
        mShaderMatrix.setTranslate(mDstRectF.left, mDstRectF.top);
        mShaderMatrix.preScale(
            mDstRectF.width() / mBitmap.getWidth(), mDstRectF.height() / mBitmap.getHeight());
        mBitmapShader.setLocalMatrix(mShaderMatrix);
        mPaint.setShader(mBitmapShader);
      }

      mApplyGravity = false;
    }
  }
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    if (mScrollDisabled) return true;

    View v = mChildViews.get(mCurrent);
    if (v != null) {
      Rect bounds = getScrollBounds(v);
      switch (directionOfTravel(velocityX, velocityY)) {
        case MOVING_LEFT:
          if (bounds.left >= 0) {
            // Fling off to the left bring next view onto screen
            View vl = mChildViews.get(mCurrent + 1);

            if (vl != null) {
              slideViewOntoScreen(vl);
              return true;
            }
          }
          break;
        case MOVING_RIGHT:
          if (bounds.right <= 0) {
            // Fling off to the right bring previous view onto screen
            View vr = mChildViews.get(mCurrent - 1);

            if (vr != null) {
              slideViewOntoScreen(vr);
              return true;
            }
          }
          break;
      }
      mScrollerLastX = mScrollerLastY = 0;
      // If the page has been dragged out of bounds then we want to spring back
      // nicely. fling jumps back into bounds instantly, so we don't want to use
      // fling in that case. On the other hand, we don't want to forgo a fling
      // just because of a slightly off-angle drag taking us out of bounds other
      // than in the direction of the drag, so we test for out of bounds only
      // in the direction of travel.
      //
      // Also don't fling if out of bounds in any direction by more than fling
      // margin
      Rect expandedBounds = new Rect(bounds);
      expandedBounds.inset(-FLING_MARGIN, -FLING_MARGIN);

      if (withinBoundsInDirectionOfTravel(bounds, velocityX, velocityY)
          && expandedBounds.contains(0, 0)) {
        mScroller.fling(
            0,
            0,
            (int) velocityX,
            (int) velocityY,
            bounds.left,
            bounds.right,
            bounds.top,
            bounds.bottom);
        post(this);
      }
    }

    return true;
  }
 @Override
 protected void onBoundsChange(Rect bounds) {
   mIcon.setBounds(bounds);
   if (mBgDrawable != null) {
     sTempRect.set(bounds);
     sTempRect.inset(-mRingOutset, -mRingOutset);
     mBgDrawable.setBounds(sTempRect);
   }
   mIndicatorRectDirty = true;
 }
 void b(float paramFloat1, float paramFloat2)
 {
   Rect localRect = new Rect(this.d);
   this.e.offset(paramFloat1, paramFloat2);
   this.e.offset(Math.max(0.0F, this.i.left - this.e.left), Math.max(0.0F, this.i.top - this.e.top));
   this.e.offset(Math.min(0.0F, this.i.right - this.e.right), Math.min(0.0F, this.i.bottom - this.e.bottom));
   this.d = e();
   localRect.union(this.d);
   localRect.inset(-10, -10);
   this.a.invalidate(localRect);
 }
예제 #14
0
  /**
   * Adds padding to the given size rectangle
   *
   * @param size The size where the padding should be added to
   * @return The size with the padding
   */
  protected Rect sizeAddPadding(Rect size) {
    // Copy the rectangle
    Rect out = new Rect(size);

    // Add the padding
    out.inset(-(int) (Expression.lineWidth * 2.5), -(int) (Expression.lineWidth * 2.5));
    out.offsetTo(0, 0);

    // Return the result
    return out;
  }
예제 #15
0
  protected void inflateData(
      int LineNumber,
      int Margin,
      int Width,
      int Height,
      float MinLengthPercentage,
      float MinAngle) {
    Rect bounds = new Rect(0, 0, Width, Height);

    bounds.inset(Margin, Margin);

    inflateData(LineNumber, MinLengthPercentage, MinAngle, bounds);
  }
 private void updateBounds(Rect bounds) {
   if (bounds == null) {
     bounds = getBounds();
   }
   mBoundsF.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
   mBoundsI.set(bounds);
   if (mInsetForPadding) {
     float vInset = calculateVerticalPadding(mPadding, mRadius, mInsetForRadius);
     float hInset = calculateHorizontalPadding(mPadding, mRadius, mInsetForRadius);
     mBoundsI.inset((int) Math.ceil(hInset), (int) Math.ceil(vInset));
     // to make sure they have same bounds.
     mBoundsF.set(mBoundsI);
   }
 }
예제 #17
0
 private void updateLayoutMatrix() {
   synchronized (updateLayoutLock) {
     if (!updateLayoutProperties) {
       return;
     }
     // Initialize to maximum allowed area. Round to integer coordinates inwards the layout
     // bounding box (ceil left/top and floor right/bottom) to not break constraints.
     displayLayout.set(
         (screenWidth * layoutInPercentage.left + 99) / 100,
         (screenHeight * layoutInPercentage.top + 99) / 100,
         (screenWidth * layoutInPercentage.right) / 100,
         (screenHeight * layoutInPercentage.bottom) / 100);
     Logging.d(
         TAG,
         "ID: "
             + id
             + ". AdjustTextureCoords. Allowed display size: "
             + displayLayout.width()
             + " x "
             + displayLayout.height()
             + ". Video: "
             + videoWidth
             + " x "
             + videoHeight
             + ". Rotation: "
             + rotationDegree
             + ". Mirror: "
             + mirror);
     final float videoAspectRatio =
         (rotationDegree % 180 == 0)
             ? (float) videoWidth / videoHeight
             : (float) videoHeight / videoWidth;
     // Adjust display size based on |scalingType|.
     final Point displaySize =
         RendererCommon.getDisplaySize(
             scalingType, videoAspectRatio, displayLayout.width(), displayLayout.height());
     displayLayout.inset(
         (displayLayout.width() - displaySize.x) / 2,
         (displayLayout.height() - displaySize.y) / 2);
     Logging.d(
         TAG,
         "  Adjusted display size: " + displayLayout.width() + " x " + displayLayout.height());
     layoutMatrix =
         RendererCommon.getLayoutMatrix(
             mirror, videoAspectRatio, (float) displayLayout.width() / displayLayout.height());
     updateLayoutProperties = false;
     Logging.d(TAG, "  AdjustTextureCoords done");
   }
 }
예제 #18
0
  // Grows the cropping rectange by (dx, dy) in image space.
  void moveBy(float dx, float dy) {
    Rect invalRect = new Rect(mDrawRect);

    mCropRect.offset(dx, dy);

    // Put the cropping rectangle inside image rectangle.
    mCropRect.offset(
        Math.max(0, mImageRect.left - mCropRect.left), Math.max(0, mImageRect.top - mCropRect.top));

    mCropRect.offset(
        Math.min(0, mImageRect.right - mCropRect.right),
        Math.min(0, mImageRect.bottom - mCropRect.bottom));

    mDrawRect = computeLayout();
    invalRect.union(mDrawRect);
    invalRect.inset(-10, -10);
    mContext.invalidate(invalRect);
  }
  // Grows the cropping rectangle by (dx, dy) in image space
  void moveBy(float dx, float dy) {
    Rect invalRect = new Rect(drawRect);

    cropRect.offset(dx, dy);

    // Put the cropping rectangle inside image rectangle
    cropRect.offset(
        Math.max(0, imageRect.left - cropRect.left), Math.max(0, imageRect.top - cropRect.top));

    cropRect.offset(
        Math.min(0, imageRect.right - cropRect.right),
        Math.min(0, imageRect.bottom - cropRect.bottom));

    drawRect = computeLayout();
    invalRect.union(drawRect);
    invalRect.inset(-(int) handleRadius, -(int) handleRadius);
    viewContext.invalidate(invalRect);
  }
      /** NOTE: This has to be called within a surface transaction. */
      public void drawIfNeeded() {
        synchronized (mWindowManagerService.mWindowMap) {
          if (!mInvalidated) {
            return;
          }
          mInvalidated = false;
          Canvas canvas = null;
          try {
            // Empty dirty rectangle means unspecified.
            if (mDirtyRect.isEmpty()) {
              mBounds.getBounds(mDirtyRect);
            }
            mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
            canvas = mSurface.lockCanvas(mDirtyRect);
            if (DEBUG_VIEWPORT_WINDOW) {
              Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect);
            }
          } catch (IllegalArgumentException iae) {
            /* ignore */
          } catch (Surface.OutOfResourcesException oore) {
            /* ignore */
          }
          if (canvas == null) {
            return;
          }
          if (DEBUG_VIEWPORT_WINDOW) {
            Slog.i(LOG_TAG, "Bounds: " + mBounds);
          }
          canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
          mPaint.setAlpha(mAlpha);
          Path path = mBounds.getBoundaryPath();
          canvas.drawPath(path, mPaint);

          mSurface.unlockCanvasAndPost(canvas);

          if (mAlpha > 0) {
            mSurfaceControl.show();
          } else {
            mSurfaceControl.hide();
          }
        }
      }
  /** Computes the stack and task rects */
  public void computeRects(int windowWidth, int windowHeight, Rect taskStackBounds) {
    // Compute the stack rects
    mViewRect.set(0, 0, windowWidth, windowHeight);
    mStackRect.set(taskStackBounds);
    mStackVisibleRect.set(taskStackBounds);
    mStackVisibleRect.bottom = mViewRect.bottom;

    int widthPadding = (int) (mConfig.taskStackWidthPaddingPct * mStackRect.width());
    int heightPadding = mConfig.taskStackTopPaddingPx;
    mStackRect.inset(widthPadding, heightPadding);

    // Compute the task rect
    int size = mStackRect.width();
    int left = mStackRect.left + (mStackRect.width() - size) / 2;
    mTaskRect.set(left, mStackRect.top, left + size, mStackRect.top + size);

    // Update the affiliation offsets
    float visibleTaskPct = 0.5f;
    mWithinAffiliationOffset = mConfig.taskBarHeight;
    mBetweenAffiliationOffset = (int) (visibleTaskPct * mTaskRect.height());
  }
예제 #22
0
  @Override
  public void draw(Canvas canvas) {
    // Draw the bounding boxes
    drawBoundingBoxes(canvas);

    // Get the bounding box
    final Rect operator = getOperatorBoundingBoxes()[0];

    // Draw the operator
    operator.inset(operator.width() / 10, operator.height() / 10); // Padding
    canvas.save();
    canvas.translate(operator.left, operator.top);
    operatorPaint.setStrokeWidth(lineWidth);
    operatorPaint.setColor(this.getColor());
    canvas.drawLine(
        0, operator.height() / 2, operator.width(), operator.height() / 2, operatorPaint);
    canvas.drawLine(
        operator.width() / 2, 0, operator.width() / 2, operator.height(), operatorPaint);
    canvas.restore();

    // Draw the children
    drawChildren(canvas);
  }
  @Override
  public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) {
    super.draw(canvas, mapView, shadow);

    // go through all OverlayItems and draw title for each of them
    for (OverlayItem item : mOverlays) {
      /* Converts latitude & longitude of this overlay item to coordinates on screen.
       * As we have called boundCenterBottom() in constructor, so these coordinates
       * will be of the bottom center position of the displayed marker.
       */
      GeoPoint point = item.getPoint();
      Point markerBottomCenterCoords = new Point();
      mapView.getProjection().toPixels(point, markerBottomCenterCoords);

      /* Find the width and height of the title*/
      TextPaint paintText = new TextPaint();
      Paint paintRect = new Paint();

      Rect rect = new Rect();
      paintText.setTextSize(FONT_SIZE);
      paintText.getTextBounds(item.getTitle(), 0, item.getTitle().length(), rect);

      rect.inset(-TITLE_MARGIN, -TITLE_MARGIN);
      rect.offsetTo(
          markerBottomCenterCoords.x - rect.width() / 2,
          markerBottomCenterCoords.y - markerHeight - rect.height());

      paintText.setTextAlign(Paint.Align.CENTER);
      paintText.setTextSize(FONT_SIZE);
      paintText.setARGB(255, 255, 255, 255);
      paintRect.setARGB(130, 0, 0, 0);

      canvas.drawRoundRect(new RectF(rect), 2, 2, paintRect);
      canvas.drawText(
          item.getTitle(), rect.left + rect.width() / 2, rect.bottom - TITLE_MARGIN, paintText);
    }
  }
  /*
   * Use to signal that there's a portion of this view that wants to be
   * visible to the user on the screen. This method will place the sub
   * view on the screen, and will also place as much of this view as possible
   * on the screen. If this view is smaller than the viewable area available, it
   * will be fully visible in addition to the subview.
   */
  private void requestChildViewOnScreen(View child) {
    // Take focus so the user can be prepared to interact with this question, since
    // they will need to be fixing the input
    acceptFocus();

    // Get the rectangle that wants to put itself on the screen
    Rect vitalPortion = new Rect();
    child.getDrawingRect(vitalPortion);

    // Save a reference to it in case we have to manipulate it later.
    Rect vitalPortionSaved = new Rect();
    child.getDrawingRect(vitalPortionSaved);

    // Then get the bounding rectangle for this whole view.
    Rect wholeView = new Rect();
    this.getDrawingRect(wholeView);

    // If we don't know enough about the screen, just default to asking to see the
    // subview that was requested.
    if (mFrameHeight == -1) {
      child.requestRectangleOnScreen(vitalPortion);
      return;
    }

    // If the whole view fits, just request that we display the whole thing.
    if (wholeView.height() < mFrameHeight) {
      this.requestRectangleOnScreen(wholeView);
      return;
    }

    // The whole view will not fit, we need to scale down our requested focus.
    // Trying to construct the "ideal" rectangle here is actually pretty hard
    // but the base case is just to see if we can get the view onto the screen from
    // the bottom or the top

    int topY = wholeView.top;
    int bottomY = wholeView.bottom;

    // shrink the view to contain only the current frame size.
    wholeView.inset(0, (wholeView.height() - mFrameHeight) / 2);
    wholeView.offsetTo(wholeView.left, topY);

    // The view is now the size of the frame and anchored back at the top.

    // Now let's contextualize where the child view actually is in this frame.
    this.offsetDescendantRectToMyCoords(child, vitalPortion);

    // If the newly transformed view now contains the child portion, we're good
    if (wholeView.contains(vitalPortion)) {
      this.requestRectangleOnScreen(wholeView);
      return;
    }

    // otherwise, move to the requested frame to be at the bottom of this view
    wholeView.offsetTo(wholeView.left, bottomY - wholeView.height());

    // now see if the transformed view contains the vital portion
    if (wholeView.contains(vitalPortion)) {
      this.requestRectangleOnScreen(wholeView);
      return;
    }

    // Otherwise the child is hidden in the frame, so it won't matter which
    // we choose.
    child.requestRectangleOnScreen(vitalPortionSaved);
  }
  private void onSaveClicked() {
    // TODO this code needs to change to use the decode/crop/encode single
    // step api so that we don't require that the whole (possibly large)
    // bitmap doesn't have to be read into memory
    if (mCrop == null) {
      return;
    }

    if (mSaving) return;
    mSaving = true;

    Bitmap croppedImage;

    // If the output is required to a specific size, create an new image
    // with the cropped image in the center and the extra space filled.
    if (mOutputX != 0 && mOutputY != 0 && !mScale) {
      // Don't scale the image but instead fill it so it's the
      // required dimension
      croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, Bitmap.Config.RGB_565);
      Canvas canvas = new Canvas(croppedImage);

      Rect srcRect = mCrop.getCropRect();
      Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);

      int dx = (srcRect.width() - dstRect.width()) / 2;
      int dy = (srcRect.height() - dstRect.height()) / 2;

      // If the srcRect is too big, use the center part of it.
      srcRect.inset(Math.max(0, dx), Math.max(0, dy));

      // If the dstRect is too big, use the center part of it.
      dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

      // Draw the cropped bitmap in the center
      canvas.drawBitmap(mBitmap, srcRect, dstRect, null);

      // Release bitmap memory as soon as possible
      mImageView.clear();
      mBitmap.recycle();
    } else {
      Rect r = mCrop.getCropRect();

      int width = r.width();
      int height = r.height();

      // If we are circle cropping, we want alpha channel, which is the
      // third param here.
      croppedImage =
          Bitmap.createBitmap(
              width, height, mCircleCrop ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);

      Canvas canvas = new Canvas(croppedImage);
      Rect dstRect = new Rect(0, 0, width, height);
      canvas.drawBitmap(mBitmap, r, dstRect, null);

      // Release bitmap memory as soon as possible
      mImageView.clear();
      mBitmap.recycle();

      if (mCircleCrop) {
        // OK, so what's all this about?
        // Bitmaps are inherently rectangular but we want to return
        // something that's basically a circle.  So we fill in the
        // area around the circle with alpha.  Note the all important
        // PortDuff.Mode.CLEAR.
        Canvas c = new Canvas(croppedImage);
        Path p = new Path();
        p.addCircle(width / 2F, height / 2F, width / 2F, Path.Direction.CW);
        c.clipPath(p, Region.Op.DIFFERENCE);
        c.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
      }

      // If the required dimension is specified, scale the image.
      if (mOutputX != 0 && mOutputY != 0 && mScale) {
        croppedImage =
            Util.transform(
                new Matrix(), croppedImage, mOutputX, mOutputY, mScaleUp, Util.RECYCLE_INPUT);
      }
    }

    mImageView.setImageBitmapResetBase(croppedImage, true);
    mImageView.center(true, true);
    mImageView.mHighlightViews.clear();

    // Return the cropped image directly or save it to the specified URI.
    Bundle myExtras = getIntent().getExtras();
    if (myExtras != null
        && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
      Bundle extras = new Bundle();
      extras.putParcelable("data", croppedImage);
      setResult(RESULT_OK, (new Intent()).setAction("inline-data").putExtras(extras));
      finish();
    } else {
      final Bitmap b = croppedImage;
      final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage;
      Util.startBackgroundJob(
          this,
          this,
          null,
          getResources().getString(msdId),
          new Runnable() {
            public void run() {
              saveOutput(b);
            }
          },
          mHandler);
    }
  }
예제 #26
0
  private void onSaveClicked() throws Exception {
    // TODO this code needs to change to use the decode/crop/encode single
    // step api so that we don't require that the whole (possibly large)
    // bitmap doesn't have to be read into memory
    if (mSaving) return;

    if (mCrop == null) {

      return;
    }

    mSaving = true;

    Rect r = mCrop.getCropRect();

    int width = r.width();
    int height = r.height();

    // If we are circle cropping, we want alpha channel, which is the
    // third param here.
    Bitmap croppedImage;
    try {

      croppedImage =
          Bitmap.createBitmap(
              width, height, mCircleCrop ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
    } catch (Exception e) {
      throw e;
    }
    if (croppedImage == null) {

      return;
    }

    {
      Canvas canvas = new Canvas(croppedImage);
      Rect dstRect = new Rect(0, 0, width, height);
      canvas.drawBitmap(mBitmap, r, dstRect, null);
    }

    if (mCircleCrop) {

      // OK, so what's all this about?
      // Bitmaps are inherently rectangular but we want to return
      // something that's basically a circle.  So we fill in the
      // area around the circle with alpha.  Note the all important
      // PortDuff.Mode.CLEAR.
      Canvas c = new Canvas(croppedImage);
      Path p = new Path();
      p.addCircle(width / 2F, height / 2F, width / 2F, Path.Direction.CW);
      c.clipPath(p, Region.Op.DIFFERENCE);
      c.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
    }

    /* If the output is required to a specific size then scale or fill */
    if (mOutputX != 0 && mOutputY != 0) {

      if (mScale) {

        /* Scale the image to the required dimensions */
        Bitmap old = croppedImage;
        croppedImage = Util.transform(new Matrix(), croppedImage, mOutputX, mOutputY, mScaleUp);
        if (old != croppedImage) {

          old.recycle();
        }
      } else {

        /* Don't scale the image crop it to the size requested.
         * Create an new image with the cropped image in the center and
         * the extra space filled.
         */

        // Don't scale the image but instead fill it so it's the
        // required dimension
        Bitmap b = Bitmap.createBitmap(mOutputX, mOutputY, Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(b);

        Rect srcRect = mCrop.getCropRect();
        Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);

        int dx = (srcRect.width() - dstRect.width()) / 2;
        int dy = (srcRect.height() - dstRect.height()) / 2;

        /* If the srcRect is too big, use the center part of it. */
        srcRect.inset(Math.max(0, dx), Math.max(0, dy));

        /* If the dstRect is too big, use the center part of it. */
        dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

        /* Draw the cropped bitmap in the center */
        canvas.drawBitmap(mBitmap, srcRect, dstRect, null);

        /* Set the cropped bitmap as the new bitmap */
        croppedImage.recycle();
        croppedImage = b;
      }
    }

    // Return the cropped image directly or save it to the specified URI.
    Bundle myExtras = getIntent().getExtras();
    if (myExtras != null
        && (myExtras.getParcelable("data") != null || myExtras.getBoolean(RETURN_DATA))) {

      Bundle extras = new Bundle();
      extras.putParcelable(RETURN_DATA_AS_BITMAP, croppedImage);
      setResult(RESULT_OK, (new Intent()).setAction(ACTION_INLINE_DATA).putExtras(extras));
      finish();
    } else {
      final Bitmap b = croppedImage;
      Util.startBackgroundJob(
          this,
          null,
          getString(R.string.saving_image),
          new Runnable() {
            public void run() {

              saveOutput(b);
            }
          },
          mHandler);
    }
  }
예제 #27
0
  @Override
  public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) {
    super.draw(canvas, mapView, shadow);

    Paint mPaint = new Paint();
    mPaint.setDither(true);
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(2);

    List<Clue> clues = huntedService.getDataProvider().getTrackLog();

    Clue prevClue = null;
    for (Clue clue : clues) {
      if (prevClue != null) {
        GeoPoint prevCluePoint = Map.getPointForClue(prevClue);
        GeoPoint currentCluePoint = Map.getPointForClue(clue);
        Point fromPoint = new Point();
        mapView.getProjection().toPixels(prevCluePoint, fromPoint);
        Point toPoint = new Point();
        mapView.getProjection().toPixels(currentCluePoint, toPoint);
        canvas.drawLine(fromPoint.x, fromPoint.y, toPoint.x, toPoint.y, mPaint);
      }

      prevClue = clue;
    }

    // go through all OverlayItems and draw title for each of them
    List<OverlayItem> overlaysCopy = new ArrayList<OverlayItem>(overlays);
    for (OverlayItem item : overlaysCopy) {
      /* Converts latitude & longitude of this overlay item to coordinates on screen.
       * As we have called boundCenterBottom() in constructor, so these coordinates
       * will be of the bottom center position of the displayed marker.
       */
      GeoPoint point = item.getPoint();
      Point markerBottomCenterCoords = new Point();
      mapView.getProjection().toPixels(point, markerBottomCenterCoords);

      /* Find the width and height of the title*/
      TextPaint paintText = new TextPaint();
      Paint paintRect = new Paint();

      Rect rect = new Rect();
      paintText.setTextSize(FONT_SIZE);
      paintText.getTextBounds(item.getTitle(), 0, item.getTitle().length(), rect);

      rect.inset(-TITLE_MARGIN, -TITLE_MARGIN);
      rect.offsetTo(
          markerBottomCenterCoords.x - rect.width() / 2,
          markerBottomCenterCoords.y - 15 - rect.height());

      paintText.setTextAlign(Paint.Align.CENTER);
      paintText.setTextSize(FONT_SIZE);
      paintText.setARGB(255, 255, 255, 255);
      paintRect.setARGB(130, 0, 0, 0);

      canvas.drawRoundRect(new RectF(rect), 2, 2, paintRect);
      canvas.drawText(
          item.getTitle(), rect.left + rect.width() / 2, rect.bottom - TITLE_MARGIN, paintText);
    }
  }
예제 #28
0
  private void onSaveClicked() {
    if (!mNeedCrop) {
      Bitmap nocropBitmap = createNoCropBitmap();
      mImageView.clear();
      if (nocropBitmap != mBitmap) {
        mBitmap.recycle();
        mBitmap = null;
      }
      if (null != nocropBitmap) {
        // Return the cropped image directly or save it to the specified
        // URI.
        Bundle myExtras = getIntent().getExtras();
        if (myExtras != null
            && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
          Bundle extras = new Bundle();
          extras.putParcelable("data", nocropBitmap);
          setResult(
              RESULT_OK,
              (new Intent()).setAction(ICustomAction.ACTION_INLINE_DATA).putExtras(extras));
          finish();
        } else {
          final Bitmap b = nocropBitmap;
          final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage;
          Util.startBackgroundJob(
              this,
              null,
              getResources().getString(msdId),
              new Runnable() {
                @Override
                public void run() {
                  saveOutput(b);
                }
              },
              mHandler);
        }
      } else {
        setResult(RESULT_CANCELED);
        finish();
      }
      return;
    }
    // TODO this code needs to change to use the decode/crop/encode single
    // step api so that we don't require that the whole (possibly large)
    // bitmap doesn't have to be read into memory
    if (mCrop == null) {
      return;
    }

    if (mSaving) {
      return;
    }
    mSaving = true;

    Bitmap croppedImage = null;
    Bitmap.Config bmpConfig = mHasApha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.ARGB_8888;

    // If the output is required to a specific size, create an new image
    // with the cropped image in the center and the extra space filled.
    if (mOutputX != 0 && mOutputY != 0 && !mScale) {
      // Don't scale the image but instead fill it so it's the
      // required dimension
      try {
        croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, bmpConfig);
      } catch (OutOfMemoryError e) {
        // 创建失败
        e.printStackTrace();
        OutOfMemoryHandler.handle();
        Toast.makeText(this, getString(R.string.err_out_of_memory), Toast.LENGTH_SHORT);
        // Release bitmap memory as soon as possible
        mImageView.clear();
        mBitmap.recycle();
        mBitmap = null;

        setResult(RESULT_CANCELED);
        finish();
        return;
      }

      Canvas canvas = new Canvas(croppedImage);
      Rect srcRect = mCrop.getCropRect();
      Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);

      int dx = (srcRect.width() - dstRect.width()) / 2;
      int dy = (srcRect.height() - dstRect.height()) / 2;

      // If the srcRect is too big, use the center part of it.
      srcRect.inset(Math.max(0, dx), Math.max(0, dy));

      // If the dstRect is too big, use the center part of it.
      dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

      // Draw the cropped bitmap in the center
      canvas.drawBitmap(mBitmap, srcRect, dstRect, null);

      // Release bitmap memory as soon as possible
      mImageView.clear();
      mBitmap.recycle();
    } else {
      Rect r = mCrop.getCropRect();

      // int width = r.width();
      // int height = r.height();

      // If we are circle cropping, we want alpha channel, which is the
      // third param here.
      try {
        croppedImage = Bitmap.createBitmap(mOutputX, mOutputY, bmpConfig);
      } catch (OutOfMemoryError e) {
        e.printStackTrace();
        OutOfMemoryHandler.handle();
        // 创建失败
        // Toast.makeText(this, getString(R.string.err_out_of_memory),
        // Toast.LENGTH_SHORT).show();
        // Release bitmap memory as soon as possible
        mImageView.clear();
        mBitmap.recycle();

        setResult(RESULT_CANCELED);
        finish();
        return;
      }

      Canvas canvas = new Canvas(croppedImage);
      canvas.setDrawFilter(
          new PaintFlagsDrawFilter(
              0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); // 在有缩放的情况下需要提高绘图质量
      Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);
      canvas.drawBitmap(mBitmap, r, dstRect, null);

      // Release bitmap memory as soon as possible
      mImageView.clear();
      mBitmap.recycle();

      // if (mCircleCrop) {
      // // OK, so what's all this about?
      // // Bitmaps are inherently rectangular but we want to return
      // // something that's basically a circle. So we fill in the
      // // area around the circle with alpha. Note the all important
      // // PortDuff.Mode.CLEAR.
      // Canvas c = new Canvas(croppedImage);
      // Path p = new Path();
      // p.addCircle(width / 2F, height / 2F, width / 2F,
      // Path.Direction.CW);
      // c.clipPath(p, Region.Op.DIFFERENCE);
      // c.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
      // }

      // If the required dimension is specified, scale the image.
      // if (mOutputX != 0 && mOutputY != 0 && mScale) {
      // croppedImage = Util.transform(new Matrix(), croppedImage,
      // mOutputX, mOutputY, mScaleUp, Util.RECYCLE_INPUT);
      // }
    }

    mImageView.setImageBitmapResetBase(croppedImage, true);
    mImageView.center(true, true);
    mImageView.mHighlightViews.clear();

    // Return the cropped image directly or save it to the specified URI.
    Bundle myExtras = getIntent().getExtras();
    if (myExtras != null
        && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
      Bundle extras = new Bundle();
      extras.putParcelable("data", croppedImage);
      setResult(
          RESULT_OK, (new Intent()).setAction(ICustomAction.ACTION_INLINE_DATA).putExtras(extras));
      finish();
    } else {
      final Bitmap b = croppedImage;
      final int msdId = mSetWallpaper ? R.string.wallpaper : R.string.savingImage;
      Util.startBackgroundJob(
          this,
          null,
          getResources().getString(msdId),
          new Runnable() {
            @Override
            public void run() {
              saveOutput(b);
            }
          },
          mHandler);
    }
  }