/** Called when the user finishes a scroll action. */ private void onScrollFinished() { if (mAutoCenterInSlice) { centerOnCurrentItem(); } else { mPieView.decelerate(); } }
/** * Set the current rotation of the pie graphic. Setting this value may change the current item. * * @param rotation The current pie rotation, in degrees. */ public void setPieRotation(int rotation) { rotation = (rotation % 360 + 360) % 360; mPieRotation = rotation; mPieView.rotateTo(rotation); calcCurrentItem(); }
/** * Initialize the control. This code is in a separate method so that it can be called from both * constructors. */ private void init() { // Force the background to software rendering because otherwise the Blur // filter won't work. setLayerToSW(this); // Set up the paint for the label text mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setColor(mTextColor); if (mTextHeight == 0) { mTextHeight = mTextPaint.getTextSize(); } else { mTextPaint.setTextSize(mTextHeight); } // Set up the paint for the pie slices mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPiePaint.setStyle(Paint.Style.FILL); mPiePaint.setTextSize(mTextHeight); cSlicePaint = new Paint(Paint.ANTI_ALIAS_FLAG); cSlicePaint.setStyle(Paint.Style.FILL); // Set up the paint for the shadow mShadowPaint = new Paint(0); mShadowPaint.setColor(0xff101010); mShadowPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL)); // Add a child view to draw the pie. Putting this in a child view // makes it possible to draw it on a separate hardware layer that rotates // independently mPieView = new PieView(getContext()); addView(mPieView); mPieView.rotateTo(mPieRotation); // The pointer doesn't need hardware acceleration, but in order to show up // in front of the pie it also needs to be on a separate view. mPointerView = new PointerView(getContext()); addView(mPointerView); // Set up an animator to animate the PieRotation property. This is used to // correct the pie's orientation after the user lets go of it. if (Build.VERSION.SDK_INT >= 11) { mAutoCenterAnimator = ObjectAnimator.ofInt(PieChart.this, "PieRotation", 0); // Add a listener to hook the onAnimationEnd event so that we can do // some cleanup when the pie stops moving. mAutoCenterAnimator.addListener( new Animator.AnimatorListener() { public void onAnimationStart(Animator animator) {} public void onAnimationEnd(Animator animator) { mPieView.decelerate(); } public void onAnimationCancel(Animator animator) {} public void onAnimationRepeat(Animator animator) {} }); } // Create a Scroller to handle the fling gesture. if (Build.VERSION.SDK_INT < 11) { mScroller = new Scroller(getContext()); } else { mScroller = new Scroller(getContext(), null, true); } // The scroller doesn't have any built-in animation functions--it just supplies // values when we ask it to. So we have to have a way to call it every frame // until the fling ends. This code (ab)uses a ValueAnimator object to generate // a callback on every animation frame. We don't use the animated value at all. if (Build.VERSION.SDK_INT >= 11) { mScrollAnimator = ValueAnimator.ofFloat(0, 1); mScrollAnimator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator valueAnimator) { tickScrollAnimation(); } }); } // Create a gesture detector to handle onTouch messages mDetector = new GestureDetector(PieChart.this.getContext(), new GestureListener()); // Turn off long press--this control doesn't use it, and if long press is enabled, // you can't scroll for a bit, pause, then scroll some more (the pause is interpreted // as a long press, apparently) mDetector.setIsLongpressEnabled(false); }
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); Log.d(TAG, "Slice Count: " + mData.size()); if (mData.size() > 0) { // // Set dimensions for text, pie chart, etc // // Account for padding float xpad = (float) (getPaddingLeft() + getPaddingRight()); float ypad = (float) (getPaddingTop() + getPaddingBottom()); // Account for the label if (mShowText) xpad += mTextWidth; float ww = (float) w - xpad; float hh = (float) h - ypad; // Figure out how big we can make the pie. float diameter = Math.min(ww, hh); mPieBounds = new RectF(0.0f, 0.0f, diameter, diameter); mPieBounds.offsetTo(getPaddingLeft(), getPaddingTop()); // Log.d(TAG, "mPieBounds>> "+mPieBounds); mPointerY = mTextY - (mTextHeight / 2.0f); float pointerOffset = mPieBounds.centerY() - mPointerY; // Make adjustments based on text position if (mTextPos == TEXTPOS_LEFT) { mTextPaint.setTextAlign(Paint.Align.RIGHT); if (mShowText) mPieBounds.offset(mTextWidth, 0.0f); mTextX = mPieBounds.left; if (pointerOffset < 0) { pointerOffset = -pointerOffset; mCurrentItemAngle = 225; } else { mCurrentItemAngle = 135; } mPointerX = mPieBounds.centerX() - pointerOffset; } else { mTextPaint.setTextAlign(Paint.Align.LEFT); mTextX = mPieBounds.right; if (pointerOffset < 0) { pointerOffset = -pointerOffset; mCurrentItemAngle = 315; } else { mCurrentItemAngle = 45; } mPointerX = mPieBounds.centerX() + pointerOffset; } mShadowBounds = new RectF( mPieBounds.left + 10, mPieBounds.bottom + 10, mPieBounds.right - 10, mPieBounds.bottom + 20); // Lay out the child view that actually draws the pie. mPieView.layout( (int) mPieBounds.left, (int) mPieBounds.top, (int) mPieBounds.right, (int) mPieBounds.bottom); mPieView.setPivot(mPieBounds.width() / 2, mPieBounds.height() / 2); mPointerView.layout(0, 0, w, h); onDataChanged(); } }