public SampleView(Context context) { super(context); setFocusable(true); mPath = new Path(); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mRect = new Rect(0, 0, 120, 120); mDrawable = new GradientDrawable( GradientDrawable.Orientation.TL_BR, new int[] {0xFFFF0000, 0xFF00FF00, 0xFF0000FF}); mDrawable.setShape(GradientDrawable.RECTANGLE); mDrawable.setGradientRadius((float) (Math.sqrt(2) * 60)); }
private void drawBrightnessIndicator(Canvas canvas) { // get a representation of the height of the indicator within the bar float brightnessHeight = mNewColor[2] * mWheel.getHeight(); // Log.d(TAG, String.format("Brightness height: %f", brightnessHeight)); // convert the height to an absolute y position based on the bar's position float absoluteY = mWheelPosition.y + mWheel.getHeight() - brightnessHeight; // get the y value "above" the x axis for the x coordinate calculation // note: because of symmetry, the sign doesn't matter so we'll use the positive float heightAboveXAxis = Math.abs(brightnessHeight - (float) mRadius); // Log.d(TAG, String.format("Height above X: %f", heightAboveXAxis)); float leftEdgeRadius = (float) (mRadius + SPACE_BETWEEN_WHEEL_AND_BAR); float rightEdgeRadius = leftEdgeRadius + ARC_WIDTH; // get the x coordinate relative to the center of the wheel float leftXInCircle = (float) Math.sqrt(leftEdgeRadius * leftEdgeRadius - heightAboveXAxis * heightAboveXAxis); float rightXInCircle = (float) Math.sqrt(rightEdgeRadius * rightEdgeRadius - heightAboveXAxis * heightAboveXAxis); // get the absolute x and y coordinates of the left edge of the bar at the bar height float leftX = mWheelCenter.x + leftXInCircle; float rightX = mWheelCenter.x + rightXInCircle; float indicatorHeight = BRIGHTNESS_INDICATOR_SIZE / 2.0f; float indicatorWidth = BRIGHTNESS_INDICATOR_SIZE; Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStrokeWidth(1.0f); Path leftTrianglePath = new Path(); leftTrianglePath.moveTo(leftX, absoluteY - indicatorHeight); leftTrianglePath.lineTo(leftX + indicatorWidth, absoluteY); leftTrianglePath.lineTo(leftX, absoluteY + indicatorHeight); leftTrianglePath.close(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.FILL); canvas.drawPath(leftTrianglePath, paint); paint.setColor(Color.WHITE); paint.setStyle(Paint.Style.STROKE); canvas.drawPath(leftTrianglePath, paint); Path rightTrianglePath = new Path(); rightTrianglePath.moveTo(rightX, absoluteY - indicatorHeight); rightTrianglePath.lineTo(rightX - indicatorWidth, absoluteY); rightTrianglePath.lineTo(rightX, absoluteY + indicatorHeight); rightTrianglePath.close(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.FILL); canvas.drawPath(rightTrianglePath, paint); paint.setColor(Color.WHITE); paint.setStyle(Paint.Style.STROKE); canvas.drawPath(rightTrianglePath, paint); }
@Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); // Logger.d(TAG, "onTouchEvent: " + event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isTouched = true; this.setLayoutParams(newLp); endPoint.x = (int) downX; endPoint.y = (int) downY; changeViewHeight( this, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); postInvalidate(); downX = event.getX() + location[0]; downY = event.getY() + location[1]; // Logger.d(TAG, String.format("downX: %f, downY: %f", downX, downY)); break; case MotionEvent.ACTION_MOVE: // 计算直角边和斜边(用于计算绘制两圆之间的填充去) triangle.deltaX = event.getX() - downX; triangle.deltaY = -1 * (event.getY() - downY); // y轴方向相反,所有需要取反 double distance = Math.sqrt(triangle.deltaX * triangle.deltaX + triangle.deltaY * triangle.deltaY); triangle.hypotenuse = distance; // Logger.d(TAG, "triangle: " + triangle); refreshCurRadiusByMoveDistance((int) distance); endPoint.x = (int) event.getX(); endPoint.y = (int) event.getY(); postInvalidate(); break; case MotionEvent.ACTION_UP: isTouched = false; this.setLayoutParams(originLp); if (isArrivedMaxMoved) { // 触发事件 changeViewHeight(this, originWidth, originHeight); postInvalidate(); if (null != onDraggableFlagViewListener) { onDraggableFlagViewListener.onFlagDismiss(this); } Logger.d(TAG, "触发事件..."); resetAfterDismiss(); } else { // 还原 changeViewHeight(this, originWidth, originHeight); startRollBackAnimation(500 /*ms*/); } downX = Float.MAX_VALUE; downY = Float.MAX_VALUE; break; } return true; }
// Determines which edges are hit by touching at (x, y). public int getHit(float x, float y) { Rect r = computeLayout(); final float hysteresis = 20F; int retval = GROW_NONE; if (mCircle) { float distX = x - r.centerX(); float distY = y - r.centerY(); int distanceFromCenter = (int) Math.sqrt(distX * distX + distY * distY); int radius = mDrawRect.width() / 2; int delta = distanceFromCenter - radius; if (Math.abs(delta) <= hysteresis) { if (Math.abs(distY) > Math.abs(distX)) { if (distY < 0) { retval = GROW_TOP_EDGE; } else { retval = GROW_BOTTOM_EDGE; } } else { if (distX < 0) { retval = GROW_LEFT_EDGE; } else { retval = GROW_RIGHT_EDGE; } } } else if (distanceFromCenter < radius) { retval = MOVE; } else { retval = GROW_NONE; } } else { // verticalCheck makes sure the position is between the top and // the bottom edge (with some tolerance). Similar for horizCheck. boolean verticalCheck = (y >= r.top - hysteresis) && (y < r.bottom + hysteresis); boolean horizCheck = (x >= r.left - hysteresis) && (x < r.right + hysteresis); // Check whether the position is near some edge(s). if ((Math.abs(r.left - x) < hysteresis) && verticalCheck) { retval |= GROW_LEFT_EDGE; } if ((Math.abs(r.right - x) < hysteresis) && verticalCheck) { retval |= GROW_RIGHT_EDGE; } if ((Math.abs(r.top - y) < hysteresis) && horizCheck) { retval |= GROW_TOP_EDGE; } if ((Math.abs(r.bottom - y) < hysteresis) && horizCheck) { retval |= GROW_BOTTOM_EDGE; } // Not near any edge but inside the rectangle: move. if (retval == GROW_NONE && r.contains((int) x, (int) y)) { retval = MOVE; } } return retval; }
@Override public boolean onTouch(View view, MotionEvent motionEvent) { float xDelta = Math.abs(motionEvent.getRawX() - showcaseX); float yDelta = Math.abs(motionEvent.getRawY() - showcaseY); double distanceFromFocus = Math.sqrt(Math.pow(xDelta, 2) + Math.pow(yDelta, 2)); if (mOptions.hideOnClickOutside && distanceFromFocus > showcaseRadius) { this.hide(); return true; } return mOptions.block && distanceFromFocus > showcaseRadius; }
@Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX() - CENTER_X; float y = event.getY() - CENTER_Y; boolean inCenter = Math.sqrt(x * x + y * y) <= CENTER_RADIUS; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mTrackingCenter = inCenter; if (inCenter) { mHighlightCenter = true; invalidate(); break; } case MotionEvent.ACTION_MOVE: if (mTrackingCenter) { if (mHighlightCenter != inCenter) { mHighlightCenter = inCenter; invalidate(); } } else { float angle = (float) Math.atan2(y, x); // need to turn angle [-PI ... PI] into unit [0....1] float unit = angle / (2 * PI); if (unit < 0) { unit += 1; } mCenterPaint.setColor(interpColor(mColors, unit)); invalidate(); } break; case MotionEvent.ACTION_UP: if (mTrackingCenter) { if (inCenter) { mListener.colorChanged(mCenterPaint.getColor()); } mTrackingCenter = false; // so we draw w/o halo invalidate(); } break; } return true; }
@Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX() - mWheelCenter.x; float y = event.getY() - mWheelCenter.y; double distanceFromCenter = Math.sqrt(x * x + y * y); boolean inWheel = false; boolean inBar = false; if (distanceFromCenter <= mRadius) { inWheel = true; } else if (distanceFromCenter <= (mRadius + SPACE_BETWEEN_WHEEL_AND_BAR + ARC_WIDTH) && event.getX() > mWheelCenter.x) { inBar = true; } switch (event.getAction()) { // always change to the new color immediately using the appropriate control case MotionEvent.ACTION_DOWN: isTrackingHSWheel = inWheel; isTrackingBBar = inBar; if (inWheel) { setCurrentHueSaturation(x, y, distanceFromCenter); } else if (inBar) { setCurrentBrightness(event.getY()); } break; case MotionEvent.ACTION_MOVE: if (isTrackingHSWheel) { setCurrentHueSaturation(x, y, distanceFromCenter); } else if (isTrackingBBar) { setCurrentBrightness(event.getY()); } break; case MotionEvent.ACTION_UP: isTrackingHSWheel = false; isTrackingBBar = false; break; } return true; }
/** * @param deltaFlipDistance The distance to flip. * @return The duration for a flip, bigger deltaFlipDistance = longer duration. The increase if * duration gets smaller for bigger values of deltaFlipDistance. */ private int getFlipDuration(int deltaFlipDistance) { float distance = Math.abs(deltaFlipDistance); return (int) (MAX_SINGLE_PAGE_FLIP_ANIM_DURATION * Math.sqrt(distance / FLIP_DISTANCE_PER_PAGE)); }