Merge "Tuner: Nav bar tuner"
This commit is contained in:
24
packages/SystemUI/res/drawable/ic_left.xml
Normal file
24
packages/SystemUI/res/drawable/ic_left.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M15.41,16.09l-4.58,-4.59 4.58,-4.59L14.0,5.5l-6.0,6.0 6.0,6.0z"/>
|
||||
</vector>
|
||||
24
packages/SystemUI/res/drawable/ic_menu.xml
Normal file
24
packages/SystemUI/res/drawable/ic_menu.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M3.0,18.0l18.0,0.0l0.0,-2.0L3.0,16.0l0.0,2.0zm0.0,-5.0l18.0,0.0l0.0,-2.0L3.0,11.0l0.0,2.0zm0.0,-7.0l0.0,2.0l18.0,0.0L21.0,6.0L3.0,6.0z"/>
|
||||
</vector>
|
||||
24
packages/SystemUI/res/drawable/ic_remove.xml
Normal file
24
packages/SystemUI/res/drawable/ic_remove.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19.0,13.0L5.0,13.0l0.0,-2.0l14.0,0.0l0.0,2.0z"/>
|
||||
</vector>
|
||||
24
packages/SystemUI/res/drawable/ic_right.xml
Normal file
24
packages/SystemUI/res/drawable/ic_right.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M8.59,16.34l4.58,-4.59 -4.58,-4.59L10.0,5.75l6.0,6.0 -6.0,6.0z"/>
|
||||
</vector>
|
||||
@@ -34,7 +34,7 @@
|
||||
<bool name="config_keyguardUserSwitcher">true</bool>
|
||||
|
||||
<!-- Nav bar button default ordering/layout -->
|
||||
<string name="config_navBarLayout" translatable="false">space;back,home,recent;menu_ime</string>
|
||||
<string name="config_navBarLayout" translatable="false">left;back,home,recent;right</string>
|
||||
|
||||
<!-- Animation duration when using long press on recents to dock -->
|
||||
<integer name="long_press_dock_anim_duration">290</integer>
|
||||
|
||||
@@ -19,6 +19,6 @@
|
||||
<resources>
|
||||
|
||||
<!-- Nav bar button default ordering/layout -->
|
||||
<string name="config_navBarLayout" translatable="false">back,home;space;menu_ime,recent</string>
|
||||
<string name="config_navBarLayout" translatable="false">back,home,left;space;right,recent</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -286,7 +286,7 @@
|
||||
<string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIFactory</string>
|
||||
|
||||
<!-- Nav bar button default ordering/layout -->
|
||||
<string name="config_navBarLayout" translatable="false">space,back;home;recent,menu_ime</string>
|
||||
<string name="config_navBarLayout" translatable="false">left,back;home;recent,right</string>
|
||||
|
||||
<bool name="quick_settings_show_full_alarm">false</bool>
|
||||
|
||||
|
||||
@@ -1541,56 +1541,71 @@
|
||||
<!-- SysUI Tuner: Button that leads to the navigation bar customization screen [CHAR LIMIT=60] -->
|
||||
<string name="nav_bar">Navigation bar</string>
|
||||
|
||||
<!-- SysUI Tuner: Group of buttons that show on the start of the screen [CHAR LIMIT=30] -->
|
||||
<string name="start">Start</string>
|
||||
<!-- SysUI Tuner: Group of buttons that show on the center of the screen [CHAR LIMIT=30] -->
|
||||
<string name="center">Center</string>
|
||||
<!-- SysUI Tuner: Group of buttons that show on the end of the screen [CHAR LIMIT=30] -->
|
||||
<string name="end">End</string>
|
||||
<!-- SysUI Tuner: Name of space used in custom navigation bar layouts [CHAR LIMIT=30] -->
|
||||
<string name="space">Spacer</string>
|
||||
<!-- SysUI Tuner: Button that controls layout of navigation bar [CHAR LIMIT=60] -->
|
||||
<string name="nav_bar_layout">Layout</string>
|
||||
|
||||
<!-- SysUI Tuner: Label for section of settings about the left nav button [CHAR LIMIT=60] -->
|
||||
<string name="nav_bar_left">Left</string>
|
||||
|
||||
<!-- SysUI Tuner: Label for section of settings about the right nav button [CHAR LIMIT=60] -->
|
||||
<string name="nav_bar_right">Right</string>
|
||||
|
||||
<!-- SysUI Tuner: Setting for button type in nav bar [CHAR LIMIT=60] -->
|
||||
<string name="nav_bar_button_type">Button type</string>
|
||||
|
||||
<!-- SysUI Tuner: Added to nav bar option to indicate it is the default [CHAR LIMIT=60] -->
|
||||
<string name="nav_bar_default"> (default)</string>
|
||||
|
||||
<!-- SysUI Tuner: Labels for different types of navigation bar buttons [CHAR LIMIT=60] -->
|
||||
<string-array name="nav_bar_buttons">
|
||||
<item>Clipboard</item>
|
||||
<item>Keycode</item>
|
||||
<item>Menu / Keyboard Switcher</item>
|
||||
<item>None</item>
|
||||
</string-array>
|
||||
<string-array name="nav_bar_button_values" translatable="false">
|
||||
<item>clipboard</item>
|
||||
<item>key</item>
|
||||
<item>menu_ime</item>
|
||||
<item>space</item>
|
||||
</string-array>
|
||||
|
||||
<!-- SysUI Tuner: Labels for different types of navigation bar layouts [CHAR LIMIT=60] -->
|
||||
<string-array name="nav_bar_layouts">
|
||||
<item>Divided (default)</item>
|
||||
<item>Centered</item>
|
||||
<item>Left-aligned</item>
|
||||
<item>Right-aligned</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="nav_bar_layouts_values" translatable="false">
|
||||
<item>default</item>
|
||||
<item>left;back,home,recent;right</item>
|
||||
<item>left,back,home,recent,right;space;space</item>
|
||||
<item>space;space;left,back,home,recent,right</item>
|
||||
</string-array>
|
||||
|
||||
<!-- SysUI Tuner: Name of Combination Menu / Keyboard Switcher button [CHAR LIMIT=30] -->
|
||||
<string name="menu_ime">Menu / Keyboard Switcher</string>
|
||||
<!-- SysUI Tuner: Title for dialog to add a button [CHAR LIMIT=30] -->
|
||||
<string name="select_button">Select button to add</string>
|
||||
<!-- SysUI Tuner: Button to add a button [CHAR LIMIT=30] -->
|
||||
<string name="add_button">Add button</string>
|
||||
<!-- SysUI Tuner: Save the current settings [CHAR LIMIT=30] -->
|
||||
<string name="save">Save</string>
|
||||
<!-- SysUI Tuner: Reset to default settings [CHAR LIMIT=30] -->
|
||||
<string name="reset">Reset</string>
|
||||
|
||||
<!-- SysUI Tuner: Title of no home warning dialog [CHAR LIMIT=30] -->
|
||||
<string name="no_home_title">No home button found</string>
|
||||
<!-- SysUI Tuner: Message of no home warning dialog [CHAR LIMIT=NONE] -->
|
||||
<string name="no_home_message">A home button is required to be able to navigate this device. Please add a home button before saving.</string>
|
||||
|
||||
<!-- SysUI Tuner: Adjust button width dialog title [CHAR LIMIT=60] -->
|
||||
<string name="adjust_button_width">Adjust button width</string>
|
||||
|
||||
<!-- SysUI Tuner: Nav bar button that holds the clipboard [CHAR LIMIT=30] -->
|
||||
<string name="clipboard">Clipboard</string>
|
||||
|
||||
<!-- SysUI Tuner: Description of nav bar button that holds the clipboard [CHAR LIMIT=NONE] -->
|
||||
<string name="clipboard_description">The Clipboard allows items to be dragged directly to the clipboard. Items can also be dragged directly out of the clipboard when present.</string>
|
||||
|
||||
<!-- SysUI Tuner: Accessibility description for custom nav key [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_key">Custom navigation button</string>
|
||||
|
||||
<!-- SysUI Tuner: Nav bar button that emulates a keycode [CHAR LIMIT=30] -->
|
||||
<string name="keycode">Keycode</string>
|
||||
|
||||
<!-- SysUI Tuner: Description of nav bar button that emulates a keycode [CHAR LIMIT=NONE] -->
|
||||
<string name="keycode_description">Keycode buttons allow keyboard keys to
|
||||
be added to the Navigation Bar. When pressed they emulate the selected
|
||||
keyboard key. First the key must be selected for the button, followed
|
||||
by an image to be shown on the button.</string>
|
||||
|
||||
<!-- SysUI Tuner: Title of dialog to select which key to emulate [CHAR LIMIT=60] -->
|
||||
<string name="select_keycode">Select Keyboard Button</string>
|
||||
|
||||
<!-- SysUI Tuner: Label for preview area in navigation bar tuner [CHAR LIMIT=NONE] -->
|
||||
<string name="preview">Preview</string>
|
||||
<!-- SysUI Tuner: Settings to change nav bar icon [CHAR LIMIT=30] -->
|
||||
<string name="icon">Icon</string>
|
||||
|
||||
<!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
|
||||
<string name="drag_to_add_tiles">Drag to add tiles</string>
|
||||
|
||||
79
packages/SystemUI/res/xml/nav_bar_tuner.xml
Normal file
79
packages/SystemUI/res/xml/nav_bar_tuner.xml
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:sysui="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/nav_bar">
|
||||
|
||||
<ListPreference
|
||||
android:key="layout"
|
||||
android:title="@string/nav_bar_layout"
|
||||
android:summary="%s"
|
||||
android:persistent="false"
|
||||
android:entries="@array/nav_bar_layouts"
|
||||
android:entryValues="@array/nav_bar_layouts_values" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="left"
|
||||
android:title="@string/nav_bar_left">
|
||||
|
||||
<DropDownPreference
|
||||
android:key="type_left"
|
||||
android:title="@string/nav_bar_button_type"
|
||||
android:persistent="false"
|
||||
android:summary="%s"
|
||||
android:entries="@array/nav_bar_buttons"
|
||||
android:entryValues="@array/nav_bar_button_values" />
|
||||
|
||||
<Preference
|
||||
android:key="keycode_left"
|
||||
android:persistent="false"
|
||||
android:title="@string/keycode" />
|
||||
|
||||
<com.android.systemui.tuner.BetterListPreference
|
||||
android:key="icon_left"
|
||||
android:persistent="false"
|
||||
android:summary="%s"
|
||||
android:title="@string/icon" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="right"
|
||||
android:title="@string/nav_bar_right">
|
||||
|
||||
<DropDownPreference
|
||||
android:key="type_right"
|
||||
android:title="@string/nav_bar_button_type"
|
||||
android:summary="%s"
|
||||
android:persistent="false"
|
||||
android:entries="@array/nav_bar_buttons"
|
||||
android:entryValues="@array/nav_bar_button_values" />
|
||||
|
||||
<Preference
|
||||
android:key="keycode_right"
|
||||
android:persistent="false"
|
||||
android:title="@string/keycode" />
|
||||
|
||||
<com.android.systemui.tuner.BetterListPreference
|
||||
android:key="icon_right"
|
||||
android:persistent="false"
|
||||
android:summary="%s"
|
||||
android:title="@string/icon" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -150,12 +150,10 @@
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
<!--
|
||||
<Preference
|
||||
android:key="nav_bar"
|
||||
android:title="@string/nav_bar"
|
||||
android:fragment="com.android.systemui.tuner.NavBarTuner" />
|
||||
-->
|
||||
|
||||
<Preference
|
||||
android:key="other"
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
@@ -47,6 +48,8 @@ public class NavigationBarInflaterView extends FrameLayout
|
||||
private static final String TAG = "NavBarInflater";
|
||||
|
||||
public static final String NAV_BAR_VIEWS = "sysui_nav_bar";
|
||||
public static final String NAV_BAR_LEFT = "sysui_nav_bar_left";
|
||||
public static final String NAV_BAR_RIGHT = "sysui_nav_bar_right";
|
||||
|
||||
public static final String MENU_IME = "menu_ime";
|
||||
public static final String BACK = "back";
|
||||
@@ -55,6 +58,8 @@ public class NavigationBarInflaterView extends FrameLayout
|
||||
public static final String NAVSPACE = "space";
|
||||
public static final String CLIPBOARD = "clipboard";
|
||||
public static final String KEY = "key";
|
||||
public static final String LEFT = "left";
|
||||
public static final String RIGHT = "right";
|
||||
|
||||
public static final String GRAVITY_SEPARATOR = ";";
|
||||
public static final String BUTTON_SEPARATOR = ",";
|
||||
@@ -130,7 +135,8 @@ public class NavigationBarInflaterView extends FrameLayout
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS);
|
||||
TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS, NAV_BAR_LEFT,
|
||||
NAV_BAR_RIGHT);
|
||||
PluginManager.getInstance(getContext()).addPluginListener(NavBarButtonProvider.ACTION, this,
|
||||
NavBarButtonProvider.VERSION, true /* Allow multiple */);
|
||||
}
|
||||
@@ -148,6 +154,9 @@ public class NavigationBarInflaterView extends FrameLayout
|
||||
clearViews();
|
||||
inflateLayout(newValue);
|
||||
}
|
||||
} else if (NAV_BAR_LEFT.equals(key) || NAV_BAR_RIGHT.equals(key)) {
|
||||
clearViews();
|
||||
inflateLayout(mCurrentLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +277,13 @@ public class NavigationBarInflaterView extends FrameLayout
|
||||
boolean landscape) {
|
||||
View v = null;
|
||||
String button = extractButton(buttonSpec);
|
||||
if (LEFT.equals(button)) {
|
||||
buttonSpec = TunerService.get(mContext).getValue(NAV_BAR_LEFT, NAVSPACE);
|
||||
button = extractButton(buttonSpec);
|
||||
} else if (RIGHT.equals(button)) {
|
||||
buttonSpec = TunerService.get(mContext).getValue(NAV_BAR_RIGHT, MENU_IME);
|
||||
button = extractButton(buttonSpec);
|
||||
}
|
||||
// Let plugins go first so they can override a standard view if they want.
|
||||
for (NavBarButtonProvider provider : mPlugins) {
|
||||
v = provider.createView(buttonSpec, parent);
|
||||
@@ -291,7 +307,14 @@ public class NavigationBarInflaterView extends FrameLayout
|
||||
v = inflater.inflate(R.layout.custom_key, parent, false);
|
||||
((KeyButtonView) v).setCode(code);
|
||||
if (uri != null) {
|
||||
((KeyButtonView) v).loadAsync(uri);
|
||||
if (uri.contains(":")) {
|
||||
((KeyButtonView) v).loadAsync(Icon.createWithContentUri(uri));
|
||||
} else if (uri.contains("/")) {
|
||||
int index = uri.indexOf('/');
|
||||
String pkg = uri.substring(0, index);
|
||||
int id = Integer.parseInt(uri.substring(index + 1));
|
||||
((KeyButtonView) v).loadAsync(Icon.createWithResource(pkg, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
return v;
|
||||
|
||||
@@ -116,18 +116,18 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
|
||||
mOnClickListener = onClickListener;
|
||||
}
|
||||
|
||||
public void loadAsync(String uri) {
|
||||
new AsyncTask<String, Void, Drawable>() {
|
||||
public void loadAsync(Icon icon) {
|
||||
new AsyncTask<Icon, Void, Drawable>() {
|
||||
@Override
|
||||
protected Drawable doInBackground(String... params) {
|
||||
return Icon.createWithContentUri(params[0]).loadDrawable(mContext);
|
||||
protected Drawable doInBackground(Icon... params) {
|
||||
return params[0].loadDrawable(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Drawable drawable) {
|
||||
setImageDrawable(drawable);
|
||||
}
|
||||
}.execute(uri);
|
||||
}.execute(icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the
|
||||
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.tuner;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.ListPreference;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class BetterListPreference extends ListPreference {
|
||||
|
||||
private CharSequence mSummary;
|
||||
|
||||
public BetterListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSummary(CharSequence summary) {
|
||||
super.setSummary(summary);
|
||||
mSummary = summary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return mSummary;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of the License at
|
||||
@@ -14,590 +14,227 @@
|
||||
|
||||
package com.android.systemui.tuner;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.BACK;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.BUTTON_SEPARATOR;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.CLIPBOARD;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.GRAVITY_SEPARATOR;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.HOME;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_END;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_START;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_IMAGE_DELIM;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAVSPACE;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_LEFT;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_RIGHT;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.RECENT;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.SIZE_MOD_END;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.SIZE_MOD_START;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractButton;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractSize;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractImage;
|
||||
import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractKeycode;
|
||||
|
||||
public class NavBarTuner extends Fragment implements TunerService.Tunable {
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v14.preference.PreferenceFragment;
|
||||
import android.support.v7.preference.DropDownPreference;
|
||||
import android.support.v7.preference.ListPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
||||
import android.support.v7.preference.PreferenceCategory;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.ImageSpan;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.EditText;
|
||||
|
||||
private static final int SAVE = Menu.FIRST + 1;
|
||||
private static final int RESET = Menu.FIRST + 2;
|
||||
private static final int READ_REQUEST = 42;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.phone.NavigationBarInflaterView;
|
||||
import com.android.systemui.tuner.TunerService.Tunable;
|
||||
|
||||
private static final float PREVIEW_SCALE = .95f;
|
||||
private static final float PREVIEW_SCALE_LANDSCAPE = .75f;
|
||||
import java.util.ArrayList;
|
||||
|
||||
private NavBarAdapter mNavBarAdapter;
|
||||
private PreviewNavInflater mPreview;
|
||||
public class NavBarTuner extends PreferenceFragment {
|
||||
|
||||
private static final String LAYOUT = "layout";
|
||||
private static final String LEFT = "left";
|
||||
private static final String RIGHT = "right";
|
||||
|
||||
private static final String TYPE = "type";
|
||||
private static final String KEYCODE = "keycode";
|
||||
private static final String ICON = "icon";
|
||||
|
||||
private static final int[] ICONS = new int[]{
|
||||
R.drawable.ic_qs_circle,
|
||||
R.drawable.ic_add,
|
||||
R.drawable.ic_remove,
|
||||
R.drawable.ic_left,
|
||||
R.drawable.ic_right,
|
||||
R.drawable.ic_menu,
|
||||
};
|
||||
|
||||
private final ArrayList<Tunable> mTunables = new ArrayList<>();
|
||||
private Handler mHandler;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
final View view = inflater.inflate(R.layout.nav_bar_tuner, container, false);
|
||||
inflatePreview((ViewGroup) view.findViewById(R.id.nav_preview_frame));
|
||||
return view;
|
||||
}
|
||||
|
||||
private void inflatePreview(ViewGroup view) {
|
||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
||||
boolean isRotated = display.getRotation() == Surface.ROTATION_90
|
||||
|| display.getRotation() == Surface.ROTATION_270;
|
||||
|
||||
Configuration config = new Configuration(getContext().getResources().getConfiguration());
|
||||
boolean isPhoneLandscape = isRotated && (config.smallestScreenWidthDp < 600);
|
||||
final float scale = isPhoneLandscape ? PREVIEW_SCALE_LANDSCAPE : PREVIEW_SCALE;
|
||||
config.densityDpi = (int) (config.densityDpi * scale);
|
||||
|
||||
mPreview = (PreviewNavInflater) LayoutInflater.from(getContext().createConfigurationContext(
|
||||
config)).inflate(R.layout.nav_bar_tuner_inflater, view, false);
|
||||
final ViewGroup.LayoutParams layoutParams = mPreview.getLayoutParams();
|
||||
layoutParams.width = (int) ((isPhoneLandscape ? display.getHeight() : display.getWidth())
|
||||
* scale);
|
||||
// Not sure why, but the height dimen is not being scaled with the dp, set it manually
|
||||
// for now.
|
||||
layoutParams.height = (int) (layoutParams.height * scale);
|
||||
if (isPhoneLandscape) {
|
||||
int width = layoutParams.width;
|
||||
layoutParams.width = layoutParams.height;
|
||||
layoutParams.height = width;
|
||||
}
|
||||
view.addView(mPreview);
|
||||
|
||||
if (isRotated) {
|
||||
mPreview.findViewById(R.id.rot0).setVisibility(View.GONE);
|
||||
final View rot90 = mPreview.findViewById(R.id.rot90);
|
||||
} else {
|
||||
mPreview.findViewById(R.id.rot90).setVisibility(View.GONE);
|
||||
final View rot0 = mPreview.findViewById(R.id.rot0);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyChanged() {
|
||||
mPreview.onTuningChanged(NAV_BAR_VIEWS, mNavBarAdapter.getNavString());
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
mHandler = new Handler();
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
RecyclerView recyclerView = (RecyclerView) view.findViewById(android.R.id.list);
|
||||
final Context context = getContext();
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(context));
|
||||
mNavBarAdapter = new NavBarAdapter(context);
|
||||
recyclerView.setAdapter(mNavBarAdapter);
|
||||
recyclerView.addItemDecoration(new Dividers(context));
|
||||
final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mNavBarAdapter.mCallbacks);
|
||||
mNavBarAdapter.setTouchHelper(itemTouchHelper);
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView);
|
||||
|
||||
TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS);
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
TunerService.get(getContext()).removeTunable(this);
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.nav_bar_tuner);
|
||||
bindLayout((ListPreference) findPreference(LAYOUT));
|
||||
bindButton((PreferenceCategory) findPreference(LEFT),
|
||||
NAV_BAR_LEFT, NAVSPACE);
|
||||
bindButton((PreferenceCategory) findPreference(RIGHT),
|
||||
NAV_BAR_RIGHT, MENU_IME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTuningChanged(String key, String navLayout) {
|
||||
if (!NAV_BAR_VIEWS.equals(key)) return;
|
||||
Context context = getContext();
|
||||
if (navLayout == null) {
|
||||
navLayout = context.getString(R.string.config_navBarLayout);
|
||||
}
|
||||
String[] views = navLayout.split(GRAVITY_SEPARATOR);
|
||||
String[] groups = new String[] { NavBarAdapter.START, NavBarAdapter.CENTER,
|
||||
NavBarAdapter.END};
|
||||
CharSequence[] groupLabels = new String[] { getString(R.string.start),
|
||||
getString(R.string.center), getString(R.string.end) };
|
||||
mNavBarAdapter.clear();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
mNavBarAdapter.addButton(groups[i], groupLabels[i]);
|
||||
for (String button : views[i].split(BUTTON_SEPARATOR)) {
|
||||
mNavBarAdapter.addButton(button, getLabel(button, context));
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mTunables.forEach(t -> TunerService.get(getContext()).removeTunable(t));
|
||||
}
|
||||
|
||||
private void addTunable(Tunable tunable, String... keys) {
|
||||
mTunables.add(tunable);
|
||||
TunerService.get(getContext()).addTunable(tunable, keys);
|
||||
}
|
||||
|
||||
private void bindLayout(ListPreference preference) {
|
||||
addTunable((key, newValue) -> mHandler.post(() -> {
|
||||
String val = newValue;
|
||||
if (val == null) {
|
||||
val = "default";
|
||||
}
|
||||
}
|
||||
mNavBarAdapter.addButton(NavBarAdapter.ADD, getString(R.string.add_button));
|
||||
setHasOptionsMenu(true);
|
||||
preference.setValue(val);
|
||||
}), NAV_BAR_VIEWS);
|
||||
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
|
||||
String val = (String) newValue;
|
||||
if ("default".equals(val)) val = null;
|
||||
TunerService.get(getContext()).setValue(NAV_BAR_VIEWS, val);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
// TODO: Show save button conditionally, only when there are changes.
|
||||
menu.add(Menu.NONE, SAVE, Menu.NONE, getString(R.string.save))
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
menu.add(Menu.NONE, RESET, Menu.NONE, getString(R.string.reset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == SAVE) {
|
||||
if (!mNavBarAdapter.hasHomeButton()) {
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.no_home_title)
|
||||
.setMessage(R.string.no_home_message)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
private void bindButton(PreferenceCategory parent, String setting, String def) {
|
||||
String k = parent.getKey();
|
||||
DropDownPreference type = (DropDownPreference) findPreference(TYPE + "_" + k);
|
||||
Preference keycode = findPreference(KEYCODE + "_" + k);
|
||||
ListPreference icon = (ListPreference) findPreference(ICON + "_" + k);
|
||||
setupIcons(icon);
|
||||
addTunable((key, newValue) -> mHandler.post(() -> {
|
||||
String val = newValue;
|
||||
if (val == null) {
|
||||
val = def;
|
||||
}
|
||||
String button = extractButton(val);
|
||||
if (button.startsWith(KEY)) {
|
||||
type.setValue(KEY);
|
||||
String uri = extractImage(button);
|
||||
int code = extractKeycode(button);
|
||||
icon.setValue(uri);
|
||||
updateSummary(icon);
|
||||
keycode.setSummary(code + "");
|
||||
keycode.setVisible(true);
|
||||
icon.setVisible(true);
|
||||
} else {
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
NAV_BAR_VIEWS, mNavBarAdapter.getNavString());
|
||||
type.setValue(button);
|
||||
keycode.setVisible(false);
|
||||
icon.setVisible(false);
|
||||
}
|
||||
return true;
|
||||
} else if (item.getItemId() == RESET) {
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
NAV_BAR_VIEWS, null);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private static CharSequence getLabel(String button, Context context) {
|
||||
if (button.startsWith(HOME)) {
|
||||
return context.getString(R.string.accessibility_home);
|
||||
} else if (button.startsWith(BACK)) {
|
||||
return context.getString(R.string.accessibility_back);
|
||||
} else if (button.startsWith(RECENT)) {
|
||||
return context.getString(R.string.accessibility_recent);
|
||||
} else if (button.startsWith(NAVSPACE)) {
|
||||
return context.getString(R.string.space);
|
||||
} else if (button.startsWith(MENU_IME)) {
|
||||
return context.getString(R.string.menu_ime);
|
||||
} else if (button.startsWith(CLIPBOARD)) {
|
||||
return context.getString(R.string.clipboard);
|
||||
} else if (button.startsWith(KEY)) {
|
||||
return context.getString(R.string.keycode);
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
private static class Holder extends RecyclerView.ViewHolder {
|
||||
private TextView title;
|
||||
|
||||
public Holder(View itemView) {
|
||||
super(itemView);
|
||||
title = (TextView) itemView.findViewById(android.R.id.title);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Dividers extends RecyclerView.ItemDecoration {
|
||||
private final Drawable mDivider;
|
||||
|
||||
public Dividers(Context context) {
|
||||
TypedValue value = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.listDivider, value, true);
|
||||
mDivider = context.getDrawable(value.resourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||
super.onDraw(c, parent, state);
|
||||
final int left = parent.getPaddingLeft();
|
||||
final int right = parent.getWidth() - parent.getPaddingRight();
|
||||
|
||||
final int childCount = parent.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final View child = parent.getChildAt(i);
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
|
||||
.getLayoutParams();
|
||||
final int top = child.getBottom() + params.bottomMargin;
|
||||
final int bottom = top + mDivider.getIntrinsicHeight();
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void selectImage() {
|
||||
startActivityForResult(KeycodeSelectionHelper.getSelectImageIntent(), READ_REQUEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == READ_REQUEST && resultCode == Activity.RESULT_OK && data != null) {
|
||||
final Uri uri = data.getData();
|
||||
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
getContext().getContentResolver().takePersistableUriPermission(uri, takeFlags);
|
||||
mNavBarAdapter.onImageSelected(uri);
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
private class NavBarAdapter extends RecyclerView.Adapter<Holder>
|
||||
implements View.OnClickListener {
|
||||
|
||||
private static final String START = "start";
|
||||
private static final String CENTER = "center";
|
||||
private static final String END = "end";
|
||||
private static final String ADD = "add";
|
||||
|
||||
private static final int ADD_ID = 0;
|
||||
private static final int BUTTON_ID = 1;
|
||||
private static final int CATEGORY_ID = 2;
|
||||
|
||||
private List<String> mButtons = new ArrayList<>();
|
||||
private List<CharSequence> mLabels = new ArrayList<>();
|
||||
private int mCategoryLayout;
|
||||
private int mButtonLayout;
|
||||
private ItemTouchHelper mTouchHelper;
|
||||
|
||||
// Stored keycode while we wait for image selection on a KEY.
|
||||
private int mKeycode;
|
||||
|
||||
public NavBarAdapter(Context context) {
|
||||
TypedArray attrs = context.getTheme().obtainStyledAttributes(null,
|
||||
android.R.styleable.Preference, android.R.attr.preferenceStyle, 0);
|
||||
mButtonLayout = attrs.getResourceId(android.R.styleable.Preference_layout, 0);
|
||||
attrs = context.getTheme().obtainStyledAttributes(null,
|
||||
android.R.styleable.Preference, android.R.attr.preferenceCategoryStyle, 0);
|
||||
mCategoryLayout = attrs.getResourceId(android.R.styleable.Preference_layout, 0);
|
||||
}
|
||||
|
||||
public void setTouchHelper(ItemTouchHelper itemTouchHelper) {
|
||||
mTouchHelper = itemTouchHelper;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
mButtons.clear();
|
||||
mLabels.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void addButton(String button, CharSequence label) {
|
||||
mButtons.add(button);
|
||||
mLabels.add(label);
|
||||
notifyItemInserted(mLabels.size() - 1);
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
public boolean hasHomeButton() {
|
||||
final int N = mButtons.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (mButtons.get(i).startsWith(HOME)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getNavString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 1; i < mButtons.size() - 1; i++) {
|
||||
String button = mButtons.get(i);
|
||||
if (button.equals(CENTER) || button.equals(END)) {
|
||||
if (builder.length() == 0 || builder.toString().endsWith(GRAVITY_SEPARATOR)) {
|
||||
// No start or center buttons, fill with a space.
|
||||
builder.append(NAVSPACE);
|
||||
}
|
||||
builder.append(GRAVITY_SEPARATOR);
|
||||
continue;
|
||||
} else if (builder.length() != 0 && !builder.toString().endsWith(
|
||||
GRAVITY_SEPARATOR)) {
|
||||
builder.append(BUTTON_SEPARATOR);
|
||||
}
|
||||
builder.append(button);
|
||||
}
|
||||
if (builder.toString().endsWith(GRAVITY_SEPARATOR)) {
|
||||
// No end buttons, fill with space.
|
||||
builder.append(NAVSPACE);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
String button = mButtons.get(position);
|
||||
if (button.equals(START) || button.equals(CENTER) || button.equals(END)) {
|
||||
return CATEGORY_ID;
|
||||
}
|
||||
if (button.equals(ADD)) {
|
||||
return ADD_ID;
|
||||
}
|
||||
return BUTTON_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
final Context context = parent.getContext();
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
final View view = inflater.inflate(getLayoutId(viewType), parent, false);
|
||||
if (viewType == BUTTON_ID) {
|
||||
inflater.inflate(R.layout.nav_control_widget,
|
||||
(ViewGroup) view.findViewById(android.R.id.widget_frame));
|
||||
}
|
||||
return new Holder(view);
|
||||
}
|
||||
|
||||
private int getLayoutId(int viewType) {
|
||||
if (viewType == CATEGORY_ID) {
|
||||
return mCategoryLayout;
|
||||
}
|
||||
return mButtonLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(Holder holder, int position) {
|
||||
holder.title.setText(mLabels.get(position));
|
||||
if (holder.getItemViewType() == BUTTON_ID) {
|
||||
bindButton(holder, position);
|
||||
} else if (holder.getItemViewType() == ADD_ID) {
|
||||
bindAdd(holder);
|
||||
}
|
||||
}
|
||||
|
||||
private void bindAdd(Holder holder) {
|
||||
TypedValue value = new TypedValue();
|
||||
final Context context = holder.itemView.getContext();
|
||||
context.getTheme().resolveAttribute(android.R.attr.colorAccent, value, true);
|
||||
final ImageView icon = (ImageView) holder.itemView.findViewById(android.R.id.icon);
|
||||
icon.setImageResource(R.drawable.ic_add);
|
||||
icon.setImageTintList(ColorStateList.valueOf(context.getColor(value.resourceId)));
|
||||
holder.itemView.findViewById(android.R.id.summary).setVisibility(View.GONE);
|
||||
holder.itemView.setClickable(true);
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showAddDialog(v.getContext());
|
||||
}
|
||||
}), setting);
|
||||
OnPreferenceChangeListener listener = (preference, newValue) -> {
|
||||
mHandler.post(() -> {
|
||||
setValue(setting, type, keycode, icon);
|
||||
updateSummary(icon);
|
||||
});
|
||||
}
|
||||
|
||||
private void bindButton(final Holder holder, int position) {
|
||||
holder.itemView.findViewById(android.R.id.icon_frame).setVisibility(View.GONE);
|
||||
holder.itemView.findViewById(android.R.id.summary).setVisibility(View.GONE);
|
||||
bindClick(holder.itemView.findViewById(R.id.close), holder);
|
||||
bindClick(holder.itemView.findViewById(R.id.width), holder);
|
||||
holder.itemView.findViewById(R.id.drag).setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
mTouchHelper.startDrag(holder);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showAddDialog(final Context context) {
|
||||
final String[] options = new String[] {
|
||||
BACK, HOME, RECENT, MENU_IME, NAVSPACE, CLIPBOARD, KEY,
|
||||
};
|
||||
final CharSequence[] labels = new CharSequence[options.length];
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
labels[i] = getLabel(options[i], context);
|
||||
}
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.select_button)
|
||||
.setItems(labels, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (KEY.equals(options[which])) {
|
||||
showKeyDialogs(context);
|
||||
} else {
|
||||
int index = mButtons.size() - 1;
|
||||
showAddedMessage(context, options[which]);
|
||||
mButtons.add(index, options[which]);
|
||||
mLabels.add(index, labels[which]);
|
||||
|
||||
notifyItemInserted(index);
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
}).setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onImageSelected(Uri uri) {
|
||||
int index = mButtons.size() - 1;
|
||||
mButtons.add(index, KEY + KEY_CODE_START + mKeycode + KEY_IMAGE_DELIM + uri.toString()
|
||||
+ KEY_CODE_END);
|
||||
mLabels.add(index, getLabel(KEY, getContext()));
|
||||
|
||||
notifyItemInserted(index);
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
private void showKeyDialogs(final Context context) {
|
||||
final KeycodeSelectionHelper.OnSelectionComplete listener =
|
||||
new KeycodeSelectionHelper.OnSelectionComplete() {
|
||||
@Override
|
||||
public void onSelectionComplete(int code) {
|
||||
mKeycode = code;
|
||||
selectImage();
|
||||
}
|
||||
};
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.keycode)
|
||||
.setMessage(R.string.keycode_description)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
KeycodeSelectionHelper.showKeycodeSelect(context, listener);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
private void showAddedMessage(Context context, String button) {
|
||||
if (CLIPBOARD.equals(button)) {
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.clipboard)
|
||||
.setMessage(R.string.clipboard_description)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void bindClick(View view, Holder holder) {
|
||||
view.setOnClickListener(this);
|
||||
view.setTag(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Holder holder = (Holder) v.getTag();
|
||||
if (v.getId() == R.id.width) {
|
||||
showWidthDialog(holder, v.getContext());
|
||||
} else if (v.getId() == R.id.close) {
|
||||
int position = holder.getAdapterPosition();
|
||||
mButtons.remove(position);
|
||||
mLabels.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void showWidthDialog(final Holder holder, Context context) {
|
||||
final String buttonSpec = mButtons.get(holder.getAdapterPosition());
|
||||
float amount = extractSize(buttonSpec);
|
||||
final AlertDialog dialog = new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.adjust_button_width)
|
||||
.setView(R.layout.nav_width_view)
|
||||
.setNegativeButton(android.R.string.cancel, null).create();
|
||||
dialog.setButton(DialogInterface.BUTTON_POSITIVE,
|
||||
context.getString(android.R.string.ok),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface d, int which) {
|
||||
final String button = extractButton(buttonSpec);
|
||||
SeekBar seekBar = (SeekBar) dialog.findViewById(R.id.seekbar);
|
||||
if (seekBar.getProgress() == 75) {
|
||||
mButtons.set(holder.getAdapterPosition(), button);
|
||||
} else {
|
||||
float amount = (seekBar.getProgress() + 25) / 100f;
|
||||
mButtons.set(holder.getAdapterPosition(), button
|
||||
+ SIZE_MOD_START + amount + SIZE_MOD_END);
|
||||
}
|
||||
notifyChanged();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
SeekBar seekBar = (SeekBar) dialog.findViewById(R.id.seekbar);
|
||||
// Range is .25 - 1.75.
|
||||
seekBar.setMax(150);
|
||||
seekBar.setProgress((int) ((amount - .25f) * 100));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mButtons.size();
|
||||
}
|
||||
|
||||
private final ItemTouchHelper.Callback mCallbacks = new ItemTouchHelper.Callback() {
|
||||
@Override
|
||||
public boolean isLongPressDragEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemViewSwipeEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMovementFlags(RecyclerView recyclerView,
|
||||
RecyclerView.ViewHolder viewHolder) {
|
||||
if (viewHolder.getItemViewType() != BUTTON_ID) {
|
||||
return makeMovementFlags(0, 0);
|
||||
}
|
||||
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
|
||||
return makeMovementFlags(dragFlags, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
|
||||
RecyclerView.ViewHolder target) {
|
||||
int from = viewHolder.getAdapterPosition();
|
||||
int to = target.getAdapterPosition();
|
||||
if (to == 0) {
|
||||
// Can't go above the top.
|
||||
return false;
|
||||
}
|
||||
move(from, to, mButtons);
|
||||
move(from, to, mLabels);
|
||||
notifyChanged();
|
||||
notifyItemMoved(from, to);
|
||||
return true;
|
||||
}
|
||||
|
||||
private <T> void move(int from, int to, List<T> list) {
|
||||
list.add(from > to ? to : to + 1, list.get(from));
|
||||
list.remove(from > to ? from + 1 : from);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
||||
// Don't care.
|
||||
}
|
||||
return true;
|
||||
};
|
||||
type.setOnPreferenceChangeListener(listener);
|
||||
icon.setOnPreferenceChangeListener(listener);
|
||||
keycode.setOnPreferenceClickListener(preference -> {
|
||||
EditText editText = new EditText(getContext());
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(preference.getTitle())
|
||||
.setView(editText)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
int code = KeyEvent.KEYCODE_ENTER;
|
||||
try {
|
||||
code = Integer.parseInt(editText.getText().toString());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
keycode.setSummary(code + "");
|
||||
setValue(setting, type, keycode, icon);
|
||||
}).show();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void updateSummary(ListPreference icon) {
|
||||
try {
|
||||
int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14,
|
||||
getContext().getResources().getDisplayMetrics());
|
||||
String pkg = icon.getValue().split("/")[0];
|
||||
int id = Integer.parseInt(icon.getValue().split("/")[1]);
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
Drawable d = Icon.createWithResource(pkg, id)
|
||||
.loadDrawable(getContext());
|
||||
d.setTint(Color.BLACK);
|
||||
d.setBounds(0, 0, size, size);
|
||||
ImageSpan span = new ImageSpan(d);
|
||||
builder.append(" ", span, 0);
|
||||
icon.setSummary(builder);
|
||||
} catch (Exception e) {
|
||||
Log.d("NavButton", "Problem with summary", e);
|
||||
icon.setSummary(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void setValue(String setting, DropDownPreference type, Preference keycode,
|
||||
ListPreference icon) {
|
||||
String button = type.getValue();
|
||||
if (KEY.equals(button)) {
|
||||
String uri = icon.getValue();
|
||||
int code = KeyEvent.KEYCODE_ENTER;
|
||||
try {
|
||||
code = Integer.parseInt(keycode.getSummary().toString());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
button = button + KEY_CODE_START + code + KEY_IMAGE_DELIM + uri + KEY_CODE_END;
|
||||
}
|
||||
TunerService.get(getContext()).setValue(setting, button);
|
||||
}
|
||||
|
||||
private void setupIcons(ListPreference icon) {
|
||||
CharSequence[] labels = new CharSequence[ICONS.length];
|
||||
CharSequence[] values = new CharSequence[ICONS.length];
|
||||
int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14,
|
||||
getContext().getResources().getDisplayMetrics());
|
||||
for (int i = 0; i < ICONS.length; i++) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i])
|
||||
.loadDrawable(getContext());
|
||||
d.setTint(Color.BLACK);
|
||||
d.setBounds(0, 0, size, size);
|
||||
ImageSpan span = new ImageSpan(d);
|
||||
builder.append(" ", span, 0);
|
||||
labels[i] = builder;
|
||||
values[i] = getContext().getPackageName() + "/" + ICONS[i];
|
||||
}
|
||||
icon.setEntries(labels);
|
||||
icon.setEntryValues(values);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
@@ -126,6 +127,12 @@ public class TunerService extends SystemUI {
|
||||
return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
|
||||
}
|
||||
|
||||
public String getValue(String setting, String def) {
|
||||
String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
|
||||
if (ret == null) return def;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void setValue(String setting, int value) {
|
||||
Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user