1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.storagemanager.deletionhelper; 18 19import android.app.Activity; 20import android.app.Fragment; 21import android.app.FragmentManager; 22import android.os.Bundle; 23import android.text.SpannableString; 24import android.text.Spanned; 25import android.text.TextPaint; 26import android.text.style.ClickableSpan; 27import android.util.DisplayMetrics; 28import android.view.View; 29import android.view.ViewGroup; 30import android.widget.Button; 31import android.widget.TextView.BufferType; 32import com.android.settingslib.widget.LinkTextView; 33import com.android.storagemanager.ButtonBarProvider; 34import com.android.storagemanager.R; 35 36/** 37 * The DeletionHelperActivity is an activity for deleting apps, photos, and downloaded files which 38 * have not been recently used. 39 */ 40public class DeletionHelperActivity extends Activity implements ButtonBarProvider { 41 42 private ViewGroup mButtonBar; 43 private Button mNextButton, mSkipButton; 44 private DeletionHelperSettings mFragment; 45 46 @Override 47 protected void onCreate(Bundle savedInstanceState) { 48 super.onCreate(savedInstanceState); 49 setContentView(R.layout.settings_main_prefs); 50 51 setIsEmptyState(false /* isEmptyState */); 52 53 // If we are not returning from an existing activity, create a new fragment. 54 if (savedInstanceState == null) { 55 FragmentManager manager = getFragmentManager(); 56 mFragment = DeletionHelperSettings.newInstance(AppsAsyncLoader.NORMAL_THRESHOLD); 57 manager.beginTransaction().replace(R.id.main_content, mFragment).commit(); 58 } 59 SpannableString linkText = 60 new SpannableString( 61 getString(R.string.empty_state_review_items_link).toUpperCase()); 62 LinkTextView emptyStateLink = (LinkTextView) findViewById(R.id.all_items_link); 63 linkText = NoThresholdSpan.linkify(linkText, this); 64 emptyStateLink.setText(linkText, BufferType.SPANNABLE); 65 66 mButtonBar = (ViewGroup) findViewById(R.id.button_bar); 67 mNextButton = (Button) findViewById(R.id.next_button); 68 mSkipButton = (Button) findViewById(R.id.skip_button); 69 } 70 71 @Override 72 public void onRequestPermissionsResult( 73 int requestCode, String permissions[], int[] grantResults) { 74 super.onRequestPermissionsResult(requestCode, permissions, grantResults); 75 mFragment.onRequestPermissionsResult(requestCode, permissions, grantResults); 76 } 77 78 void setIsEmptyState(boolean isEmptyState) { 79 final View emptyContent = findViewById(R.id.empty_state); 80 final View mainContent = findViewById(R.id.main_content); 81 // Check if we need to animate now since we will modify visibility before the animation 82 // starts 83 final boolean shouldAnimate = isEmptyState && emptyContent.getVisibility() != View.VISIBLE; 84 85 // Update UI 86 mainContent.setVisibility(isEmptyState ? View.GONE : View.VISIBLE); 87 emptyContent.setVisibility(isEmptyState ? View.VISIBLE : View.GONE); 88 findViewById(R.id.button_bar).setVisibility(isEmptyState ? View.GONE : View.VISIBLE); 89 setTitle(isEmptyState ? R.string.empty_state_title : R.string.deletion_helper_title); 90 91 // Animate UI changes 92 if (!shouldAnimate) { 93 return; 94 } 95 animateToEmptyState(); 96 } 97 98 private void animateToEmptyState() { 99 View content = findViewById(R.id.empty_state); 100 101 // Animate the empty state in 102 DisplayMetrics displayMetrics = new DisplayMetrics(); 103 getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); 104 final float oldX = content.getTranslationX(); 105 content.setTranslationX(oldX + displayMetrics.widthPixels); 106 content.animate() 107 .translationX(oldX) 108 .withEndAction( 109 () -> { 110 content.setTranslationX(oldX); 111 }); 112 } 113 114 @Override 115 public ViewGroup getButtonBar() { 116 return mButtonBar; 117 } 118 119 @Override 120 public Button getNextButton() { 121 return mNextButton; 122 } 123 124 @Override 125 public Button getSkipButton() { 126 return mSkipButton; 127 } 128 129 private static class NoThresholdSpan extends ClickableSpan { 130 private final DeletionHelperActivity mParent; 131 132 public NoThresholdSpan(DeletionHelperActivity parent) { 133 super(); 134 mParent = parent; 135 } 136 137 @Override 138 public void onClick(View widget) { 139 FragmentManager manager = mParent.getFragmentManager(); 140 Fragment fragment = DeletionHelperSettings.newInstance(AppsAsyncLoader.NO_THRESHOLD); 141 manager.beginTransaction().replace(R.id.main_content, fragment).commit(); 142 mParent.setIsEmptyState(false); 143 } 144 145 @Override 146 public void updateDrawState(TextPaint ds) { 147 super.updateDrawState(ds); 148 // Remove underline 149 ds.setUnderlineText(false); 150 } 151 152 /** 153 * This method takes a string and turns it into a url span that will launch a 154 * SupportSystemInformationDialogFragment 155 * 156 * @param msg The text to turn into a link 157 * @param parent The dialog the text is in 158 * @return A CharSequence containing the original text content as a url 159 */ 160 public static SpannableString linkify(SpannableString msg, DeletionHelperActivity parent) { 161 NoThresholdSpan link = new NoThresholdSpan(parent); 162 msg.setSpan(link, 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 163 return msg; 164 } 165 } 166}