/* * 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.Resources; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.annotation.VisibleForTesting; /** * This class is used to initialize view which was inflated * from {@link R.xml.app_entities_header.xml}. * *
How to use AppEntitiesHeaderController? * *
1. Add a {@link LayoutPreference} in layout XML file. *
* <com.android.settingslib.widget.LayoutPreference * android:key="app_entities_header" * android:layout="@layout/app_entities_header"/> ** *
2. Use AppEntitiesHeaderController to call below methods, then you can initialize
* view of app_entities_header
.
*
*
* * View headerView = ((LayoutPreference) screen.findPreference("app_entities_header")) * .findViewById(R.id.app_entities_header); * * final AppEntityInfo appEntityInfo = new AppEntityInfo.Builder() * .setIcon(icon) * .setTitle(title) * .setSummary(summary) * .setOnClickListener(view -> doSomething()) * .build(); * * AppEntitiesHeaderController.newInstance(context, headerView) * .setHeaderTitleRes(R.string.xxxxx) * .setHeaderDetailsRes(R.string.xxxxx) * .setHeaderDetailsClickListener(onClickListener) * .setAppEntity(0, appEntityInfo) * .setAppEntity(1, appEntityInfo) * .setAppEntity(2, appEntityInfo) * .apply(); **/ public class AppEntitiesHeaderController { private static final String TAG = "AppEntitiesHeaderCtl"; @VisibleForTesting public static final int MAXIMUM_APPS = 3; private final Context mContext; private final TextView mHeaderTitleView; private final TextView mHeaderEmptyView; private final Button mHeaderDetailsView; private final AppEntityInfo[] mAppEntityInfos; private final View mAppViewsContainer; private final View[] mAppEntityViews; private final ImageView[] mAppIconViews; private final TextView[] mAppTitleViews; private final TextView[] mAppSummaryViews; private int mHeaderTitleRes; private int mHeaderDetailsRes; private int mHeaderEmptyRes; private CharSequence mHeaderDetails; private View.OnClickListener mDetailsOnClickListener; /** * Creates a new instance of the controller. * * @param context the Context the view is running in * @param appEntitiesHeaderView view was inflated from
app_entities_header
*/
public static AppEntitiesHeaderController newInstance(@NonNull Context context,
@NonNull View appEntitiesHeaderView) {
return new AppEntitiesHeaderController(context, appEntitiesHeaderView);
}
private AppEntitiesHeaderController(Context context, View appEntitiesHeaderView) {
mContext = context;
mHeaderTitleView = appEntitiesHeaderView.findViewById(R.id.header_title);
mHeaderDetailsView = appEntitiesHeaderView.findViewById(R.id.header_details);
mHeaderEmptyView = appEntitiesHeaderView.findViewById(R.id.empty_view);
mAppViewsContainer = appEntitiesHeaderView.findViewById(R.id.app_views_container);
mAppEntityInfos = new AppEntityInfo[MAXIMUM_APPS];
mAppIconViews = new ImageView[MAXIMUM_APPS];
mAppTitleViews = new TextView[MAXIMUM_APPS];
mAppSummaryViews = new TextView[MAXIMUM_APPS];
mAppEntityViews = new View[]{
appEntitiesHeaderView.findViewById(R.id.app1_view),
appEntitiesHeaderView.findViewById(R.id.app2_view),
appEntitiesHeaderView.findViewById(R.id.app3_view)
};
// Initialize view in advance, so we won't take too much time to do it when controller is
// binding view.
for (int index = 0; index < MAXIMUM_APPS; index++) {
final View appView = mAppEntityViews[index];
mAppIconViews[index] = (ImageView) appView.findViewById(R.id.app_icon);
mAppTitleViews[index] = (TextView) appView.findViewById(R.id.app_title);
mAppSummaryViews[index] = (TextView) appView.findViewById(R.id.app_summary);
}
}
/**
* Set the text resource for app entities header title.
*/
public AppEntitiesHeaderController setHeaderTitleRes(@StringRes int titleRes) {
mHeaderTitleRes = titleRes;
return this;
}
/**
* Set the text resource for app entities header details.
*/
public AppEntitiesHeaderController setHeaderDetailsRes(@StringRes int detailsRes) {
mHeaderDetailsRes = detailsRes;
return this;
}
/**
* Set the text for app entities header details.
*/
public AppEntitiesHeaderController setHeaderDetails(CharSequence detailsText) {
mHeaderDetails = detailsText;
return this;
}
/**
* Register a callback to be invoked when header details view is clicked.
*/
public AppEntitiesHeaderController setHeaderDetailsClickListener(
@Nullable View.OnClickListener clickListener) {
mDetailsOnClickListener = clickListener;
return this;
}
/**
* Sets the string resource id for the empty text.
*/
public AppEntitiesHeaderController setHeaderEmptyRes(@StringRes int emptyRes) {
mHeaderEmptyRes = emptyRes;
return this;
}
/**
* Set an app entity at a specified position view.
*
* @param index the index at which the specified view is to be inserted
* @param appEntityInfo the information of an app entity
* @return this {@code AppEntitiesHeaderController} object
*/
public AppEntitiesHeaderController setAppEntity(int index,
@NonNull AppEntityInfo appEntityInfo) {
mAppEntityInfos[index] = appEntityInfo;
return this;
}
/**
* Remove an app entity at a specified position view.
*
* @param index the index at which the specified view is to be removed
* @return this {@code AppEntitiesHeaderController} object
*/
public AppEntitiesHeaderController removeAppEntity(int index) {
mAppEntityInfos[index] = null;
return this;
}
/**
* Clear all app entities in app entities header.
*
* @return this {@code AppEntitiesHeaderController} object
*/
public AppEntitiesHeaderController clearAllAppEntities() {
for (int index = 0; index < MAXIMUM_APPS; index++) {
removeAppEntity(index);
}
return this;
}
/**
* Done mutating app entities header, rebinds everything.
*/
public void apply() {
bindHeaderTitleView();
if (isAppEntityInfosEmpty()) {
setEmptyViewVisible(true);
return;
}
setEmptyViewVisible(false);
bindHeaderDetailsView();
// Rebind all apps view
for (int index = 0; index < MAXIMUM_APPS; index++) {
bindAppEntityView(index);
}
}
private void bindHeaderTitleView() {
CharSequence titleText = "";
try {
titleText = mContext.getText(mHeaderTitleRes);
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Resource of header title can't not be found!", e);
}
mHeaderTitleView.setText(titleText);
mHeaderTitleView.setVisibility(
TextUtils.isEmpty(titleText) ? View.GONE : View.VISIBLE);
}
private void bindHeaderDetailsView() {
CharSequence detailsText = mHeaderDetails;
if (TextUtils.isEmpty(detailsText)) {
try {
detailsText = mContext.getText(mHeaderDetailsRes);
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Resource of header details can't not be found!", e);
}
}
mHeaderDetailsView.setText(detailsText);
mHeaderDetailsView.setVisibility(
TextUtils.isEmpty(detailsText) ? View.GONE : View.VISIBLE);
mHeaderDetailsView.setOnClickListener(mDetailsOnClickListener);
}
private void bindAppEntityView(int index) {
final AppEntityInfo appEntityInfo = mAppEntityInfos[index];
mAppEntityViews[index].setVisibility(appEntityInfo != null ? View.VISIBLE : View.GONE);
if (appEntityInfo != null) {
mAppEntityViews[index].setOnClickListener(appEntityInfo.getClickListener());
mAppIconViews[index].setImageDrawable(appEntityInfo.getIcon());
final CharSequence title = appEntityInfo.getTitle();
mAppTitleViews[index].setVisibility(
TextUtils.isEmpty(title) ? View.INVISIBLE : View.VISIBLE);
mAppTitleViews[index].setText(title);
final CharSequence summary = appEntityInfo.getSummary();
mAppSummaryViews[index].setVisibility(
TextUtils.isEmpty(summary) ? View.INVISIBLE : View.VISIBLE);
mAppSummaryViews[index].setText(summary);
}
}
private void setEmptyViewVisible(boolean visible) {
if (mHeaderEmptyRes != 0) {
mHeaderEmptyView.setText(mHeaderEmptyRes);
}
mHeaderEmptyView.setVisibility(visible ? View.VISIBLE : View.GONE);
mHeaderDetailsView.setVisibility(visible ? View.GONE : View.VISIBLE);
mAppViewsContainer.setVisibility(visible ? View.GONE : View.VISIBLE);
}
private boolean isAppEntityInfosEmpty() {
for (AppEntityInfo info : mAppEntityInfos) {
if (info != null) {
return false;
}
}
return true;
}
}