Create a bar char preference widget
- Per Q design, we will show a bar chart in Settings > Privacy page.
Permission team also needs this bar chart in their page.
- Create a new library named SettingsLibBarChartPreference
Test: visual, robotest
Change-Id: Iff5a1233357a6aa6a667c0059f542a1b444b59a2
Fixes: 117623686
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 042808a0..2321790 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -19,6 +19,7 @@
"SettingsLibLayoutPreference",
"SettingsLibActionButtonsPreference",
"SettingsLibEntityHeaderWidgets",
+ "SettingsLibBarChartPreference"
],
// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES
diff --git a/packages/SettingsLib/BarChartPreference/Android.bp b/packages/SettingsLib/BarChartPreference/Android.bp
new file mode 100644
index 0000000..477e897
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/Android.bp
@@ -0,0 +1,13 @@
+android_library {
+ name: "SettingsLibBarChartPreference",
+
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+
+ static_libs: [
+ "androidx.preference_preference",
+ ],
+
+ sdk_version: "system_current",
+ min_sdk_version: "21",
+}
diff --git a/packages/SettingsLib/BarChartPreference/AndroidManifest.xml b/packages/SettingsLib/BarChartPreference/AndroidManifest.xml
new file mode 100644
index 0000000..4b9f1ab
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.widget">
+
+ <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_chart.xml b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_chart.xml
new file mode 100644
index 0000000..1a4d7b7
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_chart.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/bar_chart_title"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:gravity="center"
+ android:textAppearance="@style/BarChart.Text.HeaderTitle"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center|bottom">
+
+ <com.android.settingslib.widget.BarView
+ android:id="@+id/bar_view1"
+ style="@style/BarViewStyle"
+ settings:barColor="#FA7B17"/>
+ <com.android.settingslib.widget.BarView
+ android:id="@+id/bar_view2"
+ style="@style/BarViewStyle"
+ settings:barColor="#F439A0"/>
+ <com.android.settingslib.widget.BarView
+ android:id="@+id/bar_view3"
+ style="@style/BarViewStyle"
+ settings:barColor="#A142F4"/>
+ <com.android.settingslib.widget.BarView
+ android:id="@+id/bar_view4"
+ style="@style/BarViewStyle"
+ settings:barColor="#24C1E0"/>
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/bar_chart_details"
+ style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:gravity="center"/>
+
+</LinearLayout>
diff --git a/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml
new file mode 100644
index 0000000..b053317
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/res/layout/settings_bar_view.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <View
+ android:id="@+id/bar_view"
+ android:layout_width="8dp"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorAccent"/>
+
+ <ImageView
+ android:id="@+id/icon_view"
+ android:layout_width="@dimen/settings_bar_view_icon_size"
+ android:layout_height="@dimen/settings_bar_view_icon_size"
+ android:scaleType="fitCenter"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"/>
+
+ <TextView
+ android:id="@+id/bar_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="2dp"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="@style/BarChart.Text.Title"/>
+
+ <TextView
+ android:id="@+id/bar_summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dp"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="@style/BarChart.Text.Summary"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/BarChartPreference/res/values/attrs.xml b/packages/SettingsLib/BarChartPreference/res/values/attrs.xml
new file mode 100644
index 0000000..df3eb0a
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/res/values/attrs.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<resources>
+
+ <declare-styleable name="SettingsBarView">
+ <!-- The color of bar view -->
+ <attr name="barColor" format="color" />
+ </declare-styleable>
+
+</resources>
diff --git a/packages/SettingsLib/BarChartPreference/res/values/dimens.xml b/packages/SettingsLib/BarChartPreference/res/values/dimens.xml
new file mode 100644
index 0000000..7148afa
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<resources>
+ <dimen name="settings_bar_view_max_height">106dp</dimen>
+ <dimen name="settings_bar_view_icon_size">24dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/BarChartPreference/res/values/styles.xml b/packages/SettingsLib/BarChartPreference/res/values/styles.xml
new file mode 100644
index 0000000..647d080
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/res/values/styles.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<resources>
+ <style name="BarViewStyle">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:layout_marginStart">8dp</item>
+ <item name="android:layout_marginEnd">8dp</item>
+ </style>
+
+ <style name="BarChart.Text"
+ parent="@android:style/TextAppearance.Material.Subhead">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="BarChart.Text.HeaderTitle">
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="BarChart.Text.Title">
+ <item name="android:textSize">22sp</item>
+ </style>
+
+ <style name="BarChart.Text.Summary"
+ parent="@android:style/TextAppearance.Material.Body1">
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
new file mode 100644
index 0000000..89ebf4d
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2018 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.settingslib.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import java.util.Arrays;
+
+/**
+ * This BarChartPreference shows four bar views in this preference at most.
+ *
+ * <p>The following code sample shows a typical use, with an XML layout and code to initialize the
+ * contents of the BarChartPreference:
+ *
+ * <pre>
+ * <com.android.settingslib.widget.BarChartPreference
+ * android:key="bar_chart"/>
+ * </pre>
+ *
+ * <p>This code sample demonstrates how to initialize the contents of the BarChartPreference defined
+ * in the previous XML layout:
+ *
+ * <pre>
+ * BarViewInfo[] viewsInfo = new BarViewInfo [] {
+ * new BarViewInfo(icon, 18, res of summary),
+ * new BarViewInfo(icon, 25, res of summary),
+ * new BarViewInfo(icon, 10, res of summary),
+ * new BarViewInfo(icon, 3, res of summary),
+ * };
+ * </pre>
+ *
+ * <pre>
+ * BarChartPreference preference = ((BarChartPreference) findPreference("bar_chart"));
+ *
+ * preference.setBarChartTitleRes(R.string.title_res);
+ * preference.setBarChartDetailsRes(R.string.details_res);
+ * preference.setBarChartDetailsClickListener(v -> doSomething());
+ * preference.setAllBarViewsData(viewsInfo);
+ * </pre>
+ */
+public class BarChartPreference extends Preference {
+
+ private static final String TAG = "BarChartPreference";
+ private static final int MAXIMUM_BAR_VIEWS = 4;
+ private static final int[] BAR_VIEWS = {
+ R.id.bar_view1,
+ R.id.bar_view2,
+ R.id.bar_view3,
+ R.id.bar_view4
+ };
+
+ private int mMaxBarHeight;
+ private @StringRes int mTitleId;
+ private @StringRes int mDetailsId;
+ private BarViewInfo[] mBarViewsInfo;
+ private View.OnClickListener mDetailsOnClickListener;
+
+ /**
+ * Constructs a new BarChartPreference with the given context's theme.
+ * It sets a layout with settings bar chart style
+ *
+ * @param context The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ */
+ public BarChartPreference(Context context) {
+ super(context);
+ init();
+ }
+
+ /**
+ * Constructs a new BarChartPreference with the given context's theme and the supplied
+ * attribute set.
+ * It sets a layout with settings bar chart style
+ *
+ * @param context the Context the view is running in
+ * @param attrs the attributes of the XML tag that is inflating the view.
+ */
+ public BarChartPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ /**
+ * Constructs a new BarChartPreference with the given context's theme, the supplied
+ * attribute set, and default style attribute.
+ * It sets a layout with settings bar chart style
+ *
+ * @param context The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ * @param defStyleAttr An attribute in the current theme that contains a
+ * reference to a style resource that supplies default
+ * values for the view. Can be 0 to not look for
+ * defaults.
+ */
+ public BarChartPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ /**
+ * Constructs a new BarChartPreference with the given context's theme, the supplied
+ * attribute set, and default styles.
+ * It sets a layout with settings bar chart style
+ *
+ * @param context The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ * @param defStyleAttr An attribute in the current theme that contains a
+ * reference to a style resource that supplies default
+ * values for the view. Can be 0 to not look for
+ * defaults.
+ * @param defStyleRes A resource identifier of a style resource that
+ * supplies default values for the view, used only if
+ * defStyleAttr is 0 or can not be found in the theme.
+ * Can be 0 to not look for defaults.
+ */
+ public BarChartPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init();
+ }
+
+ /**
+ * Set the text resource for bar chart title.
+ */
+ public void setBarChartTitle(@StringRes int resId) {
+ mTitleId = resId;
+ notifyChanged();
+ }
+
+ /**
+ * Set the text resource for bar chart details.
+ */
+ public void setBarChartDetails(@StringRes int resId) {
+ mDetailsId = resId;
+ notifyChanged();
+ }
+
+ /**
+ * Register a callback to be invoked when bar chart details view is clicked.
+ */
+ public void setBarChartDetailsClickListener(@Nullable View.OnClickListener clickListener) {
+ mDetailsOnClickListener = clickListener;
+ notifyChanged();
+ }
+
+ /**
+ * Set all bar view information which you'd like to show in preference.
+ *
+ * <p>This method helps you do a sort by {@linkBarViewInfo#mBarNumber} in descending order.
+ *
+ * @param barViewsInfo the barViewsInfo contain at least one {@link BarViewInfo}.
+ */
+ public void setAllBarViewsInfo(@NonNull BarViewInfo[] barViewsInfo) {
+ mBarViewsInfo = barViewsInfo;
+ // Do a sort in descending order, the first element would have max {@link
+ // BarViewInfo#mBarNumber}
+ Arrays.sort(mBarViewsInfo);
+ caculateAllBarViewsHeight();
+ notifyChanged();
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ holder.setDividerAllowedAbove(true);
+ holder.setDividerAllowedBelow(true);
+
+ bindChartTitleView(holder);
+ bindChartDetailsView(holder);
+ updateBarChart(holder);
+ }
+
+ private void init() {
+ setSelectable(false);
+ setLayoutResource(R.layout.settings_bar_chart);
+ mMaxBarHeight = getContext().getResources().getDimensionPixelSize(
+ R.dimen.settings_bar_view_max_height);
+ }
+
+ private void bindChartTitleView(PreferenceViewHolder holder) {
+ final TextView titleView = (TextView) holder.findViewById(R.id.bar_chart_title);
+ titleView.setText(mTitleId);
+ }
+
+ private void bindChartDetailsView(PreferenceViewHolder holder) {
+ final Button detailsView = (Button) holder.findViewById(R.id.bar_chart_details);
+ detailsView.setText(mDetailsId);
+ detailsView.setOnClickListener(mDetailsOnClickListener);
+ }
+
+ private void updateBarChart(PreferenceViewHolder holder) {
+ for (int index = 0; index < MAXIMUM_BAR_VIEWS; index++) {
+ final BarView barView = (BarView) holder.findViewById(BAR_VIEWS[index]);
+
+ // If there is no bar views data can be shown.
+ if (mBarViewsInfo == null || index >= mBarViewsInfo.length) {
+ barView.setVisibility(View.GONE);
+ continue;
+ }
+ barView.setVisibility(View.VISIBLE);
+ barView.updateBarViewUI(mBarViewsInfo[index]);
+ }
+ }
+
+ private void caculateAllBarViewsHeight() {
+ // Since we sorted this array in advance, the first element must have the max {@link
+ // BarViewInfo#mBarNumber}.
+ final int maxBarViewNumber = mBarViewsInfo[0].getBarNumber();
+ // If the max number of bar view is zero, then we don't caculate the unit for bar height.
+ final int unit = maxBarViewNumber == 0 ? 0 : mMaxBarHeight / maxBarViewNumber;
+
+ for (BarViewInfo barView : mBarViewsInfo) {
+ barView.setBarHeight(barView.getBarNumber() * unit);
+ }
+ }
+}
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java
new file mode 100644
index 0000000..6243a2d
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 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.settingslib.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * A extension view for bar chart.
+ */
+public class BarView extends LinearLayout {
+
+ private static final String TAG = "BarView";
+
+ private View mBarView;
+ private ImageView mIcon;
+ private TextView mBarTitle;
+ private TextView mBarSummary;
+
+ /**
+ * Constructs a new BarView with the given context's theme.
+ *
+ * @param context The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ */
+ public BarView(Context context) {
+ super(context);
+ init();
+ }
+
+ /**
+ * Constructs a new BarView with the given context's theme and the supplied
+ * attribute set.
+ *
+ * @param context the Context the view is running in
+ * @param attrs the attributes of the XML tag that is inflating the view.
+ */
+ public BarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+
+ // Get accent color
+ TypedArray a = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
+ @ColorInt final int colorAccent = a.getColor(0, 0);
+
+ // Get bar color from layout XML
+ a = context.obtainStyledAttributes(attrs, R.styleable.SettingsBarView);
+ @ColorInt final int barColor = a.getColor(R.styleable.SettingsBarView_barColor,
+ colorAccent);
+ a.recycle();
+
+ mBarView.setBackgroundColor(barColor);
+ }
+
+ /**
+ * This helps update the bar view UI with a {@link BarViewInfo}.
+ *
+ * @param barViewInfo A {@link BarViewInfo} saves bar view status.
+ */
+ public void updateBarViewUI(BarViewInfo barViewInfo) {
+ //Set height of bar view
+ mBarView.getLayoutParams().height = barViewInfo.getBarHeight();
+ mIcon.setImageDrawable(barViewInfo.getIcon());
+ // For now, we use the bar number as title.
+ mBarTitle.setText(Integer.toString(barViewInfo.getBarNumber()));
+ mBarSummary.setText(barViewInfo.getSummaryRes());
+ }
+
+ @VisibleForTesting
+ CharSequence getTitle() {
+ return mBarTitle.getText();
+ }
+
+ @VisibleForTesting
+ CharSequence getSummary() {
+ return mBarSummary.getText();
+ }
+
+ private void init() {
+ LayoutInflater.from(getContext()).inflate(R.layout.settings_bar_view, this);
+ setOrientation(LinearLayout.VERTICAL);
+ setGravity(Gravity.CENTER);
+
+ mBarView = findViewById(R.id.bar_view);
+ mIcon = (ImageView) findViewById(R.id.icon_view);
+ mBarTitle = (TextView) findViewById(R.id.bar_title);
+ mBarSummary = (TextView) findViewById(R.id.bar_summary);
+ }
+
+ private void setOnClickListner(View.OnClickListener listener) {
+ mBarView.setOnClickListener(listener);
+ }
+}
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java
new file mode 100644
index 0000000..aa83ce9
--- /dev/null
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 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.settingslib.widget;
+
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+
+import java.util.Comparator;
+
+/**
+ * A class responsible for saving bar view information.
+ */
+public class BarViewInfo implements Comparable<BarViewInfo> {
+
+ private final Drawable mIcon;
+ private View.OnClickListener mListener;
+ private @StringRes int mSummaryRes;
+ // A number indicates this bar's height. The larger number shows a higher bar view.
+ private int mBarNumber;
+ // A real height of bar view.
+ private int mBarHeight;
+
+ /**
+ * Construct a BarViewInfo instance.
+ *
+ * @param icon the icon of bar view.
+ * @param barNumber the number of bar view. The larger number show a more height of bar view.
+ * @param summaryRes the resource identifier of the string resource to be displayed
+ * @return BarViewInfo object.
+ */
+ public BarViewInfo(Drawable icon, @IntRange(from = 0) int barNumber,
+ @StringRes int summaryRes) {
+ mIcon = icon;
+ mBarNumber = barNumber;
+ mSummaryRes = summaryRes;
+ }
+
+ /**
+ * Set number for bar view.
+ *
+ * @param barNumber the number of bar view. The larger number shows a higher bar view.
+ */
+ public void setBarNumber(@IntRange(from = 0) int barNumber) {
+ mBarNumber = barNumber;
+ }
+
+ /**
+ * Set summary resource for bar view
+ *
+ * @param resId the resource identifier of the string resource to be displayed
+ */
+ public void setSummary(@StringRes int resId) {
+ mSummaryRes = resId;
+ }
+
+ /**
+ * Set a click listner for bar view.
+ *
+ * @param listener the click listner is attached on bar view.
+ */
+ public void setClickListener(@Nullable View.OnClickListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Get the icon of bar view.
+ *
+ * @return Drawable the icon of bar view.
+ */
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * Get the OnClickListener of bar view.
+ *
+ * @return View.OnClickListener the click listner of bar view.
+ */
+ public View.OnClickListener getListener() {
+ return mListener;
+ }
+
+ /**
+ * Get the real height of bar view.
+ *
+ * @return the real height of bar view.
+ */
+ public int getBarHeight() {
+ return mBarHeight;
+ }
+
+ /**
+ * Get summary resource of bar view.
+ *
+ * @return summary resource of bar view.
+ */
+ public int getSummaryRes() {
+ return mSummaryRes;
+ }
+
+ /**
+ * Get the number of app uses this permisssion.
+ *
+ * @return the number of app uses this permission.
+ */
+ public int getBarNumber() {
+ return mBarNumber;
+ }
+
+ @Override
+ public int compareTo(BarViewInfo other) {
+ // Descending order
+ return Comparator.comparingInt((BarViewInfo barViewInfo) -> barViewInfo.mBarNumber)
+ .compare(other, this);
+ }
+
+ /**
+ * Set a real height for bar view.
+ *
+ * <p>This method should not be called by outside. It usually should be called by
+ * {@link BarChartPreference#caculateAllBarViewsHeight}
+ *
+ * @param barHeight the real bar height for bar view.
+ */
+ void setBarHeight(@IntRange(from = 0) int barHeight) {
+ mBarHeight = barHeight;
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
new file mode 100644
index 0000000..371c3d4
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2018 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.settingslib.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.preference.PreferenceViewHolder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BarChartPreferenceTest {
+
+ private Context mContext;
+ private View mBarChartView;
+ private Drawable mIcon;
+ private BarView mBarView1;
+ private BarView mBarView2;
+ private BarView mBarView3;
+ private BarView mBarView4;
+ private PreferenceViewHolder mHolder;
+ private BarChartPreference mPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mBarChartView = View.inflate(mContext, R.layout.settings_bar_chart, null /* parent */);
+ mHolder = PreferenceViewHolder.createInstanceForTests(mBarChartView);
+ mPreference = new BarChartPreference(mContext, null /* attrs */);
+ mPreference.setBarChartTitle(R.string.debug_app);
+ mPreference.setBarChartDetails(R.string.debug_app);
+
+
+ mIcon = mContext.getDrawable(R.drawable.ic_menu);
+ mBarView1 = (BarView) mBarChartView.findViewById(R.id.bar_view1);
+ mBarView2 = (BarView) mBarChartView.findViewById(R.id.bar_view2);
+ mBarView3 = (BarView) mBarChartView.findViewById(R.id.bar_view3);
+ mBarView4 = (BarView) mBarChartView.findViewById(R.id.bar_view4);
+ }
+
+ @Test
+ public void setBarChartTitleRes_setTitleRes_showInBarChartTitle() {
+ final TextView titleView = (TextView) mBarChartView.findViewById(R.id.bar_chart_title);
+
+ mPreference.setBarChartTitle(R.string.debug_app);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(titleView.getText()).isEqualTo(mContext.getText(R.string.debug_app));
+ }
+
+ @Test
+ public void setBarChartDetailsRes_setDetailsRes_showInBarChartDetails() {
+ final TextView detailsView = (TextView) mBarChartView.findViewById(R.id.bar_chart_details);
+
+ mPreference.setBarChartDetails(R.string.debug_app);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(detailsView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(detailsView.getText()).isEqualTo(mContext.getText(R.string.debug_app));
+ }
+
+ @Test
+ public void setBarChartDetailsClickListener_setClickListener_detailsViewAttachClickListener() {
+ final TextView detailsView = (TextView) mBarChartView.findViewById(R.id.bar_chart_details);
+
+ mPreference.setBarChartDetailsClickListener(v -> {
+ });
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(detailsView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(detailsView.hasOnClickListeners()).isTrue();
+ }
+
+ @Test
+ public void setAllBarViewsInfo_setOneBarViewInfo_showOneBarView() {
+ final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
+ new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app)
+ };
+
+ mPreference.setAllBarViewsInfo(barViewsInfo);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView1.getTitle()).isEqualTo("10");
+
+ assertThat(mBarView2.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mBarView3.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mBarView4.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void setAllBarViewsInfo_setTwoBarViewsInfo_showTwoBarViews() {
+ final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
+ new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app)
+ };
+
+ mPreference.setAllBarViewsInfo(barViewsInfo);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView1.getTitle()).isEqualTo("20");
+ assertThat(mBarView2.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView2.getTitle()).isEqualTo("10");
+
+ assertThat(mBarView3.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mBarView4.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void setAllBarViewsInfo_setThreeBarViewsInfo_showThreeBarViews() {
+ final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
+ new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app)
+ };
+
+ mPreference.setAllBarViewsInfo(barViewsInfo);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView1.getTitle()).isEqualTo("20");
+ assertThat(mBarView2.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView2.getTitle()).isEqualTo("10");
+ assertThat(mBarView3.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView3.getTitle()).isEqualTo("5");
+
+ assertThat(mBarView4.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void setAllBarViewsInfo_setFourBarViewsInfo_showFourBarViews() {
+ final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
+ new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 2 /* barNumber */, R.string.debug_app),
+ };
+
+ mPreference.setAllBarViewsInfo(barViewsInfo);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView1.getTitle()).isEqualTo("20");
+ assertThat(mBarView2.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView2.getTitle()).isEqualTo("10");
+ assertThat(mBarView3.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView3.getTitle()).isEqualTo("5");
+ assertThat(mBarView4.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView4.getTitle()).isEqualTo("2");
+ }
+
+ @Test
+ public void setAllBarViewsInfo_setFourBarViewsInfo_barViewWasSortedInDescending() {
+ final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
+ new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 50 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app),
+ new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
+ };
+
+ mPreference.setAllBarViewsInfo(barViewsInfo);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView1.getTitle()).isEqualTo("50");
+ assertThat(mBarView2.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView2.getTitle()).isEqualTo("30");
+ assertThat(mBarView3.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView3.getTitle()).isEqualTo("10");
+ assertThat(mBarView4.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView4.getTitle()).isEqualTo("5");
+ }
+
+ @Test
+ public void setAllBarViewsInfo_setValidSummaryRes_barViewShouldShowSummary() {
+ final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
+ new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
+ };
+
+ mPreference.setAllBarViewsInfo(barViewsInfo);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBarView1.getSummary()).isEqualTo(mContext.getText(R.string.debug_app));
+ }
+}