NavBarTuner.java revision de850bbcaa61c1874b803f2086443febbafd81a4
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15package com.android.systemui.tuner; 16 17import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY; 18import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_END; 19import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_START; 20import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_IMAGE_DELIM; 21import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME; 22import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAVSPACE; 23import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_LEFT; 24import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_RIGHT; 25import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS; 26import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractButton; 27import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractImage; 28import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractKeycode; 29 30import android.annotation.Nullable; 31import android.app.AlertDialog; 32import android.content.DialogInterface; 33import android.content.DialogInterface.OnClickListener; 34import android.content.res.Resources; 35import android.graphics.Color; 36import android.graphics.drawable.Drawable; 37import android.graphics.drawable.Icon; 38import android.os.Bundle; 39import android.os.Handler; 40import android.support.v14.preference.PreferenceFragment; 41import android.support.v7.preference.DropDownPreference; 42import android.support.v7.preference.ListPreference; 43import android.support.v7.preference.Preference; 44import android.support.v7.preference.Preference.OnPreferenceChangeListener; 45import android.support.v7.preference.Preference.OnPreferenceClickListener; 46import android.support.v7.preference.PreferenceCategory; 47import android.text.SpannableStringBuilder; 48import android.text.style.ImageSpan; 49import android.util.Log; 50import android.util.TypedValue; 51import android.view.KeyEvent; 52import android.widget.EditText; 53 54import com.android.systemui.Dependency; 55import com.android.systemui.R; 56import com.android.systemui.statusbar.phone.NavigationBarInflaterView; 57import com.android.systemui.tuner.TunerService.Tunable; 58 59import java.util.ArrayList; 60 61public class NavBarTuner extends PreferenceFragment { 62 63 private static final String LAYOUT = "layout"; 64 private static final String LEFT = "left"; 65 private static final String RIGHT = "right"; 66 67 private static final String TYPE = "type"; 68 private static final String KEYCODE = "keycode"; 69 private static final String ICON = "icon"; 70 71 private static final int[] ICONS = new int[]{ 72 R.drawable.ic_qs_circle, 73 R.drawable.ic_add, 74 R.drawable.ic_remove, 75 R.drawable.ic_left, 76 R.drawable.ic_right, 77 R.drawable.ic_menu, 78 }; 79 80 private final ArrayList<Tunable> mTunables = new ArrayList<>(); 81 private Handler mHandler; 82 83 @Override 84 public void onCreate(@Nullable Bundle savedInstanceState) { 85 mHandler = new Handler(); 86 super.onCreate(savedInstanceState); 87 } 88 89 @Override 90 public void onActivityCreated(@Nullable Bundle savedInstanceState) { 91 super.onActivityCreated(savedInstanceState); 92 getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); 93 } 94 95 @Override 96 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 97 addPreferencesFromResource(R.xml.nav_bar_tuner); 98 bindLayout((ListPreference) findPreference(LAYOUT)); 99 bindButton((PreferenceCategory) findPreference(LEFT), 100 NAV_BAR_LEFT, NAVSPACE); 101 bindButton((PreferenceCategory) findPreference(RIGHT), 102 NAV_BAR_RIGHT, MENU_IME); 103 } 104 105 @Override 106 public void onDestroy() { 107 super.onDestroy(); 108 mTunables.forEach(t -> Dependency.get(TunerService.class).removeTunable(t)); 109 } 110 111 private void addTunable(Tunable tunable, String... keys) { 112 mTunables.add(tunable); 113 Dependency.get(TunerService.class).addTunable(tunable, keys); 114 } 115 116 private void bindLayout(ListPreference preference) { 117 addTunable((key, newValue) -> mHandler.post(() -> { 118 String val = newValue; 119 if (val == null) { 120 val = "default"; 121 } 122 preference.setValue(val); 123 }), NAV_BAR_VIEWS); 124 preference.setOnPreferenceChangeListener((preference1, newValue) -> { 125 String val = (String) newValue; 126 if ("default".equals(val)) val = null; 127 Dependency.get(TunerService.class).setValue(NAV_BAR_VIEWS, val); 128 return true; 129 }); 130 } 131 132 private void bindButton(PreferenceCategory parent, String setting, String def) { 133 String k = parent.getKey(); 134 DropDownPreference type = (DropDownPreference) findPreference(TYPE + "_" + k); 135 Preference keycode = findPreference(KEYCODE + "_" + k); 136 ListPreference icon = (ListPreference) findPreference(ICON + "_" + k); 137 setupIcons(icon); 138 addTunable((key, newValue) -> mHandler.post(() -> { 139 String val = newValue; 140 if (val == null) { 141 val = def; 142 } 143 String button = extractButton(val); 144 if (button.startsWith(KEY)) { 145 type.setValue(KEY); 146 String uri = extractImage(button); 147 int code = extractKeycode(button); 148 icon.setValue(uri); 149 updateSummary(icon); 150 keycode.setSummary(code + ""); 151 keycode.setVisible(true); 152 icon.setVisible(true); 153 } else { 154 type.setValue(button); 155 keycode.setVisible(false); 156 icon.setVisible(false); 157 } 158 }), setting); 159 OnPreferenceChangeListener listener = (preference, newValue) -> { 160 mHandler.post(() -> { 161 setValue(setting, type, keycode, icon); 162 updateSummary(icon); 163 }); 164 return true; 165 }; 166 type.setOnPreferenceChangeListener(listener); 167 icon.setOnPreferenceChangeListener(listener); 168 keycode.setOnPreferenceClickListener(preference -> { 169 EditText editText = new EditText(getContext()); 170 new AlertDialog.Builder(getContext()) 171 .setTitle(preference.getTitle()) 172 .setView(editText) 173 .setNegativeButton(android.R.string.cancel, null) 174 .setPositiveButton(android.R.string.ok, (dialog, which) -> { 175 int code = KeyEvent.KEYCODE_ENTER; 176 try { 177 code = Integer.parseInt(editText.getText().toString()); 178 } catch (Exception e) { 179 } 180 keycode.setSummary(code + ""); 181 setValue(setting, type, keycode, icon); 182 }).show(); 183 return true; 184 }); 185 } 186 187 private void updateSummary(ListPreference icon) { 188 try { 189 int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, 190 getContext().getResources().getDisplayMetrics()); 191 String pkg = icon.getValue().split("/")[0]; 192 int id = Integer.parseInt(icon.getValue().split("/")[1]); 193 SpannableStringBuilder builder = new SpannableStringBuilder(); 194 Drawable d = Icon.createWithResource(pkg, id) 195 .loadDrawable(getContext()); 196 d.setTint(Color.BLACK); 197 d.setBounds(0, 0, size, size); 198 ImageSpan span = new ImageSpan(d); 199 builder.append(" ", span, 0); 200 icon.setSummary(builder); 201 } catch (Exception e) { 202 Log.d("NavButton", "Problem with summary", e); 203 icon.setSummary(null); 204 } 205 } 206 207 private void setValue(String setting, DropDownPreference type, Preference keycode, 208 ListPreference icon) { 209 String button = type.getValue(); 210 if (KEY.equals(button)) { 211 String uri = icon.getValue(); 212 int code = KeyEvent.KEYCODE_ENTER; 213 try { 214 code = Integer.parseInt(keycode.getSummary().toString()); 215 } catch (Exception e) { 216 } 217 button = button + KEY_CODE_START + code + KEY_IMAGE_DELIM + uri + KEY_CODE_END; 218 } 219 Dependency.get(TunerService.class).setValue(setting, button); 220 } 221 222 private void setupIcons(ListPreference icon) { 223 CharSequence[] labels = new CharSequence[ICONS.length]; 224 CharSequence[] values = new CharSequence[ICONS.length]; 225 int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, 226 getContext().getResources().getDisplayMetrics()); 227 for (int i = 0; i < ICONS.length; i++) { 228 SpannableStringBuilder builder = new SpannableStringBuilder(); 229 Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i]) 230 .loadDrawable(getContext()); 231 d.setTint(Color.BLACK); 232 d.setBounds(0, 0, size, size); 233 ImageSpan span = new ImageSpan(d); 234 builder.append(" ", span, 0); 235 labels[i] = builder; 236 values[i] = getContext().getPackageName() + "/" + ICONS[i]; 237 } 238 icon.setEntries(labels); 239 icon.setEntryValues(values); 240 } 241} 242