Cleanup Storage Settings
Bug: 183078080 Test: make make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.deviceinfo make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.deviceinfo.storage atest com.android.settings.deviceinfo atest com.android.settings.deviceinfo.storage Change-Id: I901f5f7999ea94dafb72a2517a11e2ff1fd51b42
This commit is contained in:
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
package com.android.settings.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Typeface;
|
||||
import android.icu.text.DecimalFormatSymbols;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* DonutView represents a donut graph. It visualizes a certain percentage of fullness with a
|
||||
* corresponding label with the fullness on the inside (i.e. "50%" inside of the donut).
|
||||
*/
|
||||
public class DonutView extends View {
|
||||
private static final int TOP = -90;
|
||||
// From manual testing, this is the longest we can go without visual errors.
|
||||
private static final int LINE_CHARACTER_LIMIT = 10;
|
||||
private float mStrokeWidth;
|
||||
private double mPercent;
|
||||
private Paint mBackgroundCircle;
|
||||
private Paint mFilledArc;
|
||||
private TextPaint mTextPaint;
|
||||
private TextPaint mBigNumberPaint;
|
||||
private String mPercentString;
|
||||
private String mFullString;
|
||||
private boolean mShowPercentString = true;
|
||||
private int mMeterBackgroundColor;
|
||||
private int mMeterConsumedColor;
|
||||
|
||||
public DonutView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public DonutView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mMeterBackgroundColor = context.getColor(R.color.meter_background_color);
|
||||
mMeterConsumedColor = Utils.getColorStateListDefaultColor(mContext,
|
||||
R.color.meter_consumed_color);
|
||||
boolean applyColorAccent = true;
|
||||
Resources resources = context.getResources();
|
||||
mStrokeWidth = resources.getDimension(R.dimen.storage_donut_thickness);
|
||||
|
||||
if (attrs != null) {
|
||||
TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.DonutView);
|
||||
mMeterBackgroundColor = styledAttrs.getColor(R.styleable.DonutView_meterBackgroundColor,
|
||||
mMeterBackgroundColor);
|
||||
mMeterConsumedColor = styledAttrs.getColor(R.styleable.DonutView_meterConsumedColor,
|
||||
mMeterConsumedColor);
|
||||
applyColorAccent = styledAttrs.getBoolean(R.styleable.DonutView_applyColorAccent,
|
||||
true);
|
||||
mShowPercentString = styledAttrs.getBoolean(R.styleable.DonutView_showPercentString,
|
||||
true);
|
||||
mStrokeWidth = styledAttrs.getDimensionPixelSize(R.styleable.DonutView_thickness,
|
||||
(int) mStrokeWidth);
|
||||
styledAttrs.recycle();
|
||||
}
|
||||
|
||||
mBackgroundCircle = new Paint();
|
||||
mBackgroundCircle.setAntiAlias(true);
|
||||
mBackgroundCircle.setStrokeCap(Paint.Cap.BUTT);
|
||||
mBackgroundCircle.setStyle(Paint.Style.STROKE);
|
||||
mBackgroundCircle.setStrokeWidth(mStrokeWidth);
|
||||
mBackgroundCircle.setColor(mMeterBackgroundColor);
|
||||
|
||||
mFilledArc = new Paint();
|
||||
mFilledArc.setAntiAlias(true);
|
||||
mFilledArc.setStrokeCap(Paint.Cap.BUTT);
|
||||
mFilledArc.setStyle(Paint.Style.STROKE);
|
||||
mFilledArc.setStrokeWidth(mStrokeWidth);
|
||||
mFilledArc.setColor(mMeterConsumedColor);
|
||||
|
||||
if (applyColorAccent) {
|
||||
final ColorFilter mAccentColorFilter =
|
||||
new PorterDuffColorFilter(
|
||||
Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
mBackgroundCircle.setColorFilter(mAccentColorFilter);
|
||||
mFilledArc.setColorFilter(mAccentColorFilter);
|
||||
}
|
||||
|
||||
final Locale locale = resources.getConfiguration().locale;
|
||||
final int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale);
|
||||
final int bidiFlags = (layoutDirection == LAYOUT_DIRECTION_LTR)
|
||||
? Paint.BIDI_LTR
|
||||
: Paint.BIDI_RTL;
|
||||
|
||||
mTextPaint = new TextPaint();
|
||||
mTextPaint.setColor(Utils.getColorAccentDefaultColor(getContext()));
|
||||
mTextPaint.setAntiAlias(true);
|
||||
mTextPaint.setTextSize(
|
||||
resources.getDimension(R.dimen.storage_donut_view_label_text_size));
|
||||
mTextPaint.setTextAlign(Paint.Align.CENTER);
|
||||
mTextPaint.setBidiFlags(bidiFlags);
|
||||
|
||||
mBigNumberPaint = new TextPaint();
|
||||
mBigNumberPaint.setColor(Utils.getColorAccentDefaultColor(getContext()));
|
||||
mBigNumberPaint.setAntiAlias(true);
|
||||
mBigNumberPaint.setTextSize(
|
||||
resources.getDimension(R.dimen.storage_donut_view_percent_text_size));
|
||||
mBigNumberPaint.setTypeface(Typeface.create(
|
||||
context.getString(com.android.internal.R.string.config_headlineFontFamily),
|
||||
Typeface.NORMAL));
|
||||
mBigNumberPaint.setBidiFlags(bidiFlags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
drawDonut(canvas);
|
||||
if (mShowPercentString) {
|
||||
drawInnerText(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawDonut(Canvas canvas) {
|
||||
canvas.drawArc(
|
||||
0 + mStrokeWidth,
|
||||
0 + mStrokeWidth,
|
||||
getWidth() - mStrokeWidth,
|
||||
getHeight() - mStrokeWidth,
|
||||
TOP,
|
||||
360,
|
||||
false,
|
||||
mBackgroundCircle);
|
||||
|
||||
canvas.drawArc(
|
||||
0 + mStrokeWidth,
|
||||
0 + mStrokeWidth,
|
||||
getWidth() - mStrokeWidth,
|
||||
getHeight() - mStrokeWidth,
|
||||
TOP,
|
||||
(360 * (float) mPercent),
|
||||
false,
|
||||
mFilledArc);
|
||||
}
|
||||
|
||||
private void drawInnerText(Canvas canvas) {
|
||||
final float centerX = getWidth() / 2;
|
||||
final float centerY = getHeight() / 2;
|
||||
final float totalHeight = getTextHeight(mTextPaint) + getTextHeight(mBigNumberPaint);
|
||||
final float startY = centerY + totalHeight / 2;
|
||||
// Support from Android P
|
||||
final String localizedPercentSign = new DecimalFormatSymbols().getPercentString();
|
||||
|
||||
// The first line y-coordinates start at (total height - all TextPaint height) / 2
|
||||
canvas.save();
|
||||
final Spannable percentStringSpan =
|
||||
getPercentageStringSpannable(getResources(), mPercentString, localizedPercentSign);
|
||||
final StaticLayout percentStringLayout = new StaticLayout(percentStringSpan,
|
||||
mBigNumberPaint, getWidth(), Layout.Alignment.ALIGN_CENTER, 1, 0, false);
|
||||
canvas.translate(0, (getHeight() - totalHeight) / 2);
|
||||
percentStringLayout.draw(canvas);
|
||||
canvas.restore();
|
||||
|
||||
// The second line starts at the bottom + room for the descender.
|
||||
canvas.drawText(mFullString, centerX, startY - mTextPaint.descent(), mTextPaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a percentage full to have the donut graph.
|
||||
*/
|
||||
public void setPercentage(double percent) {
|
||||
mPercent = percent;
|
||||
mPercentString = Utils.formatPercentage(mPercent);
|
||||
mFullString = getContext().getString(R.string.storage_percent_full);
|
||||
if (mFullString.length() > LINE_CHARACTER_LIMIT) {
|
||||
mTextPaint.setTextSize(
|
||||
getContext()
|
||||
.getResources()
|
||||
.getDimension(
|
||||
R.dimen.storage_donut_view_shrunken_label_text_size));
|
||||
}
|
||||
setContentDescription(getContext().getString(
|
||||
R.string.join_two_unrelated_items, mPercentString, mFullString));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
public int getMeterBackgroundColor() {
|
||||
return mMeterBackgroundColor;
|
||||
}
|
||||
|
||||
public void setMeterBackgroundColor(@ColorRes int meterBackgroundColor) {
|
||||
mMeterBackgroundColor = meterBackgroundColor;
|
||||
mBackgroundCircle.setColor(meterBackgroundColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
public int getMeterConsumedColor() {
|
||||
return mMeterConsumedColor;
|
||||
}
|
||||
|
||||
public void setMeterConsumedColor(@ColorRes int meterConsumedColor) {
|
||||
mMeterConsumedColor = meterConsumedColor;
|
||||
mFilledArc.setColor(meterConsumedColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static Spannable getPercentageStringSpannable(
|
||||
Resources resources, String percentString, String percentageSignString) {
|
||||
final float fontProportion =
|
||||
resources.getDimension(R.dimen.storage_donut_view_percent_sign_size)
|
||||
/ resources.getDimension(R.dimen.storage_donut_view_percent_text_size);
|
||||
final Spannable percentStringSpan = new SpannableString(percentString);
|
||||
int startIndex = percentString.indexOf(percentageSignString);
|
||||
int endIndex = startIndex + percentageSignString.length();
|
||||
|
||||
// Fallback to no small string if we can't find the percentage sign.
|
||||
if (startIndex < 0) {
|
||||
startIndex = 0;
|
||||
endIndex = percentString.length();
|
||||
}
|
||||
|
||||
percentStringSpan.setSpan(
|
||||
new RelativeSizeSpan(fontProportion),
|
||||
startIndex,
|
||||
endIndex,
|
||||
Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
|
||||
return percentStringSpan;
|
||||
}
|
||||
|
||||
private float getTextHeight(TextPaint paint) {
|
||||
// Technically, this should be the cap height, but I can live with the descent - ascent.
|
||||
return paint.descent() - paint.ascent();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user