QSCustomizer.java revision deba7a42ed9fdde9017f2b627fc5f63a31a82c4b
1/* 2 * Copyright (C) 2015 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 */ 16package com.android.systemui.qs.customize; 17 18import android.animation.Animator; 19import android.content.ClipData; 20import android.content.Context; 21import android.content.DialogInterface; 22import android.content.DialogInterface.OnCancelListener; 23import android.content.DialogInterface.OnDismissListener; 24import android.util.AttributeSet; 25import android.util.Log; 26import android.util.TypedValue; 27import android.view.ContextThemeWrapper; 28import android.view.DragEvent; 29import android.view.LayoutInflater; 30import android.view.Menu; 31import android.view.MenuItem; 32import android.view.View; 33import android.view.View.OnClickListener; 34import android.view.ViewGroup; 35import android.view.WindowManager; 36import android.widget.LinearLayout; 37import android.widget.ListView; 38import android.widget.Toolbar; 39import android.widget.Toolbar.OnMenuItemClickListener; 40import com.android.systemui.R; 41import com.android.systemui.qs.QSDetailClipper; 42import com.android.systemui.qs.QSTile.Host.Callback; 43import com.android.systemui.qs.customize.DropButton.OnDropListener; 44import com.android.systemui.qs.customize.TileAdapter.TileSelectedListener; 45import com.android.systemui.statusbar.phone.PhoneStatusBar; 46import com.android.systemui.statusbar.phone.QSTileHost; 47import com.android.systemui.statusbar.phone.SystemUIDialog; 48import com.android.systemui.tuner.QSPagingSwitch; 49 50import java.util.ArrayList; 51 52/** 53 * Allows full-screen customization of QS, through show() and hide(). 54 * 55 * This adds itself to the status bar window, so it can appear on top of quick settings and 56 * *someday* do fancy animations to get into/out of it. 57 */ 58public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener, Callback, 59 OnDropListener, OnClickListener, Animator.AnimatorListener, TileSelectedListener, 60 OnCancelListener, OnDismissListener { 61 62 private static final int MENU_SAVE = Menu.FIRST; 63 private static final int MENU_RESET = Menu.FIRST + 1; 64 private final QSDetailClipper mClipper; 65 66 private PhoneStatusBar mPhoneStatusBar; 67 68 private Toolbar mToolbar; 69 private ViewGroup mDragButtons; 70 private CustomQSPanel mQsPanel; 71 72 private boolean isShown; 73 private DropButton mInfoButton; 74 private DropButton mRemoveButton; 75 private FloatingActionButton mFab; 76 private SystemUIDialog mDialog; 77 private QSTileHost mHost; 78 79 public QSCustomizer(Context context, AttributeSet attrs) { 80 super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs); 81 mClipper = new QSDetailClipper(this); 82 } 83 84 public void setHost(QSTileHost host) { 85 mHost = host; 86 mHost.addCallback(this); 87 mPhoneStatusBar = host.getPhoneStatusBar(); 88 mQsPanel.setTiles(mHost.getTiles()); 89 mQsPanel.setHost(mHost); 90 mQsPanel.setSavedTiles(); 91 } 92 93 @Override 94 protected void onFinishInflate() { 95 super.onFinishInflate(); 96 mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar); 97 TypedValue value = new TypedValue(); 98 mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true); 99 mToolbar.setNavigationIcon( 100 getResources().getDrawable(R.drawable.ic_close_white, mContext.getTheme())); 101 mToolbar.setNavigationOnClickListener(new OnClickListener() { 102 @Override 103 public void onClick(View v) { 104 hide(0, 0); 105 } 106 }); 107 mToolbar.setOnMenuItemClickListener(this); 108 mToolbar.getMenu().add(Menu.NONE, MENU_SAVE, 0, mContext.getString(R.string.save)) 109 .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); 110 mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0, 111 mContext.getString(com.android.internal.R.string.reset)); 112 113 mQsPanel = (CustomQSPanel) findViewById(R.id.quick_settings_panel); 114 115 mDragButtons = (ViewGroup) findViewById(R.id.drag_buttons); 116 setDragging(false); 117 118 mInfoButton = (DropButton) findViewById(R.id.info_button); 119 mInfoButton.setOnDropListener(this); 120 mRemoveButton = (DropButton) findViewById(R.id.remove_button); 121 mRemoveButton.setOnDropListener(this); 122 123 mFab = (FloatingActionButton) findViewById(R.id.fab); 124 mFab.setImageResource(R.drawable.ic_add); 125 mFab.setOnClickListener(this); 126 } 127 128 public void show(int x, int y) { 129 isShown = true; 130 mQsPanel.setSavedTiles(); 131 mPhoneStatusBar.getStatusBarWindow().addView(this); 132 mQsPanel.setListening(true); 133 mClipper.animateCircularClip(x, y, true, this); 134 } 135 136 public void hide(int x, int y) { 137 isShown = false; 138 mQsPanel.setListening(false); 139 mClipper.animateCircularClip(x, y, false, this); 140 } 141 142 public boolean isCustomizing() { 143 return isShown; 144 } 145 146 private void reset() { 147 ArrayList<String> tiles = new ArrayList<>(); 148 for (String tile : QSPagingSwitch.QS_PAGE_TILES.split(",")) { 149 tiles.add(tile); 150 } 151 mQsPanel.setTiles(tiles); 152 } 153 154 private void setDragging(boolean dragging) { 155 mToolbar.setVisibility(!dragging ? View.VISIBLE : View.INVISIBLE); 156 } 157 158 private void save() { 159 Log.d("CustomQSPanel", "Save!"); 160 mQsPanel.saveCurrentTiles(); 161 // TODO: At save button. 162 hide(0, 0); 163 } 164 165 @Override 166 public boolean onMenuItemClick(MenuItem item) { 167 switch (item.getItemId()) { 168 case MENU_SAVE: 169 Log.d("CustomQSPanel", "Save..."); 170 save(); 171 break; 172 case MENU_RESET: 173 reset(); 174 break; 175 } 176 return true; 177 } 178 179 @Override 180 public void onTileSelected(String spec) { 181 if (mDialog != null) { 182 mQsPanel.addTile(spec); 183 mDialog.dismiss(); 184 } 185 } 186 187 @Override 188 public void onTilesChanged() { 189 mQsPanel.setTiles(mHost.getTiles()); 190 } 191 192 public boolean onDragEvent(DragEvent event) { 193 switch (event.getAction()) { 194 case DragEvent.ACTION_DRAG_STARTED: 195 setDragging(true); 196 break; 197 case DragEvent.ACTION_DRAG_ENDED: 198 setDragging(false); 199 break; 200 } 201 return true; 202 } 203 204 public void onDrop(View v, ClipData data) { 205 if (v == mRemoveButton) { 206 mQsPanel.remove(mQsPanel.getSpec(data)); 207 } else if (v == mInfoButton) { 208 mQsPanel.unstashTiles(); 209 SystemUIDialog dialog = new SystemUIDialog(mContext); 210 dialog.setTitle(mQsPanel.getSpec(data)); 211 dialog.setPositiveButton(R.string.ok, null); 212 dialog.show(); 213 } 214 } 215 216 @Override 217 public void onClick(View v) { 218 if (mFab == v) { 219 mDialog = new SystemUIDialog(mContext, 220 android.R.style.Theme_Material_Dialog); 221 View view = LayoutInflater.from(mContext).inflate(R.layout.qs_add_tiles_list, null); 222 ListView listView = (ListView) view.findViewById(android.R.id.list); 223 TileAdapter adapter = new TileAdapter(mContext, mQsPanel.getTiles(), mHost); 224 adapter.setListener(this); 225 listView.setDivider(null); 226 listView.setDividerHeight(0); 227 listView.setAdapter(adapter); 228 listView.setEmptyView(view.findViewById(R.id.empty_text)); 229 mDialog.setView(view); 230 mDialog.setOnDismissListener(this); 231 mDialog.setOnCancelListener(this); 232 mDialog.show(); 233 // Too lazy to figure out what this will be now, but it should probably be something 234 // besides just a dialog. 235 // For now, just make it big. 236 WindowManager.LayoutParams params = mDialog.getWindow().getAttributes(); 237 params.width = WindowManager.LayoutParams.MATCH_PARENT; 238 params.height = WindowManager.LayoutParams.WRAP_CONTENT; 239 mDialog.getWindow().setAttributes(params); 240 } 241 } 242 243 @Override 244 public void onDismiss(DialogInterface dialog) { 245 mDialog = null; 246 } 247 248 @Override 249 public void onCancel(DialogInterface dialog) { 250 mDialog = null; 251 } 252 253 @Override 254 public void onAnimationEnd(Animator animation) { 255 if (!isShown) { 256 mPhoneStatusBar.getStatusBarWindow().removeView(this); 257 } 258 } 259 260 @Override 261 public void onAnimationCancel(Animator animation) { 262 if (!isShown) { 263 mPhoneStatusBar.getStatusBarWindow().removeView(this); 264 } 265 } 266 267 @Override 268 public void onAnimationStart(Animator animation) { 269 // Don't care. 270 } 271 272 @Override 273 public void onAnimationRepeat(Animator animation) { 274 // Don't care. 275 } 276}