Add a collapsible checkbox preference for deletion helper.
This adds a custom preference group which has both a checkbox and collapse/expand behavior. This is intended to be used in the deletion helper for apps deletion and downloads folder deletion. This patch implements the apps deletion integration. Bug: 28769691 Change-Id: I9fb28a1baa4067841742b5dbeaf2083728c16144
This commit is contained in:
25
res/drawable/ic_keyboard_arrow_down_black_32.xml
Normal file
25
res/drawable/ic_keyboard_arrow_down_black_32.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M7.41,7.84L12,12.42l4.59,-4.58L18,9.25l-6,6 -6,-6z"/>
|
||||
</vector>
|
25
res/drawable/ic_keyboard_arrow_up_black_32.xml
Normal file
25
res/drawable/ic_keyboard_arrow_up_black_32.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
|
||||
</vector>
|
@@ -7620,4 +7620,10 @@
|
||||
<!-- Button to activate the storage manager on the storage manager upsell. [CHAR LIMIT=20]-->
|
||||
<string name="deletion_helper_upsell_activate">Turn on</string>
|
||||
|
||||
<!-- Title for the apps category in the deletion helper, showing how many apps to delete. [CHAR LIMIT=40]-->
|
||||
<string name="deletion_helper_apps_group_title">Apps (<xliff:g id="num_items">%1$d</xliff:g>)</string>
|
||||
|
||||
<!-- Summary for the apps category in the deletion helper, showing how many space to clear. [CHAR LIMIT=NONE]-->
|
||||
<string name="deletion_helper_apps_group_summary"><xliff:g id="used" example="1.2GB">%1$s</xliff:g></string>
|
||||
|
||||
</resources>
|
||||
|
@@ -23,8 +23,8 @@
|
||||
<com.android.settings.deletionhelper.DownloadsDeletionPreference
|
||||
android:key="delete_downloads" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="apps_group"
|
||||
android:title="@string/deletion_helper_apps_title" />
|
||||
<com.android.settings.CollapsibleCheckboxPreferenceGroup
|
||||
android:key="apps_group"
|
||||
android:icon="@drawable/ic_keyboard_arrow_down_black_32"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
147
src/com/android/settings/CollapsibleCheckboxPreferenceGroup.java
Normal file
147
src/com/android/settings/CollapsibleCheckboxPreferenceGroup.java
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.Checkable;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* CollapsibleCheckboxPreferenceGroup is a preference group that can be expanded or collapsed and
|
||||
* also has a checkbox.
|
||||
*/
|
||||
public class CollapsibleCheckboxPreferenceGroup extends PreferenceGroup implements
|
||||
View.OnClickListener {
|
||||
private boolean mCollapsed;
|
||||
private boolean mChecked;
|
||||
|
||||
public CollapsibleCheckboxPreferenceGroup(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public CollapsibleCheckboxPreferenceGroup(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setWidgetLayoutResource(com.android.settings.R.layout.preference_widget_checkbox);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
View checkbox = holder.findViewById(com.android.internal.R.id.checkbox);
|
||||
if (checkbox != null && checkbox instanceof Checkable) {
|
||||
((Checkable) checkbox).setChecked(mChecked);
|
||||
checkbox.setClickable(true);
|
||||
checkbox.setFocusable(true);
|
||||
checkbox.setOnClickListener(this);
|
||||
}
|
||||
|
||||
final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
|
||||
if (titleView != null) {
|
||||
Context context = getContext();
|
||||
TypedValue value = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.colorAccent, value, true);
|
||||
titleView.setTextColor(context.getColor(value.resourceId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPreference(Preference p) {
|
||||
super.addPreference(p);
|
||||
p.setVisible(!isCollapsed());
|
||||
return true;
|
||||
}
|
||||
|
||||
// The preference click handler.
|
||||
@Override
|
||||
protected void onClick() {
|
||||
super.onClick();
|
||||
setCollapse(!isCollapsed());
|
||||
}
|
||||
|
||||
// The checkbox view click handler.
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the view is collapsed.
|
||||
*/
|
||||
public boolean isCollapsed() {
|
||||
return mCollapsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the checked state of the preference.
|
||||
*/
|
||||
public boolean isChecked() {
|
||||
return mChecked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the checked state and notifies listeners of the state change.
|
||||
*/
|
||||
public void setChecked(boolean checked) {
|
||||
if (mChecked != checked) {
|
||||
mChecked = checked;
|
||||
|
||||
callChangeListener(checked);
|
||||
notifyDependencyChange(shouldDisableDependents());
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void setCollapse(boolean isCollapsed) {
|
||||
if (mCollapsed == isCollapsed) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCollapsed = isCollapsed;
|
||||
if (isCollapsed) {
|
||||
hideDropdownPreferences();
|
||||
} else {
|
||||
showDropdownPreferences();
|
||||
}
|
||||
}
|
||||
|
||||
private void showDropdownPreferences() {
|
||||
setAllPreferencesVisibility(true);
|
||||
setIcon(R.drawable.ic_keyboard_arrow_down_black_32);
|
||||
}
|
||||
|
||||
private void hideDropdownPreferences() {
|
||||
setAllPreferencesVisibility(false);
|
||||
setIcon(R.drawable.ic_keyboard_arrow_up_black_32);
|
||||
}
|
||||
|
||||
private void setAllPreferencesVisibility(boolean visible) {
|
||||
for (int i = 0; i < getPreferenceCount(); i++) {
|
||||
Preference p = getPreference(i);
|
||||
p.setVisible(visible);
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,17 +16,18 @@
|
||||
|
||||
package com.android.settings.deletionhelper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.text.format.Formatter;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import com.android.settings.deletionhelper.DownloadsDeletionPreference;
|
||||
import com.android.settings.CollapsibleCheckboxPreferenceGroup;
|
||||
import com.android.settings.PhotosDeletionPreference;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.R;
|
||||
@@ -65,7 +66,7 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
|
||||
private static final int DOWNLOADS_LOADER_ID = 1;
|
||||
|
||||
private Button mCancel, mFree;
|
||||
private PreferenceGroup mApps;
|
||||
private CollapsibleCheckboxPreferenceGroup mApps;
|
||||
private PhotosDeletionPreference mPhotoPreference;
|
||||
private DownloadsDeletionPreference mDownloadsPreference;
|
||||
|
||||
@@ -82,6 +83,7 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setAnimationAllowed(true);
|
||||
Application app = getActivity().getApplication();
|
||||
mState = ApplicationsState.getInstance(app);
|
||||
mSession = mState.newSession(this);
|
||||
@@ -89,7 +91,7 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
|
||||
mDataUsageBridge = new AppStateUsageStatsBridge(getActivity(), mState, this);
|
||||
|
||||
addPreferencesFromResource(R.xml.deletion_helper_list);
|
||||
mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
|
||||
mApps = (CollapsibleCheckboxPreferenceGroup) findPreference(KEY_APPS_GROUP);
|
||||
mPhotoPreference = (PhotosDeletionPreference) findPreference(KEY_PHOTOS_VIDEOS_PREFERENCE);
|
||||
mDownloadsPreference =
|
||||
(DownloadsDeletionPreference) findPreference(KEY_DOWNLOADS_PREFERENCE);
|
||||
@@ -131,6 +133,7 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
|
||||
|
||||
mDownloadsPreference.registerFreeableChangedListener(this);
|
||||
mDownloadsPreference.registerDeletionService(mDownloadsDeletion);
|
||||
mApps.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -191,24 +194,7 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
|
||||
ApplicationsState.SIZE_COMPARATOR);
|
||||
if (apps == null) return;
|
||||
mAppEntries = apps;
|
||||
cacheRemoveAllPrefs(mApps);
|
||||
int entryCount = apps.size();
|
||||
for (int i = 0; i < entryCount; i++) {
|
||||
AppEntry entry = apps.get(i);
|
||||
final String packageName = entry.label;
|
||||
AppDeletionPreference preference =
|
||||
(AppDeletionPreference) getCachedPreference(entry.label);
|
||||
if (preference == null) {
|
||||
preference = new AppDeletionPreference(getActivity(), entry,
|
||||
mState);
|
||||
preference.setKey(packageName);
|
||||
preference.setChecked(mCheckedApplications.contains(packageName));
|
||||
preference.setOnPreferenceChangeListener(this);
|
||||
mApps.addPreference(preference);
|
||||
}
|
||||
preference.setOrder(i);
|
||||
}
|
||||
removeCachedPrefs(mApps);
|
||||
refreshAppGroup(apps);
|
||||
|
||||
// All applications should be filled in if we've received the sizes.
|
||||
// setLoading being called multiple times causes flickering, so we only do it once.
|
||||
@@ -277,11 +263,20 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean checked = (boolean) newValue;
|
||||
if (preference.getKey().equals(mApps.getKey())) {
|
||||
return toggleAllApps(checked);
|
||||
}
|
||||
|
||||
String packageName = ((AppDeletionPreference) preference).getPackageName();
|
||||
if (checked) {
|
||||
mCheckedApplications.add(packageName);
|
||||
} else {
|
||||
mCheckedApplications.remove(packageName);
|
||||
|
||||
// We remove the preference change listener to avoid toggling every app on and off.
|
||||
mApps.setOnPreferenceChangeListener(null);
|
||||
mApps.setChecked(false);
|
||||
mApps.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
updateFreeButtonText();
|
||||
return true;
|
||||
@@ -346,17 +341,7 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
|
||||
|
||||
private long getTotalFreeableSpace() {
|
||||
long freeableSpace = 0;
|
||||
if (mAppEntries != null) {
|
||||
|
||||
for (int i = 0; i < mAppEntries.size(); i++) {
|
||||
final AppEntry entry = mAppEntries.get(i);
|
||||
long entrySize = mAppEntries.get(i).size;
|
||||
// If the entrySize is negative, it is either an unknown size or an error occurred.
|
||||
if (mCheckedApplications.contains(entry.label) && entrySize > 0) {
|
||||
freeableSpace += entrySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
freeableSpace += getTotalAppsFreeableSpace(false);
|
||||
if (mPhotoPreference != null) {
|
||||
freeableSpace += mPhotoPreference.getFreeableBytes();
|
||||
}
|
||||
@@ -365,4 +350,67 @@ public class DeletionHelperFragment extends SettingsPreferenceFragment implement
|
||||
}
|
||||
return freeableSpace;
|
||||
}
|
||||
|
||||
private void refreshAppGroup(ArrayList<AppEntry> apps) {
|
||||
int entryCount = apps.size();
|
||||
cacheRemoveAllPrefs(mApps);
|
||||
for (int i = 0; i < entryCount; i++) {
|
||||
AppEntry entry = apps.get(i);
|
||||
final String packageName = entry.label;
|
||||
AppDeletionPreference preference =
|
||||
(AppDeletionPreference) getCachedPreference(entry.label);
|
||||
if (preference == null) {
|
||||
preference = new AppDeletionPreference(getActivity(), entry, mState);
|
||||
preference.setKey(packageName);
|
||||
preference.setOnPreferenceChangeListener(this);
|
||||
mApps.addPreference(preference);
|
||||
}
|
||||
preference.setChecked(mCheckedApplications.contains(packageName));
|
||||
preference.setOrder(i);
|
||||
}
|
||||
removeCachedPrefs(mApps);
|
||||
updateAppsGroupText();
|
||||
}
|
||||
|
||||
private long getTotalAppsFreeableSpace(boolean countUnchecked) {
|
||||
long freeableSpace = 0;
|
||||
if (mAppEntries != null) {
|
||||
for (int i = 0; i < mAppEntries.size(); i++) {
|
||||
final AppEntry entry = mAppEntries.get(i);
|
||||
long entrySize = mAppEntries.get(i).size;
|
||||
// If the entrySize is negative, it is either an unknown size or an error occurred.
|
||||
if ((countUnchecked ||
|
||||
mCheckedApplications.contains(entry.label)) && entrySize > 0) {
|
||||
freeableSpace += entrySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return freeableSpace;
|
||||
}
|
||||
|
||||
private void updateAppsGroupText() {
|
||||
if (mAppEntries != null) {
|
||||
Activity app = getActivity();
|
||||
mApps.setTitle(app.getString(R.string.deletion_helper_apps_group_title,
|
||||
mAppEntries.size()));
|
||||
mApps.setSummary(app.getString(R.string.deletion_helper_apps_group_summary,
|
||||
Formatter.formatFileSize(app,
|
||||
getTotalAppsFreeableSpace(true))));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean toggleAllApps(boolean checked) {
|
||||
for (AppEntry entry : mAppEntries) {
|
||||
final String packageName = entry.label;
|
||||
if (checked) {
|
||||
mCheckedApplications.add(packageName);
|
||||
} else {
|
||||
mCheckedApplications.remove(packageName);
|
||||
}
|
||||
}
|
||||
refreshAppGroup(mAppEntries);
|
||||
updateFreeButtonText();
|
||||
return true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user