257 lines
9.1 KiB
Java
257 lines
9.1 KiB
Java
/*
|
|
* Copyright (C) 2019 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.preference.Preference;
|
|
import androidx.preference.PreferenceViewHolder;
|
|
|
|
import java.util.Arrays;
|
|
import com.android.settingslib.widget.preference.barchart.R;
|
|
/**
|
|
* This BarChartPreference shows up to 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>
|
|
* BarChartPreference preference = ((BarChartPreference) findPreference("bar_chart"));
|
|
*
|
|
* BarChartInfo info = new BarChartInfo.Builder()
|
|
* .setTitle(R.string.permission_bar_chart_title)
|
|
* .setDetails(R.string.permission_bar_chart_details)
|
|
* .setEmptyText(R.string.permission_bar_chart_empty_text)
|
|
* .addBarViewInfo(new barViewInfo(...))
|
|
* .addBarViewInfo(new barViewInfo(...))
|
|
* .addBarViewInfo(new barViewInfo(...))
|
|
* .addBarViewInfo(new barViewInfo(...))
|
|
* .setDetailsOnClickListener(v -> doSomething())
|
|
* .build();
|
|
*
|
|
* preference.initializeBarChart(info);
|
|
* </pre>
|
|
*
|
|
*
|
|
* <p>You also can update new information for bar views by
|
|
* {@link BarChartPreference#setBarViewInfos(BarViewInfo[])}
|
|
*
|
|
* <pre>
|
|
* BarViewInfo[] barViewsInfo = new BarViewInfo [] {
|
|
* new BarViewInfo(...),
|
|
* new BarViewInfo(...),
|
|
* new BarViewInfo(...),
|
|
* new BarViewInfo(...),
|
|
* };
|
|
*
|
|
* preference.setBarViewInfos(barViewsInfo);
|
|
* </pre>
|
|
*/
|
|
public class BarChartPreference extends Preference {
|
|
|
|
public static final int MAXIMUM_BAR_VIEWS = 4;
|
|
private static final String TAG = "BarChartPreference";
|
|
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 boolean mIsLoading;
|
|
private BarChartInfo mBarChartInfo;
|
|
|
|
public BarChartPreference(Context context) {
|
|
super(context);
|
|
init();
|
|
}
|
|
|
|
public BarChartPreference(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
init();
|
|
}
|
|
|
|
public BarChartPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
init();
|
|
}
|
|
|
|
public BarChartPreference(Context context, AttributeSet attrs, int defStyleAttr,
|
|
int defStyleRes) {
|
|
super(context, attrs, defStyleAttr, defStyleRes);
|
|
init();
|
|
}
|
|
|
|
/**
|
|
* According to the information in {@link BarChartInfo} to initialize bar chart.
|
|
*
|
|
* @param barChartInfo The barChartInfo contains title, details, empty text, click listener
|
|
* attached on details view and four bar views.
|
|
*/
|
|
public void initializeBarChart(@NonNull BarChartInfo barChartInfo) {
|
|
mBarChartInfo = barChartInfo;
|
|
notifyChanged();
|
|
}
|
|
|
|
/**
|
|
* Sets all bar view information which you'd like to show in preference.
|
|
*
|
|
* @param barViewInfos the barViewInfos contain at least one {@link BarViewInfo}.
|
|
*/
|
|
public void setBarViewInfos(@Nullable BarViewInfo[] barViewInfos) {
|
|
if (barViewInfos != null && barViewInfos.length > MAXIMUM_BAR_VIEWS) {
|
|
throw new IllegalStateException("We only support up to four bar views");
|
|
}
|
|
mBarChartInfo.setBarViewInfos(barViewInfos);
|
|
notifyChanged();
|
|
}
|
|
|
|
/**
|
|
* Set loading state for {@link BarChartPreference}.
|
|
*
|
|
* By default, {@link BarChartPreference} doesn't care about it.
|
|
*
|
|
* But if user sets loading state to true explicitly, it means {@link BarChartPreference}
|
|
* needs to take some time to load data. So we won't initialize any view now.
|
|
*
|
|
* Once the state is updated to false, we will start to initialize view again.
|
|
*
|
|
* @param isLoading whether or not {@link BarChartPreference} is in loading state.
|
|
*/
|
|
public void updateLoadingState(boolean isLoading) {
|
|
mIsLoading = isLoading;
|
|
notifyChanged();
|
|
}
|
|
|
|
@Override
|
|
public void onBindViewHolder(PreferenceViewHolder holder) {
|
|
super.onBindViewHolder(holder);
|
|
holder.setDividerAllowedAbove(true);
|
|
holder.setDividerAllowedBelow(true);
|
|
|
|
// We bind title and details early so that we can preserve the correct height for chart
|
|
// view.
|
|
bindChartTitleView(holder);
|
|
bindChartDetailsView(holder);
|
|
|
|
// If the state is loading, we just show a blank view.
|
|
if (mIsLoading) {
|
|
holder.itemView.setVisibility(View.INVISIBLE);
|
|
return;
|
|
}
|
|
holder.itemView.setVisibility(View.VISIBLE);
|
|
|
|
final BarViewInfo[] barViewInfos = mBarChartInfo.getBarViewInfos();
|
|
// If there is no any bar view, we just show an empty text.
|
|
if (barViewInfos == null || barViewInfos.length == 0) {
|
|
setEmptyViewVisible(holder, true /* visible */);
|
|
return;
|
|
}
|
|
setEmptyViewVisible(holder, false /* visible */);
|
|
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(mBarChartInfo.getTitle());
|
|
}
|
|
|
|
private void bindChartDetailsView(PreferenceViewHolder holder) {
|
|
final Button detailsView = (Button) holder.findViewById(R.id.bar_chart_details);
|
|
final int details = mBarChartInfo.getDetails();
|
|
if (details == 0) {
|
|
detailsView.setVisibility(View.GONE);
|
|
} else {
|
|
detailsView.setVisibility(View.VISIBLE);
|
|
detailsView.setText(details);
|
|
detailsView.setOnClickListener(mBarChartInfo.getDetailsOnClickListener());
|
|
}
|
|
}
|
|
|
|
private void updateBarChart(PreferenceViewHolder holder) {
|
|
normalizeBarViewHeights();
|
|
|
|
final BarViewInfo[] barViewInfos = mBarChartInfo.getBarViewInfos();
|
|
|
|
for (int index = 0; index < MAXIMUM_BAR_VIEWS; index++) {
|
|
final BarView barView = (BarView) holder.findViewById(BAR_VIEWS[index]);
|
|
|
|
// If there is no bar view info can be shown.
|
|
if (barViewInfos == null || index >= barViewInfos.length) {
|
|
barView.setVisibility(View.GONE);
|
|
continue;
|
|
}
|
|
barView.setVisibility(View.VISIBLE);
|
|
barView.updateView(barViewInfos[index]);
|
|
}
|
|
}
|
|
|
|
private void normalizeBarViewHeights() {
|
|
final BarViewInfo[] barViewInfos = mBarChartInfo.getBarViewInfos();
|
|
// If there is no any bar view info, we don't need to calculate the height of all bar views.
|
|
if (barViewInfos == null || barViewInfos.length == 0) {
|
|
return;
|
|
}
|
|
// Do a sort in descending order, the first element would have max {@link
|
|
// BarViewInfo#mHeight}
|
|
Arrays.sort(barViewInfos);
|
|
// Since we sorted this array in advance, the first element must have the max {@link
|
|
// BarViewInfo#mHeight}.
|
|
final int maxBarHeight = barViewInfos[0].getHeight();
|
|
// If the max number of bar view is zero, then we don't calculate the unit for bar height.
|
|
final int unit = maxBarHeight == 0 ? 0 : mMaxBarHeight / maxBarHeight;
|
|
|
|
for (BarViewInfo barView : barViewInfos) {
|
|
barView.setNormalizedHeight(barView.getHeight() * unit);
|
|
}
|
|
}
|
|
|
|
private void setEmptyViewVisible(PreferenceViewHolder holder, boolean visible) {
|
|
final View barViewsContainer = holder.findViewById(R.id.bar_views_container);
|
|
final TextView emptyView = (TextView) holder.findViewById(R.id.empty_view);
|
|
final int emptyTextRes = mBarChartInfo.getEmptyText();
|
|
|
|
if (emptyTextRes != 0) {
|
|
emptyView.setText(emptyTextRes);
|
|
}
|
|
emptyView.setVisibility(visible ? View.VISIBLE : View.GONE);
|
|
barViewsContainer.setVisibility(visible ? View.GONE : View.VISIBLE);
|
|
}
|
|
}
|