fix: 首次提交

This commit is contained in:
2024-12-09 11:25:23 +08:00
parent d0c01071e9
commit 2c2109a5f3
4741 changed files with 290641 additions and 0 deletions

View File

@@ -0,0 +1,176 @@
/*
* 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.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import java.util.ArrayList;
import java.util.List;
import com.android.settingslib.widget.preference.barchart.R;
/**
* BarChartInfo is responsible for storing information about {@link BarChartPreference}.
*/
public class BarChartInfo {
@StringRes
private final int mTitle;
@StringRes
private final int mDetails;
@StringRes
private final int mEmptyText;
private final View.OnClickListener mDetailsOnClickListener;
private BarViewInfo[] mBarViewInfos;
/**
* Gets the resource id for the title shown in {@link BarChartPreference}.
*
* @return the string resource id for title.
*/
public int getTitle() {
return mTitle;
}
/**
* Gets the resource id for the details shown in {@link BarChartPreference}.
*
* @return the string resource id for details.
*/
public int getDetails() {
return mDetails;
}
/**
* Gets the resource id for the empty text shown in {@link BarChartPreference} when there is no
* any bar view in {@link BarChartPreference}.
*
* @return the string resource id for empty text.
*/
public int getEmptyText() {
return mEmptyText;
}
/**
* Gets the click listener for the details view.
*
* @return click listener for details view.
*/
public View.OnClickListener getDetailsOnClickListener() {
return mDetailsOnClickListener;
}
/**
* Gets an array which contains up to four {@link BarViewInfo}
*
* @return an array holding the current all {@link BarViewInfo} state of the bar chart.
*/
public BarViewInfo[] getBarViewInfos() {
return mBarViewInfos;
}
void setBarViewInfos(BarViewInfo[] barViewInfos) {
mBarViewInfos = barViewInfos;
}
private BarChartInfo(Builder builder) {
mTitle = builder.mTitle;
mDetails = builder.mDetails;
mEmptyText = builder.mEmptyText;
mDetailsOnClickListener = builder.mDetailsOnClickListener;
if (builder.mBarViewInfos != null) {
mBarViewInfos = builder.mBarViewInfos.stream().toArray(BarViewInfo[]::new);
}
}
/**
* Builder class for {@link BarChartInfo}
*/
public static class Builder {
@StringRes
private int mTitle;
@StringRes
private int mDetails;
@StringRes
private int mEmptyText;
private View.OnClickListener mDetailsOnClickListener;
private List<BarViewInfo> mBarViewInfos;
/**
* Creates an instance of a {@link BarChartInfo} based on the current builder settings.
*
* @return The {@link BarChartInfo}.
*/
public BarChartInfo build() {
if (mTitle == 0) {
throw new IllegalStateException("You must call Builder#setTitle() once.");
}
return new BarChartInfo(this);
}
/**
* Sets the string resource id for the title.
*/
public Builder setTitle(@StringRes int title) {
mTitle = title;
return this;
}
/**
* Sets the string resource id for the details.
*/
public Builder setDetails(@StringRes int details) {
mDetails = details;
return this;
}
/**
* Sets the string resource id for the empty text.
*/
public Builder setEmptyText(@StringRes int emptyText) {
mEmptyText = emptyText;
return this;
}
/**
* Sets the click listener for details view.
*/
public Builder setDetailsOnClickListener(
@Nullable View.OnClickListener clickListener) {
mDetailsOnClickListener = clickListener;
return this;
}
/**
* Adds a {@link BarViewInfo} for {@link BarChartPreference}.
* Maximum of 4 {@link BarViewInfo} can be added.
*/
public Builder addBarViewInfo(@NonNull BarViewInfo barViewInfo) {
if (mBarViewInfos == null) {
mBarViewInfos = new ArrayList<>();
}
if (mBarViewInfos.size() >= BarChartPreference.MAXIMUM_BAR_VIEWS) {
throw new IllegalStateException("We only support up to four bar views");
}
mBarViewInfos.add(barViewInfo);
return this;
}
}
}

View File

@@ -0,0 +1,256 @@
/*
* 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>
* &lt;com.android.settingslib.widget.BarChartPreference
* android:key="bar_chart"/&gt;
* </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);
}
}

View File

@@ -0,0 +1,109 @@
/*
* 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.text.TextUtils;
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;
import com.android.settingslib.widget.preference.barchart.R;
/**
* {@link View} for a single vertical bar with icon and summary.
*/
public class BarView extends LinearLayout {
private static final String TAG = "BarView";
private View mBarView;
private ImageView mIcon;
private TextView mBarTitle;
private TextView mBarSummary;
public BarView(Context context) {
super(context);
init();
}
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);
}
/**
* Updates the view with a {@link BarViewInfo}.
*/
void updateView(BarViewInfo barViewInfo) {
setOnClickListener(barViewInfo.getClickListener());
//Set height of bar view
mBarView.getLayoutParams().height = barViewInfo.getNormalizedHeight();
mIcon.setImageDrawable(barViewInfo.getIcon());
mBarTitle.setText(barViewInfo.getTitle());
mBarSummary.setText(barViewInfo.getSummary());
final CharSequence barViewInfoContent = barViewInfo.getContentDescription();
if (!TextUtils.isEmpty(barViewInfoContent)
&& !TextUtils.equals((barViewInfo.getTitle()), barViewInfoContent)) {
mIcon.setContentDescription(barViewInfo.getContentDescription());
}
}
@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 | Gravity.BOTTOM);
mBarView = findViewById(R.id.bar_view);
mIcon = findViewById(R.id.icon_view);
mBarTitle = findViewById(R.id.bar_title);
mBarSummary = findViewById(R.id.bar_summary);
}
private void setOnClickListner(View.OnClickListener listener) {
mBarView.setOnClickListener(listener);
}
}

View File

@@ -0,0 +1,119 @@
/*
* 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 java.util.Comparator;
import com.android.settingslib.widget.preference.barchart.R;
/**
* A class responsible for saving bar view information.
*/
public class BarViewInfo implements Comparable<BarViewInfo> {
private final Drawable mIcon;
private View.OnClickListener mClickListener;
private CharSequence mTitle;
private CharSequence mSummary;
private @Nullable CharSequence mContentDescription;
// A number indicates this bar's height. The larger number shows a higher bar view.
private int mHeight;
// A real height of bar view.
private int mNormalizedHeight;
/**
* Construct a BarViewInfo instance.
*
* @param icon The icon of bar view.
* @param barHeight The height of bar view. Larger number shows a higher bar view.
* @param title The string for title. If this is null, use the height of the bar.
* @param summary The string for summary.
* @param contentDescription Optional text that briefly describes the contents of the icon.
*/
public BarViewInfo(Drawable icon, @IntRange(from = 0) int barHeight,
@Nullable CharSequence title, CharSequence summary,
@Nullable CharSequence contentDescription) {
mIcon = icon;
mHeight = barHeight;
mTitle = title;
mSummary = summary;
mContentDescription = contentDescription;
}
/**
* Set a click listener for bar view.
*/
public void setClickListener(@Nullable View.OnClickListener listener) {
mClickListener = listener;
}
@Override
public int compareTo(BarViewInfo other) {
// Descending order
return Comparator.comparingInt((BarViewInfo barViewInfo) -> barViewInfo.mHeight)
.compare(other, this);
}
void setHeight(@IntRange(from = 0) int height) {
mHeight = height;
}
void setTitle(CharSequence title) {
mTitle = title;
}
void setSummary(CharSequence summary) {
mSummary = summary;
}
Drawable getIcon() {
return mIcon;
}
int getHeight() {
return mHeight;
}
View.OnClickListener getClickListener() {
return mClickListener;
}
@Nullable
CharSequence getTitle() {
return mTitle;
}
CharSequence getSummary() {
return mSummary;
}
public @Nullable CharSequence getContentDescription() {
return mContentDescription;
}
void setNormalizedHeight(@IntRange(from = 0) int barHeight) {
mNormalizedHeight = barHeight;
}
int getNormalizedHeight() {
return mNormalizedHeight;
}
}