1 package com.android.packageinstaller.permission.ui; 2 3 import android.annotation.Nullable; 4 import android.os.Bundle; 5 import android.support.v14.preference.PreferenceFragment; 6 import android.support.v17.leanback.widget.VerticalGridView; 7 import android.support.v7.preference.PreferenceScreen; 8 import android.support.v7.widget.RecyclerView; 9 import android.support.v7.widget.RecyclerView.AdapterDataObserver; 10 import android.view.LayoutInflater; 11 import android.view.View; 12 import android.view.ViewGroup; 13 import android.view.animation.Animation; 14 import android.view.animation.Animation.AnimationListener; 15 import android.view.animation.AnimationUtils; 16 import android.widget.TextView; 17 18 import com.android.packageinstaller.R; 19 import com.android.packageinstaller.permission.utils.Utils; 20 21 public abstract class PermissionsFrameFragment extends PreferenceFragment { 22 23 private static final float WINDOW_ALIGNMENT_OFFSET_PERCENT = 50; 24 25 private ViewGroup mPreferencesContainer; 26 27 // TV-specific instance variables 28 @Nullable private VerticalGridView mGridView; 29 30 private View mLoadingView; 31 private ViewGroup mPrefsView; 32 private boolean mIsLoading; 33 34 /** 35 * Returns the view group that holds the preferences objects. This will 36 * only be set after {@link #onCreateView} has been called. 37 */ 38 protected final ViewGroup getPreferencesContainer() { 39 return mPreferencesContainer; 40 } 41 42 @Override 43 public View onCreateView(LayoutInflater inflater, ViewGroup container, 44 Bundle savedInstanceState) { 45 ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, 46 false); 47 mPrefsView = (ViewGroup) rootView.findViewById(R.id.prefs_container); 48 if (mPrefsView == null) { 49 mPrefsView = rootView; 50 } 51 mLoadingView = rootView.findViewById(R.id.loading_container); 52 mPreferencesContainer = (ViewGroup) super.onCreateView( 53 inflater, mPrefsView, savedInstanceState); 54 setLoading(mIsLoading, false, true /* force */); 55 mPrefsView.addView(mPreferencesContainer); 56 return rootView; 57 } 58 59 @Override 60 public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) { 61 PreferenceScreen preferences = getPreferenceScreen(); 62 if (preferences == null) { 63 preferences = getPreferenceManager().createPreferenceScreen(getActivity()); 64 setPreferenceScreen(preferences); 65 } 66 } 67 68 protected void setLoading(boolean loading, boolean animate) { 69 setLoading(loading, animate, false); 70 } 71 72 private void setLoading(boolean loading, boolean animate, boolean force) { 73 if (mIsLoading != loading || force) { 74 mIsLoading = loading; 75 if (getView() == null) { 76 // If there is no created view, there is no reason to animate. 77 animate = false; 78 } 79 if (mPrefsView != null) { 80 setViewShown(mPrefsView, !loading, animate); 81 } 82 if (mLoadingView != null) { 83 setViewShown(mLoadingView, loading, animate); 84 } 85 } 86 } 87 88 private void setViewShown(final View view, boolean shown, boolean animate) { 89 if (animate) { 90 Animation animation = AnimationUtils.loadAnimation(getContext(), 91 shown ? android.R.anim.fade_in : android.R.anim.fade_out); 92 if (shown) { 93 view.setVisibility(View.VISIBLE); 94 } else { 95 animation.setAnimationListener(new AnimationListener() { 96 @Override 97 public void onAnimationStart(Animation animation) { 98 } 99 100 @Override 101 public void onAnimationRepeat(Animation animation) { 102 } 103 104 @Override 105 public void onAnimationEnd(Animation animation) { 106 view.setVisibility(View.INVISIBLE); 107 } 108 }); 109 } 110 view.startAnimation(animation); 111 } else { 112 view.clearAnimation(); 113 view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE); 114 } 115 } 116 117 @Override 118 public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, 119 Bundle savedInstanceState) { 120 if (Utils.isTelevision(getContext())) { 121 mGridView = (VerticalGridView) inflater.inflate( 122 R.layout.leanback_preferences_list, parent, false); 123 mGridView.setWindowAlignmentOffset(0); 124 mGridView.setWindowAlignmentOffsetPercent(WINDOW_ALIGNMENT_OFFSET_PERCENT); 125 mGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE); 126 mGridView.setFocusScrollStrategy(VerticalGridView.FOCUS_SCROLL_ALIGNED); 127 return mGridView; 128 } else { 129 return super.onCreateRecyclerView(inflater, parent, savedInstanceState); 130 } 131 } 132 133 @Override 134 protected RecyclerView.Adapter<?> onCreateAdapter(PreferenceScreen preferenceScreen) { 135 final RecyclerView.Adapter<?> adapter = super.onCreateAdapter(preferenceScreen); 136 137 if (adapter != null) { 138 final TextView emptyView = (TextView) getView().findViewById(R.id.no_permissions); 139 onSetEmptyText(emptyView); 140 final RecyclerView recyclerView = getListView(); 141 adapter.registerAdapterDataObserver(new AdapterDataObserver() { 142 @Override 143 public void onChanged() { 144 checkEmpty(); 145 } 146 147 @Override 148 public void onItemRangeInserted(int positionStart, int itemCount) { 149 checkEmpty(); 150 } 151 152 @Override 153 public void onItemRangeRemoved(int positionStart, int itemCount) { 154 checkEmpty(); 155 } 156 157 private void checkEmpty() { 158 boolean isEmpty = adapter.getItemCount() == 0; 159 emptyView.setVisibility(isEmpty ? View.VISIBLE : View.GONE); 160 recyclerView.setVisibility(isEmpty ? View.GONE : View.VISIBLE); 161 if (!isEmpty && mGridView != null) { 162 mGridView.requestFocus(); 163 } 164 } 165 }); 166 167 boolean isEmpty = adapter.getItemCount() == 0; 168 emptyView.setVisibility(isEmpty ? View.VISIBLE : View.GONE); 169 recyclerView.setVisibility(isEmpty ? View.GONE : View.VISIBLE); 170 if (!isEmpty && mGridView != null) { 171 mGridView.requestFocus(); 172 } 173 } 174 175 return adapter; 176 } 177 178 /** 179 * Hook for subclasses to change the default text of the empty view. 180 * Base implementation leaves the default empty view text. 181 * 182 * @param textView the empty text view 183 */ 184 protected void onSetEmptyText(TextView textView) { 185 } 186 } 187 188