blob: 81e15818aa1c855dfe1a31e33cd2175fb1fc4f33 [file] [log] [blame]
Jason Monkbd6dbb02015-09-03 15:46:25 -04001/*
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
Jason Monkb9c00192015-10-07 11:45:33 -040018import android.animation.Animator;
Jason Monk62b63a02016-02-02 15:15:31 -050019import android.animation.Animator.AnimatorListener;
Jason Monkbd6dbb02015-09-03 15:46:25 -040020import android.content.Context;
Jason Monk62b63a02016-02-02 15:15:31 -050021import android.support.v7.widget.DefaultItemAnimator;
22import android.support.v7.widget.GridLayoutManager;
23import android.support.v7.widget.RecyclerView;
24import android.support.v7.widget.helper.ItemTouchHelper;
Jason Monkbd6dbb02015-09-03 15:46:25 -040025import android.util.AttributeSet;
Jason Monk5db8a412015-10-21 15:16:23 -070026import android.view.ContextThemeWrapper;
Jason Monk5db8a412015-10-21 15:16:23 -070027import android.view.View;
Jason Monk2681dcb2015-09-09 13:50:34 -040028import android.view.View.OnClickListener;
Jason Monkbd6dbb02015-09-03 15:46:25 -040029import android.widget.LinearLayout;
Jason Monkbd6dbb02015-09-03 15:46:25 -040030import com.android.systemui.R;
Jason Monkb9c00192015-10-07 11:45:33 -040031import com.android.systemui.qs.QSDetailClipper;
Jason Monk62b63a02016-02-02 15:15:31 -050032import com.android.systemui.qs.QSTile;
Jason Monkbd6dbb02015-09-03 15:46:25 -040033import com.android.systemui.statusbar.phone.PhoneStatusBar;
34import com.android.systemui.statusbar.phone.QSTileHost;
Jason Monkbd6dbb02015-09-03 15:46:25 -040035
36import java.util.ArrayList;
Jason Monk62b63a02016-02-02 15:15:31 -050037import java.util.List;
Jason Monkbd6dbb02015-09-03 15:46:25 -040038
39/**
40 * Allows full-screen customization of QS, through show() and hide().
41 *
42 * This adds itself to the status bar window, so it can appear on top of quick settings and
43 * *someday* do fancy animations to get into/out of it.
44 */
Jason Monk62b63a02016-02-02 15:15:31 -050045public class QSCustomizer extends LinearLayout implements AnimatorListener, OnClickListener {
Jason Monkbd6dbb02015-09-03 15:46:25 -040046
Jason Monkb9c00192015-10-07 11:45:33 -040047 private final QSDetailClipper mClipper;
Jason Monkbd6dbb02015-09-03 15:46:25 -040048
49 private PhoneStatusBar mPhoneStatusBar;
50
Jason Monkbd6dbb02015-09-03 15:46:25 -040051 private boolean isShown;
Jason Monkbbadff82015-11-06 15:47:26 -050052 private QSTileHost mHost;
Jason Monk62b63a02016-02-02 15:15:31 -050053 private RecyclerView mRecyclerView;
54 private TileAdapter mTileAdapter;
55 private View mClose;
56 private View mSave;
57 private View mReset;
Jason Monkbd6dbb02015-09-03 15:46:25 -040058
59 public QSCustomizer(Context context, AttributeSet attrs) {
60 super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
Jason Monkb9c00192015-10-07 11:45:33 -040061 mClipper = new QSDetailClipper(this);
Jason Monkbd6dbb02015-09-03 15:46:25 -040062 }
63
64 public void setHost(QSTileHost host) {
Jason Monkbbadff82015-11-06 15:47:26 -050065 mHost = host;
Jason Monkdeba7a42015-12-08 16:14:10 -050066 mPhoneStatusBar = host.getPhoneStatusBar();
Jason Monkbd6dbb02015-09-03 15:46:25 -040067 }
68
69 @Override
70 protected void onFinishInflate() {
71 super.onFinishInflate();
Jason Monk62b63a02016-02-02 15:15:31 -050072 mClose = findViewById(R.id.close);
73 mSave = findViewById(R.id.save);
74 mReset = findViewById(R.id.reset);
75 mClose.setOnClickListener(this);
76 mSave.setOnClickListener(this);
77 mReset.setOnClickListener(this);
Jason Monkbd6dbb02015-09-03 15:46:25 -040078
Jason Monk62b63a02016-02-02 15:15:31 -050079 mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
80 mTileAdapter = new TileAdapter(getContext());
81 mRecyclerView.setAdapter(mTileAdapter);
82 new ItemTouchHelper(mTileAdapter.getCallback()).attachToRecyclerView(mRecyclerView);
83 GridLayoutManager layout = new GridLayoutManager(getContext(), 3);
84 layout.setSpanSizeLookup(mTileAdapter.getSizeLookup());
85 mRecyclerView.setLayoutManager(layout);
86 mRecyclerView.addItemDecoration(mTileAdapter.getItemDecoration());
87 DefaultItemAnimator animator = new DefaultItemAnimator();
88 animator.setMoveDuration(TileAdapter.MOVE_DURATION);
89 mRecyclerView.setItemAnimator(animator);
Jason Monkbd6dbb02015-09-03 15:46:25 -040090 }
91
Jason Monkb9c00192015-10-07 11:45:33 -040092 public void show(int x, int y) {
Jason Monk8c7e47f2016-02-17 10:39:31 -050093 if (!isShown) {
94 isShown = true;
95 mPhoneStatusBar.getStatusBarWindow().addView(this);
96 setTileSpecs();
97 mClipper.animateCircularClip(x, y, true, this);
98 new TileQueryHelper(mContext, mHost).setListener(mTileAdapter);
99 }
Jason Monkbd6dbb02015-09-03 15:46:25 -0400100 }
101
Jason Monkb9c00192015-10-07 11:45:33 -0400102 public void hide(int x, int y) {
Jason Monk8c7e47f2016-02-17 10:39:31 -0500103 if (isShown) {
104 isShown = false;
105 mClipper.animateCircularClip(x, y, false, this);
106 }
Jason Monkbd6dbb02015-09-03 15:46:25 -0400107 }
108
109 public boolean isCustomizing() {
110 return isShown;
111 }
112
113 private void reset() {
114 ArrayList<String> tiles = new ArrayList<>();
Jason Monk9d02a432016-01-20 16:33:46 -0500115 String defTiles = mContext.getString(R.string.quick_settings_tiles_default);
116 for (String tile : defTiles.split(",")) {
Jason Monkbd6dbb02015-09-03 15:46:25 -0400117 tiles.add(tile);
118 }
Jason Monk62b63a02016-02-02 15:15:31 -0500119 mTileAdapter.setTileSpecs(tiles);
Jason Monkbd6dbb02015-09-03 15:46:25 -0400120 }
121
Jason Monk62b63a02016-02-02 15:15:31 -0500122 private void setTileSpecs() {
123 List<String> specs = new ArrayList<>();
124 for (QSTile tile : mHost.getTiles()) {
125 specs.add(tile.getTileSpec());
126 }
127 mTileAdapter.setTileSpecs(specs);
Jason Monkf7fe83f2015-09-09 13:03:20 -0400128 }
129
Jason Monkbd6dbb02015-09-03 15:46:25 -0400130 private void save() {
Jason Monk62b63a02016-02-02 15:15:31 -0500131 mTileAdapter.saveSpecs(mHost);
132 hide((int) mSave.getX() + mSave.getWidth() / 2, (int) mSave.getY() + mSave.getHeight() / 2);
Jason Monkf7fe83f2015-09-09 13:03:20 -0400133 }
Jason Monk2681dcb2015-09-09 13:50:34 -0400134
135 @Override
136 public void onClick(View v) {
Jason Monk62b63a02016-02-02 15:15:31 -0500137 if (v == mClose) {
138 hide((int) mClose.getX() + mClose.getWidth() / 2,
139 (int) mClose.getY() + mClose.getHeight() / 2);
140 } else if (v == mSave) {
141 save();
142 } else if (v == mReset) {
143 reset();
Jason Monk2681dcb2015-09-09 13:50:34 -0400144 }
145 }
Jason Monkb9c00192015-10-07 11:45:33 -0400146
147 @Override
148 public void onAnimationEnd(Animator animation) {
149 if (!isShown) {
150 mPhoneStatusBar.getStatusBarWindow().removeView(this);
151 }
152 }
153
154 @Override
155 public void onAnimationCancel(Animator animation) {
156 if (!isShown) {
157 mPhoneStatusBar.getStatusBarWindow().removeView(this);
158 }
159 }
160
161 @Override
162 public void onAnimationStart(Animator animation) {
163 // Don't care.
164 }
165
166 @Override
167 public void onAnimationRepeat(Animator animation) {
168 // Don't care.
169 }
Jason Monk62b63a02016-02-02 15:15:31 -0500170}