QSCustomizer.java revision 428914d0f07f4a0d5b55c4de7ec30708505bd21f
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.animation.Animator.AnimatorListener; 20import android.animation.AnimatorListenerAdapter; 21import android.content.Context; 22import android.support.v7.widget.DefaultItemAnimator; 23import android.support.v7.widget.GridLayoutManager; 24import android.support.v7.widget.RecyclerView; 25import android.util.AttributeSet; 26import android.util.TypedValue; 27import android.view.ContextThemeWrapper; 28import android.view.LayoutInflater; 29import android.view.Menu; 30import android.view.MenuItem; 31import android.view.View; 32import android.widget.LinearLayout; 33import android.widget.Toolbar; 34import android.widget.Toolbar.OnMenuItemClickListener; 35import com.android.systemui.R; 36import com.android.systemui.qs.QSContainer; 37import com.android.systemui.qs.QSDetailClipper; 38import com.android.systemui.qs.QSTile; 39import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer; 40import com.android.systemui.statusbar.phone.PhoneStatusBar; 41import com.android.systemui.statusbar.phone.QSTileHost; 42 43import java.util.ArrayList; 44import java.util.List; 45 46/** 47 * Allows full-screen customization of QS, through show() and hide(). 48 * 49 * This adds itself to the status bar window, so it can appear on top of quick settings and 50 * *someday* do fancy animations to get into/out of it. 51 */ 52public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener { 53 54 private static final int MENU_RESET = Menu.FIRST; 55 56 private final QSDetailClipper mClipper; 57 58 private PhoneStatusBar mPhoneStatusBar; 59 60 private boolean isShown; 61 private QSTileHost mHost; 62 private RecyclerView mRecyclerView; 63 private TileAdapter mTileAdapter; 64 private Toolbar mToolbar; 65 private boolean mCustomizing; 66 private NotificationsQuickSettingsContainer mNotifQsContainer; 67 private QSContainer mQsContainer; 68 69 public QSCustomizer(Context context, AttributeSet attrs) { 70 super(new ContextThemeWrapper(context, R.style.edit_theme), attrs); 71 mClipper = new QSDetailClipper(this); 72 73 LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this); 74 75 mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar); 76 TypedValue value = new TypedValue(); 77 mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true); 78 mToolbar.setNavigationIcon( 79 getResources().getDrawable(value.resourceId, mContext.getTheme())); 80 mToolbar.setNavigationOnClickListener(new OnClickListener() { 81 @Override 82 public void onClick(View v) { 83 hide((int) v.getX() + v.getWidth() / 2, (int) v.getY() + v.getHeight() / 2); 84 } 85 }); 86 mToolbar.setOnMenuItemClickListener(this); 87 mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0, 88 mContext.getString(com.android.internal.R.string.reset)); 89 mToolbar.setTitle(R.string.qs_edit); 90 91 mRecyclerView = (RecyclerView) findViewById(android.R.id.list); 92 mTileAdapter = new TileAdapter(getContext()); 93 mRecyclerView.setAdapter(mTileAdapter); 94 mTileAdapter.getItemTouchHelper().attachToRecyclerView(mRecyclerView); 95 GridLayoutManager layout = new GridLayoutManager(getContext(), 3); 96 layout.setSpanSizeLookup(mTileAdapter.getSizeLookup()); 97 mRecyclerView.setLayoutManager(layout); 98 mRecyclerView.addItemDecoration(mTileAdapter.getItemDecoration()); 99 DefaultItemAnimator animator = new DefaultItemAnimator(); 100 animator.setMoveDuration(TileAdapter.MOVE_DURATION); 101 mRecyclerView.setItemAnimator(animator); 102 } 103 104 public void setHost(QSTileHost host) { 105 mHost = host; 106 mPhoneStatusBar = host.getPhoneStatusBar(); 107 } 108 109 public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) { 110 mNotifQsContainer = notificationsQsContainer; 111 } 112 113 public void setQsContainer(QSContainer qsContainer) { 114 mQsContainer = qsContainer; 115 } 116 117 public void show(int x, int y) { 118 if (!isShown) { 119 isShown = true; 120 setTileSpecs(); 121 setVisibility(View.VISIBLE); 122 mClipper.animateCircularClip(x, y, true, mExpandAnimationListener); 123 new TileQueryHelper(mContext, mHost).setListener(mTileAdapter); 124 mNotifQsContainer.setCustomizerAnimating(true); 125 mNotifQsContainer.setCustomizerShowing(true); 126 } 127 } 128 129 public void hide(int x, int y) { 130 if (isShown) { 131 isShown = false; 132 mToolbar.dismissPopupMenus(); 133 setCustomizing(false); 134 save(); 135 mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener); 136 mNotifQsContainer.setCustomizerAnimating(true); 137 mNotifQsContainer.setCustomizerShowing(false); 138 } 139 } 140 141 private void setCustomizing(boolean customizing) { 142 mCustomizing = customizing; 143 mQsContainer.notifyCustomizeChanged(); 144 } 145 146 public boolean isCustomizing() { 147 return mCustomizing; 148 } 149 150 @Override 151 public boolean onMenuItemClick(MenuItem item) { 152 switch (item.getItemId()) { 153 case MENU_RESET: 154 reset(); 155 break; 156 } 157 return false; 158 } 159 160 private void reset() { 161 ArrayList<String> tiles = new ArrayList<>(); 162 String defTiles = mContext.getString(R.string.quick_settings_tiles_default); 163 for (String tile : defTiles.split(",")) { 164 tiles.add(tile); 165 } 166 mTileAdapter.setTileSpecs(tiles); 167 } 168 169 private void setTileSpecs() { 170 List<String> specs = new ArrayList<>(); 171 for (QSTile tile : mHost.getTiles()) { 172 specs.add(tile.getTileSpec()); 173 } 174 mTileAdapter.setTileSpecs(specs); 175 } 176 177 private void save() { 178 mTileAdapter.saveSpecs(mHost); 179 } 180 181 private final AnimatorListener mExpandAnimationListener = new AnimatorListenerAdapter() { 182 @Override 183 public void onAnimationEnd(Animator animation) { 184 setCustomizing(true); 185 mNotifQsContainer.setCustomizerAnimating(false); 186 } 187 188 @Override 189 public void onAnimationCancel(Animator animation) { 190 mNotifQsContainer.setCustomizerAnimating(false); 191 } 192 }; 193 194 private final AnimatorListener mCollapseAnimationListener = new AnimatorListenerAdapter() { 195 @Override 196 public void onAnimationEnd(Animator animation) { 197 if (!isShown) { 198 setVisibility(View.GONE); 199 } 200 mNotifQsContainer.setCustomizerAnimating(false); 201 } 202 203 @Override 204 public void onAnimationCancel(Animator animation) { 205 if (!isShown) { 206 setVisibility(View.GONE); 207 } 208 mNotifQsContainer.setCustomizerAnimating(false); 209 } 210 }; 211} 212