diff options
author | Jeff Sharkey <jsharkey@android.com> | 2011-09-25 18:22:48 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2011-09-25 18:41:13 -0700 |
commit | 461842a8c0000ebc1351ec7fe30b0f820b769ccf (patch) | |
tree | 426614b67d2a3b83e1eb8beadc2323c9e4a1102b | |
parent | 2407efcf42baf1646094d80035997ff169d3eff4 (diff) | |
download | packages_apps_Settings-461842a8c0000ebc1351ec7fe30b0f820b769ccf.zip packages_apps_Settings-461842a8c0000ebc1351ec7fe30b0f820b769ccf.tar.gz packages_apps_Settings-461842a8c0000ebc1351ec7fe30b0f820b769ccf.tar.bz2 |
Data usage strings, sweep touches, fixes.
Change strings around limiting background data. Move limit/warning
sweeps above inspection sweeps, and teach about additional neighbors
on different axis.
Guard against DialogFragment.show(), fix pie chart to draw edges, and
remove data usage from battery UI.
Bug: 5341374, 5337650, 5337385, 5319465, 5236335
Change-Id: Iea8c2a2ab405b645d85abe34a0178d4b8874cdd5
-rw-r--r-- | res/layout/data_usage_chart.xml | 32 | ||||
-rw-r--r-- | res/values/strings.xml | 12 | ||||
-rw-r--r-- | src/com/android/settings/DataUsageSummary.java | 44 | ||||
-rw-r--r-- | src/com/android/settings/fuelgauge/PowerUsageSummary.java | 6 | ||||
-rw-r--r-- | src/com/android/settings/widget/ChartDataUsageView.java | 23 | ||||
-rw-r--r-- | src/com/android/settings/widget/ChartSweepView.java | 29 | ||||
-rw-r--r-- | src/com/android/settings/widget/PieChartView.java | 128 |
7 files changed, 175 insertions, 99 deletions
diff --git a/res/layout/data_usage_chart.xml b/res/layout/data_usage_chart.xml index 38f1c11..f9d4642 100644 --- a/res/layout/data_usage_chart.xml +++ b/res/layout/data_usage_chart.xml @@ -59,6 +59,22 @@ settings:fillColorSecondary="#60ba7f3e" /> <com.android.settings.widget.ChartSweepView + android:id="@+id/sweep_left" + android:layout_width="wrap_content" + android:layout_height="match_parent" + settings:sweepDrawable="@drawable/data_sweep_left" + settings:followAxis="horizontal" + settings:neighborMargin="5dip" /> + + <com.android.settings.widget.ChartSweepView + android:id="@+id/sweep_right" + android:layout_width="wrap_content" + android:layout_height="match_parent" + settings:sweepDrawable="@drawable/data_sweep_right" + settings:followAxis="horizontal" + settings:neighborMargin="5dip" /> + + <com.android.settings.widget.ChartSweepView android:id="@+id/sweep_warning" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -82,20 +98,4 @@ settings:labelTemplate="@string/data_usage_sweep_limit" settings:labelColor="#c01a2c" /> - <com.android.settings.widget.ChartSweepView - android:id="@+id/sweep_left" - android:layout_width="wrap_content" - android:layout_height="match_parent" - settings:sweepDrawable="@drawable/data_sweep_left" - settings:followAxis="horizontal" - settings:neighborMargin="5dip" /> - - <com.android.settings.widget.ChartSweepView - android:id="@+id/sweep_right" - android:layout_width="wrap_content" - android:layout_height="match_parent" - settings:sweepDrawable="@drawable/data_sweep_right" - settings:followAxis="horizontal" - settings:neighborMargin="5dip" /> - </com.android.settings.widget.ChartDataUsageView> diff --git a/res/values/strings.xml b/res/values/strings.xml index b4cc3de..a2e1d48 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3490,7 +3490,7 @@ found in the list of installed applications.</string> <!-- Title for checkbox menu option to enable mobile data when roaming. [CHAR LIMIT=32] --> <string name="data_usage_menu_roaming">Data roaming</string> <!-- Title for checkbox menu option to restrict background data usage. [CHAR LIMIT=20] --> - <string name="data_usage_menu_restrict_background">Restrict data</string> + <string name="data_usage_menu_restrict_background">Restrict background data</string> <!-- Title for checkbox menu option to show 4G mobile data usage separate from other mobile data usage. [CHAR LIMIT=32] --> <string name="data_usage_menu_split_4g">Separate 4G usage</string> <!-- Title for checkbox menu option to show Wi-Fi data usage. [CHAR LIMIT=32] --> @@ -3547,13 +3547,15 @@ found in the list of installed applications.</string> <!-- Checkbox label that restricts background data usage of a specific application. [CHAR LIMIT=32] --> <string name="data_usage_app_restrict_background">Restrict background data</string> <!-- Summary message for checkbox that restricts background data usage of a specific application. [CHAR LIMIT=64] --> - <string name="data_usage_app_restrict_background_summary">Disable background data on networks that you\'ve chosen to limit (<xliff:g id="networks" example="Mobile, Wi-Fi">%1$s</xliff:g>).</string> + <string name="data_usage_app_restrict_background_summary">Disable background data on mobile data network only. Wi-Fi will be used if available.</string> + <!-- Summary message for checkbox that restricts background data usage of a specific application when no networks have been limited. [CHAR LIMIT=64] --> + <string name="data_usage_app_restrict_background_summary_disabled">To restrict background data for this app, first set a mobile data limit.</string> <!-- Title of dialog shown when user restricts background data usage of a specific application. [CHAR LIMIT=48] --> <string name="data_usage_app_restrict_dialog_title">Restrict background data?</string> <!-- Body of dialog shown when user restricts background data usage of a specific application. [CHAR LIMIT=NONE] --> - <string name="data_usage_app_restrict_dialog">This feature may negatively impact applications which depend on background data usage.\n\nMore appropriate data usage controls may be found within this application\'s settings.</string> + <string name="data_usage_app_restrict_dialog">This feature may cause an app that depends on background data to stop working when Wi-Fi isn\'t available.\n\nMore appropriate data usage controls may be found in the settings available from within the app.</string> <!-- Body of dialog shown when user attempts to restrict background data before a network data limit has been set. [CHAR LIMIT=NONE] --> - <string name="data_usage_restrict_denied_dialog">Restricting background data is only available when you\'ve set a network data limit.</string> + <string name="data_usage_restrict_denied_dialog">Restricting background data is possible only when you\'ve set a mobile data limit.</string> <!-- Title of dialog for editing data usage cycle reset date. [CHAR LIMIT=48] --> <string name="data_usage_cycle_editor_title">Usage cycle reset date</string> @@ -3575,7 +3577,7 @@ found in the list of installed applications.</string> <!-- Title of dialog shown before user restricts background data usage. [CHAR LIMIT=48] --> <string name="data_usage_restrict_background_title">Restrict background data?</string> <!-- Body of dialog shown before user restricts background data usage. [CHAR LIMIT=NONE] --> - <string name="data_usage_restrict_background">If you restrict background data, some apps and services won\'t work on networks that you\'ve chosen to limit.\n\nCurrently limited networks: <xliff:g id="networks" example="Mobile, Wi-Fi">%1$s</xliff:g></string> + <string name="data_usage_restrict_background">If you restrict background mobile data, some apps and services won\'t work unless Wi-Fi is available.</string> <!-- Label displaying current network data usage warning threshold. [CHAR LIMIT=18] --> <string name="data_usage_sweep_warning"><font size="21"><xliff:g id="number" example="128">^1</xliff:g></font> <font size="9"><xliff:g id="unit" example="KB">^2</xliff:g></font>\n<font size="12">warning</font></string> diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java index d6c40b2..6096029 100644 --- a/src/com/android/settings/DataUsageSummary.java +++ b/src/com/android/settings/DataUsageSummary.java @@ -751,9 +751,13 @@ public class DataUsageSummary extends Fragment { if (NetworkPolicyManager.isUidValidForPolicy(context, primaryUid) && !getRestrictBackground() && isBandwidthControlEnabled()) { setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background); - setPreferenceSummary(mAppRestrictView, - getString(R.string.data_usage_app_restrict_background_summary, - buildLimitedNetworksString())); + if (hasLimitedNetworks()) { + setPreferenceSummary(mAppRestrictView, + getString(R.string.data_usage_app_restrict_background_summary)); + } else { + setPreferenceSummary(mAppRestrictView, + getString(R.string.data_usage_app_restrict_background_summary_disabled)); + } mAppRestrictView.setVisibility(View.VISIBLE); mAppRestrict.setChecked(getAppRestrictBackground()); @@ -925,8 +929,9 @@ public class DataUsageSummary extends Fragment { historyEnd = mChartData.network.getEnd(); } - if (historyStart == Long.MAX_VALUE) historyStart = System.currentTimeMillis(); - if (historyEnd == Long.MIN_VALUE) historyEnd = System.currentTimeMillis(); + final long now = System.currentTimeMillis(); + if (historyStart == Long.MAX_VALUE) historyStart = now; + if (historyEnd == Long.MIN_VALUE) historyEnd = now + 1; boolean hasCycles = false; if (policy != null) { @@ -1489,6 +1494,8 @@ public class DataUsageSummary extends Fragment { private static final String EXTRA_UIDS = "uids"; public static void show(DataUsageSummary parent, int[] uids, CharSequence label) { + if (!parent.isAdded()) return; + final Bundle args = new Bundle(); args.putIntArray(EXTRA_UIDS, uids); @@ -1529,8 +1536,9 @@ public class DataUsageSummary extends Fragment { private static final String EXTRA_LIMIT_BYTES = "limitBytes"; public static void show(DataUsageSummary parent) { - final Resources res = parent.getResources(); + if (!parent.isAdded()) return; + final Resources res = parent.getResources(); final CharSequence message; final long limitBytes; @@ -1597,6 +1605,8 @@ public class DataUsageSummary extends Fragment { private static final String EXTRA_TEMPLATE = "template"; public static void show(DataUsageSummary parent) { + if (!parent.isAdded()) return; + final Bundle args = new Bundle(); args.putParcelable(EXTRA_TEMPLATE, parent.mTemplate); @@ -1649,6 +1659,8 @@ public class DataUsageSummary extends Fragment { private static final String EXTRA_TEMPLATE = "template"; public static void show(DataUsageSummary parent) { + if (!parent.isAdded()) return; + final Bundle args = new Bundle(); args.putParcelable(EXTRA_TEMPLATE, parent.mTemplate); @@ -1709,6 +1721,8 @@ public class DataUsageSummary extends Fragment { private static final String EXTRA_TEMPLATE = "template"; public static void show(DataUsageSummary parent) { + if (!parent.isAdded()) return; + final Bundle args = new Bundle(); args.putParcelable(EXTRA_TEMPLATE, parent.mTemplate); @@ -1766,6 +1780,8 @@ public class DataUsageSummary extends Fragment { */ public static class ConfirmDataDisableFragment extends DialogFragment { public static void show(DataUsageSummary parent) { + if (!parent.isAdded()) return; + final ConfirmDataDisableFragment dialog = new ConfirmDataDisableFragment(); dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), TAG_CONFIRM_DATA_DISABLE); @@ -1799,6 +1815,8 @@ public class DataUsageSummary extends Fragment { */ public static class ConfirmDataRoamingFragment extends DialogFragment { public static void show(DataUsageSummary parent) { + if (!parent.isAdded()) return; + final ConfirmDataRoamingFragment dialog = new ConfirmDataRoamingFragment(); dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), TAG_CONFIRM_DATA_ROAMING); @@ -1832,6 +1850,8 @@ public class DataUsageSummary extends Fragment { */ public static class ConfirmRestrictFragment extends DialogFragment { public static void show(DataUsageSummary parent) { + if (!parent.isAdded()) return; + final ConfirmRestrictFragment dialog = new ConfirmRestrictFragment(); dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), TAG_CONFIRM_RESTRICT); @@ -1843,13 +1863,7 @@ public class DataUsageSummary extends Fragment { final AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.data_usage_restrict_background_title); - - final DataUsageSummary target = (DataUsageSummary) getTargetFragment(); - if (target != null) { - final CharSequence limitedNetworks = target.buildLimitedNetworksString(); - builder.setMessage( - getString(R.string.data_usage_restrict_background, limitedNetworks)); - } + builder.setMessage(getString(R.string.data_usage_restrict_background)); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { @@ -1872,6 +1886,8 @@ public class DataUsageSummary extends Fragment { */ public static class DeniedRestrictFragment extends DialogFragment { public static void show(DataUsageSummary parent) { + if (!parent.isAdded()) return; + final DeniedRestrictFragment dialog = new DeniedRestrictFragment(); dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), TAG_DENIED_RESTRICT); @@ -1896,6 +1912,8 @@ public class DataUsageSummary extends Fragment { */ public static class ConfirmAppRestrictFragment extends DialogFragment { public static void show(DataUsageSummary parent) { + if (!parent.isAdded()) return; + final ConfirmAppRestrictFragment dialog = new ConfirmAppRestrictFragment(); dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), TAG_CONFIRM_APP_RESTRICT); diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index c24c5ea..6ff3e0e 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -202,6 +202,8 @@ public class PowerUsageSummary extends PreferenceFragment implements Runnable { switch (sipper.drainType) { case APP: { + // TODO: surface tcpBytesSent/tcpBytesReceived again once + // measured separately from uid_stats. Uid uid = sipper.uidObj; types = new int[] { R.string.usage_type_cpu, @@ -209,8 +211,6 @@ public class PowerUsageSummary extends PreferenceFragment implements Runnable { R.string.usage_type_wake_lock, R.string.usage_type_gps, R.string.usage_type_wifi_running, - R.string.usage_type_data_send, - R.string.usage_type_data_recv, R.string.usage_type_audio, R.string.usage_type_video, }; @@ -220,8 +220,6 @@ public class PowerUsageSummary extends PreferenceFragment implements Runnable { sipper.wakeLockTime, sipper.gpsTime, sipper.wifiRunningTime, - sipper.tcpBytesSent, - sipper.tcpBytesReceived, 0, 0 }; diff --git a/src/com/android/settings/widget/ChartDataUsageView.java b/src/com/android/settings/widget/ChartDataUsageView.java index 43ce97c..f10ea5e 100644 --- a/src/com/android/settings/widget/ChartDataUsageView.java +++ b/src/com/android/settings/widget/ChartDataUsageView.java @@ -120,6 +120,12 @@ public class ChartDataUsageView extends ChartView { mSweepWarning.setValidRangeDynamic(null, mSweepLimit); mSweepLimit.setValidRangeDynamic(mSweepWarning, null); + // mark neighbors for checking touch events against + mSweepLeft.setNeighbors(mSweepRight); + mSweepRight.setNeighbors(mSweepLeft); + mSweepLimit.setNeighbors(mSweepWarning, mSweepLeft, mSweepRight); + mSweepWarning.setNeighbors(mSweepLimit, mSweepLeft, mSweepRight); + mSweepLeft.addOnSweepListener(mHorizListener); mSweepRight.addOnSweepListener(mHorizListener); mSweepWarning.addOnSweepListener(mVertListener); @@ -375,12 +381,12 @@ public class ChartDataUsageView extends ChartView { return mSweepLimit.getLabelValue(); } - private long getStatsStart() { - return mHistory != null ? mHistory.getStart() : Long.MIN_VALUE; + private long getHistoryStart() { + return mHistory != null ? mHistory.getStart() : Long.MAX_VALUE; } - private long getStatsEnd() { - return mHistory != null ? mHistory.getEnd() : Long.MAX_VALUE; + private long getHistoryEnd() { + return mHistory != null ? mHistory.getEnd() : Long.MIN_VALUE; } /** @@ -394,8 +400,13 @@ public class ChartDataUsageView extends ChartView { mSeries.setBounds(visibleStart, visibleEnd); mDetailSeries.setBounds(visibleStart, visibleEnd); - final long validStart = Math.max(visibleStart, getStatsStart()); - final long validEnd = Math.min(visibleEnd, getStatsEnd()); + final long historyStart = getHistoryStart(); + final long historyEnd = getHistoryEnd(); + + final long validStart = historyStart == Long.MAX_VALUE ? visibleStart + : Math.max(visibleStart, historyStart); + final long validEnd = historyEnd == Long.MIN_VALUE ? visibleEnd + : Math.min(visibleEnd, historyEnd); if (LIMIT_SWEEPS_TO_VALID_DATA) { // prevent time sweeps from leaving valid data diff --git a/src/com/android/settings/widget/ChartSweepView.java b/src/com/android/settings/widget/ChartSweepView.java index 22a6478..c5f2aba 100644 --- a/src/com/android/settings/widget/ChartSweepView.java +++ b/src/com/android/settings/widget/ChartSweepView.java @@ -101,6 +101,8 @@ public class ChartSweepView extends View { private float mTrackingStart; private MotionEvent mTracking; + private ChartSweepView[] mNeighbors = new ChartSweepView[0]; + public ChartSweepView(Context context) { this(context, null); } @@ -149,6 +151,10 @@ public class ChartSweepView extends View { mAxis = Preconditions.checkNotNull(axis, "missing axis"); } + public void setNeighbors(ChartSweepView... neighbors) { + mNeighbors = neighbors; + } + public int getFollowAxis() { return mFollowAxis; } @@ -381,18 +387,16 @@ public class ChartSweepView extends View { * {@link ChartSweepView} compared to ourselves. */ public boolean isTouchCloserTo(MotionEvent eventInParent, ChartSweepView another) { - if (another == null) return false; + final float selfDist = getTouchDistanceFromTarget(eventInParent); + final float anotherDist = another.getTouchDistanceFromTarget(eventInParent); + return anotherDist < selfDist; + } + private float getTouchDistanceFromTarget(MotionEvent eventInParent) { if (mFollowAxis == HORIZONTAL) { - final float selfDist = Math.abs(eventInParent.getX() - (getX() + getTargetInset())); - final float anotherDist = Math.abs( - eventInParent.getX() - (another.getX() + another.getTargetInset())); - return anotherDist < selfDist; + return Math.abs(eventInParent.getX() - (getX() + getTargetInset())); } else { - final float selfDist = Math.abs(eventInParent.getY() - (getY() + getTargetInset())); - final float anotherDist = Math.abs( - eventInParent.getY() - (another.getY() + another.getTargetInset())); - return anotherDist < selfDist; + return Math.abs(eventInParent.getY() - (getY() + getTargetInset())); } } @@ -421,9 +425,10 @@ public class ChartSweepView extends View { eventInParent.offsetLocation(getLeft(), getTop()); // ignore event when closer to a neighbor - if (isTouchCloserTo(eventInParent, mValidAfterDynamic) - || isTouchCloserTo(eventInParent, mValidBeforeDynamic)) { - return false; + for (ChartSweepView neighbor : mNeighbors) { + if (isTouchCloserTo(eventInParent, neighbor)) { + return false; + } } if (acceptDrag) { diff --git a/src/com/android/settings/widget/PieChartView.java b/src/com/android/settings/widget/PieChartView.java index 6765733..bd77f04 100644 --- a/src/com/android/settings/widget/PieChartView.java +++ b/src/com/android/settings/widget/PieChartView.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; @@ -42,31 +43,34 @@ public class PieChartView extends View { public static final String TAG = "PieChartView"; public static final boolean LOGD = false; + private static final boolean FILL_GRADIENT = false; + private ArrayList<Slice> mSlices = Lists.newArrayList(); private int mOriginAngle; + private Matrix mMatrix = new Matrix(); - private Paint mPaintPrimary = new Paint(); - private Paint mPaintShadow = new Paint(); + private Paint mPaintOutline = new Paint(); private Path mPathSide = new Path(); - private Path mPathSideShadow = new Path(); + private Path mPathSideOutline = new Path(); - private Path mPathShadow = new Path(); + private Path mPathOutline = new Path(); private int mSideWidth; public class Slice { public long value; - public Path pathPrimary = new Path(); - public Path pathShadow = new Path(); + public Path path = new Path(); + public Path pathSide = new Path(); + public Path pathOutline = new Path(); - public Paint paintPrimary; + public Paint paint; public Slice(long value, int color) { this.value = value; - this.paintPrimary = buildFillPaint(color, getResources()); + this.paint = buildFillPaint(color, getResources()); } } @@ -81,12 +85,10 @@ public class PieChartView extends View { public PieChartView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - mPaintPrimary = buildFillPaint(Color.parseColor("#666666"), getResources()); - - mPaintShadow.setColor(Color.BLACK); - mPaintShadow.setStyle(Style.STROKE); - mPaintShadow.setStrokeWidth(3f * getResources().getDisplayMetrics().density); - mPaintShadow.setAntiAlias(true); + mPaintOutline.setColor(Color.BLACK); + mPaintOutline.setStyle(Style.STROKE); + mPaintOutline.setStrokeWidth(3f * getResources().getDisplayMetrics().density); + mPaintOutline.setAntiAlias(true); mSideWidth = (int) (20 * getResources().getDisplayMetrics().density); @@ -100,8 +102,10 @@ public class PieChartView extends View { paint.setStyle(Style.FILL_AND_STROKE); paint.setAntiAlias(true); - final int width = (int) (280 * res.getDisplayMetrics().density); - paint.setShader(new RadialGradient(0, 0, width, color, darken(color), TileMode.MIRROR)); + if (FILL_GRADIENT) { + final int width = (int) (280 * res.getDisplayMetrics().density); + paint.setShader(new RadialGradient(0, 0, width, color, darken(color), TileMode.MIRROR)); + } return paint; } @@ -120,6 +124,13 @@ public class PieChartView extends View { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + final float centerX = getWidth() / 2; + final float centerY = getHeight() / 2; + + mMatrix.reset(); + mMatrix.postScale(0.665f, 0.95f, centerX, centerY); + mMatrix.postRotate(-40, centerX, centerY); + generatePath(); } @@ -128,14 +139,15 @@ public class PieChartView extends View { long total = 0; for (Slice slice : mSlices) { - slice.pathPrimary.reset(); - slice.pathShadow.reset(); + slice.path.reset(); + slice.pathSide.reset(); + slice.pathOutline.reset(); total += slice.value; } mPathSide.reset(); - mPathSideShadow.reset(); - mPathShadow.reset(); + mPathSideOutline.reset(); + mPathOutline.reset(); // bail when not enough stats to render if (total == 0) { @@ -147,23 +159,56 @@ public class PieChartView extends View { final int height = getHeight(); final RectF rect = new RectF(0, 0, width, height); + final RectF rectSide = new RectF(); + rectSide.set(rect); + rectSide.offset(-mSideWidth, 0); - mPathSide.addOval(rect, Direction.CW); - mPathSideShadow.addOval(rect, Direction.CW); - mPathShadow.addOval(rect, Direction.CW); + mPathSide.addOval(rectSide, Direction.CW); + mPathSideOutline.addOval(rectSide, Direction.CW); + mPathOutline.addOval(rect, Direction.CW); int startAngle = mOriginAngle; for (Slice slice : mSlices) { final int sweepAngle = (int) (slice.value * 360 / total); - - slice.pathPrimary.moveTo(rect.centerX(), rect.centerY()); - slice.pathPrimary.arcTo(rect, startAngle, sweepAngle); - slice.pathPrimary.lineTo(rect.centerX(), rect.centerY()); - - slice.pathShadow.moveTo(rect.centerX(), rect.centerY()); - slice.pathShadow.arcTo(rect, startAngle, 0); - slice.pathShadow.moveTo(rect.centerX(), rect.centerY()); - slice.pathShadow.arcTo(rect, startAngle + sweepAngle, 0); + final int endAngle = startAngle + sweepAngle; + + final float startAngleMod = startAngle % 360; + final float endAngleMod = endAngle % 360; + final boolean startSideVisible = startAngleMod > 90 && startAngleMod < 270; + final boolean endSideVisible = endAngleMod > 90 && endAngleMod < 270; + + // draw slice + slice.path.moveTo(rect.centerX(), rect.centerY()); + slice.path.arcTo(rect, startAngle, sweepAngle); + slice.path.lineTo(rect.centerX(), rect.centerY()); + + if (startSideVisible || endSideVisible) { + + // when start is beyond horizon, push until visible + final float startAngleSide = startSideVisible ? startAngle : 450; + final float endAngleSide = endSideVisible ? endAngle : 270; + final float sweepAngleSide = endAngleSide - startAngleSide; + + // draw slice side + slice.pathSide.moveTo(rect.centerX(), rect.centerY()); + slice.pathSide.arcTo(rect, startAngleSide, 0); + slice.pathSide.rLineTo(-mSideWidth, 0); + slice.pathSide.arcTo(rectSide, startAngleSide, sweepAngleSide); + slice.pathSide.rLineTo(mSideWidth, 0); + slice.pathSide.arcTo(rect, endAngleSide, -sweepAngleSide); + } + + // draw slice outline + slice.pathOutline.moveTo(rect.centerX(), rect.centerY()); + slice.pathOutline.arcTo(rect, startAngle, 0); + if (startSideVisible) { + slice.pathOutline.rLineTo(-mSideWidth, 0); + } + slice.pathOutline.moveTo(rect.centerX(), rect.centerY()); + slice.pathOutline.arcTo(rect, startAngle + sweepAngle, 0); + if (endSideVisible) { + slice.pathOutline.rLineTo(-mSideWidth, 0); + } startAngle += sweepAngle; } @@ -174,21 +219,18 @@ public class PieChartView extends View { @Override protected void onDraw(Canvas canvas) { - canvas.translate(getWidth() * 0.25f, getHeight() * -0.05f); - canvas.rotate(-40, getWidth() * 0.5f, getHeight()); - canvas.scale(0.7f, 1.0f, getWidth(), getHeight()); + canvas.concat(mMatrix); - canvas.save(); - canvas.translate(-mSideWidth, 0); - canvas.drawPath(mPathSide, mPaintPrimary); - canvas.drawPath(mPathSideShadow, mPaintShadow); - canvas.restore(); + for (Slice slice : mSlices) { + canvas.drawPath(slice.pathSide, slice.paint); + } + canvas.drawPath(mPathSideOutline, mPaintOutline); for (Slice slice : mSlices) { - canvas.drawPath(slice.pathPrimary, slice.paintPrimary); - canvas.drawPath(slice.pathShadow, mPaintShadow); + canvas.drawPath(slice.path, slice.paint); + canvas.drawPath(slice.pathOutline, mPaintOutline); } - canvas.drawPath(mPathShadow, mPaintShadow); + canvas.drawPath(mPathOutline, mPaintOutline); } public static int darken(int color) { |