diff options
author | Andrew Wilson <anwilson@google.com> | 2014-09-09 16:56:28 -0700 |
---|---|---|
committer | Andrew Wilson <anwilson@google.com> | 2014-09-09 16:56:28 -0700 |
commit | 30736d506c12af7aa9d0266f1ea389cc9abf29b8 (patch) | |
tree | 3d0c3c5270f7dd3f204413cbebc046843f154156 | |
parent | a6f8160152d4e1ae2503d13ee92ce7b499aea18f (diff) | |
download | android_packages_apps_TvSettings-30736d506c12af7aa9d0266f1ea389cc9abf29b8.tar.gz android_packages_apps_TvSettings-30736d506c12af7aa9d0266f1ea389cc9abf29b8.tar.bz2 android_packages_apps_TvSettings-30736d506c12af7aa9d0266f1ea389cc9abf29b8.zip |
Quick Settings.
Change-Id: I74c9f4c31c4008aca31c047c2174381db8270789
25 files changed, 1112 insertions, 0 deletions
diff --git a/QuickSettings/Android.mk b/QuickSettings/Android.mk new file mode 100644 index 00000000..6b3f5021 --- /dev/null +++ b/QuickSettings/Android.mk @@ -0,0 +1,26 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_PACKAGE_NAME := TvQuickSettings + +LOCAL_MODULE_TAGS := optional +LOCAL_SDK_VERSION := current + +LOCAL_SRC_FILES := \ + $(call all-java-files-under, src) + +LOCAL_RESOURCE_DIR := \ + frameworks/support/v17/leanback/res \ + $(LOCAL_PATH)/res + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-v4 \ + android-support-v7-recyclerview \ + android-support-v17-leanback + +LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages android.support.v17.leanback + +LOCAL_CERTIFICATE := platform +LOCAL_PRIVILEGED_MODULE := true + +include $(BUILD_PACKAGE) diff --git a/QuickSettings/AndroidManifest.xml b/QuickSettings/AndroidManifest.xml new file mode 100644 index 00000000..f8c76f31 --- /dev/null +++ b/QuickSettings/AndroidManifest.xml @@ -0,0 +1,42 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tv.quicksettings" + android:sharedUserId="android.uid.system" > + + <uses-sdk android:minSdkVersion="L" /> + + <uses-permission android:name="android.permission.WRITE_SETTINGS" /> + + <application + android:hardwareAccelerated="true" + android:icon="@mipmap/ic_launcher_quicksettings" + android:label="@string/quicksettings_label" + android:requiredForAllUsers="true" + android:theme="@style/Theme.QuickSettings" > + <activity + android:name="QuickSettings" + android:label="@string/quicksettings_label_launcher" + android:launchMode="singleTask" + android:theme="@style/Theme.QuickSettings" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <action android:name="com.android.tv.QUICK_SETTINGS" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <intent-filter + android:icon="@mipmap/ic_launcher_quicksettings" + android:label="@string/quicksettings_label" + android:priority="0" > + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LEANBACK_SETTINGS" /> + </intent-filter> + </activity> + <activity + android:name="SettingsDialog" + android:exported="false" + android:theme="@style/Theme.QuickSettings" /> + </application> + +</manifest>
\ No newline at end of file diff --git a/QuickSettings/res/color/text_focused_bright.xml b/QuickSettings/res/color/text_focused_bright.xml new file mode 100644 index 00000000..166e95df --- /dev/null +++ b/QuickSettings/res/color/text_focused_bright.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:color="@color/setting_text_title_unfocused_color" android:state_focused="false" /> + <item android:color="@color/setting_text_title_color" android:state_focused="true" /> +</selector>
\ No newline at end of file diff --git a/QuickSettings/res/drawable/bg.xml b/QuickSettings/res/drawable/bg.xml new file mode 100644 index 00000000..858a375d --- /dev/null +++ b/QuickSettings/res/drawable/bg.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" ?> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/panel_bg" /> + <corners android:radius="@dimen/panel_corner_radius" /> +</shape> diff --git a/QuickSettings/res/drawable/setting_background.xml b/QuickSettings/res/drawable/setting_background.xml new file mode 100644 index 00000000..d105b83e --- /dev/null +++ b/QuickSettings/res/drawable/setting_background.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:state_focused="false"> + <shape> + <solid android:color="@color/side_panel_background" /> + </shape> + </item> + + <item android:state_focused="true"> + <shape> + <solid android:color="@color/side_panel_focused_background" /> + </shape> + </item> + +</selector>
\ No newline at end of file diff --git a/QuickSettings/res/layout/dialog_setting.xml b/QuickSettings/res/layout/dialog_setting.xml new file mode 100644 index 00000000..639bd7f9 --- /dev/null +++ b/QuickSettings/res/layout/dialog_setting.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/setting_title" + android:layout_width="@dimen/main_panel_text_width_minus_padding" + android:layout_height="@dimen/main_panel_text_height" + android:focusable="true" + android:focusableInTouchMode="true" + android:fontFamily="sans-serif-condensed" + android:gravity="right|center_vertical" + android:textAllCaps="true" + android:textColor="@color/text_focused_bright" + android:textSize="@dimen/setting_text_title_size" /> diff --git a/QuickSettings/res/layout/main_quicksettings.xml b/QuickSettings/res/layout/main_quicksettings.xml new file mode 100644 index 00000000..24325a11 --- /dev/null +++ b/QuickSettings/res/layout/main_quicksettings.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:lb="http://schemas.android.com/apk/res-auto" + android:id="@+id/main_panel" + android:layout_width="@dimen/main_panel_width" + android:layout_height="@dimen/main_panel_height" + android:background="@drawable/bg" + android:elevation="@dimen/panel_z" + android:orientation="horizontal" > + + <android.support.v17.leanback.widget.VerticalGridView + android:id="@+id/main_panel_list" + android:layout_width="@dimen/main_panel_text_width" + android:layout_height="@dimen/main_panel_height" + android:clipToPadding="false" + android:focusable="true" + android:focusableInTouchMode="true" + android:paddingEnd="@dimen/slider_horizontal_padding" /> + + <SeekBar + android:id="@+id/main_slider" + android:layout_width="@dimen/slider_width" + android:layout_height="wrap_content" + android:layout_gravity="left|center_vertical" + android:clipToPadding="false" + android:focusable="false" + android:focusableInTouchMode="false" + android:orientation="horizontal" + android:paddingEnd="@dimen/slider_horizontal_padding" + android:visibility="gone" /> + + <TextView + android:id="@+id/setting_value" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:fontFamily="sans-serif-condensed" + android:gravity="left|center_vertical" + android:textAllCaps="true" + android:textColor="@color/setting_text_title_unfocused_color" + android:textSize="@dimen/setting_text_title_size" /> + +</LinearLayout>
\ No newline at end of file diff --git a/QuickSettings/res/layout/setting.xml b/QuickSettings/res/layout/setting.xml new file mode 100644 index 00000000..0aff71f6 --- /dev/null +++ b/QuickSettings/res/layout/setting.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/setting_background" + android:focusable="true" + android:focusableInTouchMode="true" + android:orientation="vertical" + android:paddingBottom="@dimen/setting_padding_bottom" + android:paddingTop="@dimen/setting_padding_top" > + + <TextView + android:id="@+id/setting_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif-condensed" + android:paddingEnd="@dimen/setting_text_padding_right" + android:paddingStart="@dimen/setting_text_padding_left" + android:textColor="@color/setting_text_title_color" + android:textSize="@dimen/setting_text_title_size" /> + + <TextView + android:id="@+id/setting_value" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif" + android:paddingEnd="@dimen/setting_text_padding_right" + android:paddingStart="@dimen/setting_text_padding_left" + android:textColor="@color/setting_text_value_color" + android:textSize="@dimen/setting_text_value_size" /> + +</LinearLayout>
\ No newline at end of file diff --git a/QuickSettings/res/layout/side_quicksettings.xml b/QuickSettings/res/layout/side_quicksettings.xml new file mode 100644 index 00000000..6d3ac147 --- /dev/null +++ b/QuickSettings/res/layout/side_quicksettings.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:lb="http://schemas.android.com/apk/res-auto" + android:id="@+id/main_frame" + android:orientation="vertical" + android:elevation="@dimen/panel_z" + android:background="@color/side_panel_background" + android:layout_gravity="right" + android:layout_width="@dimen/panel_width" + android:layout_height="match_parent"> + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="@dimen/side_panel_title_padding_top" + android:paddingStart="@dimen/side_panel_title_padding_left" + android:paddingEnd="@dimen/side_panel_title_padding_right" + android:background="@color/side_panel_title_background"> + + <TextView android:id="@+id/side_panel_title" + android:layout_width="match_parent" + android:layout_height="@dimen/side_panel_title_text_height" + android:gravity="center_vertical" + android:textSize="@dimen/side_panel_title_text_size" + android:textColor="@color/menu_default_text_color" + android:singleLine="true" + android:fontFamily="sans-serif-condensed" + android:text="@string/main_label" /> + </FrameLayout> + + <android.support.v17.leanback.widget.VerticalGridView + android:id="@+id/side_panel_list" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clipChildren="false" + android:clipToPadding="false" + android:focusable="true" + android:focusableInTouchMode="true" + android:paddingTop="@dimen/side_panel_list_padding_top" + android:paddingBottom="@dimen/side_panel_list_padding_bottom" + lb:verticalMargin="0dp" /> + +</LinearLayout> diff --git a/QuickSettings/res/mipmap-hdpi/ic_launcher_quicksettings.png b/QuickSettings/res/mipmap-hdpi/ic_launcher_quicksettings.png Binary files differnew file mode 100644 index 00000000..ea89c141 --- /dev/null +++ b/QuickSettings/res/mipmap-hdpi/ic_launcher_quicksettings.png diff --git a/QuickSettings/res/mipmap-mdpi/ic_launcher_quicksettings.png b/QuickSettings/res/mipmap-mdpi/ic_launcher_quicksettings.png Binary files differnew file mode 100644 index 00000000..5c271e56 --- /dev/null +++ b/QuickSettings/res/mipmap-mdpi/ic_launcher_quicksettings.png diff --git a/QuickSettings/res/mipmap-xhdpi/ic_launcher_quicksettings.png b/QuickSettings/res/mipmap-xhdpi/ic_launcher_quicksettings.png Binary files differnew file mode 100644 index 00000000..ee679289 --- /dev/null +++ b/QuickSettings/res/mipmap-xhdpi/ic_launcher_quicksettings.png diff --git a/QuickSettings/res/mipmap-xxhdpi/ic_launcher_quicksettings.png b/QuickSettings/res/mipmap-xxhdpi/ic_launcher_quicksettings.png Binary files differnew file mode 100644 index 00000000..50893abe --- /dev/null +++ b/QuickSettings/res/mipmap-xxhdpi/ic_launcher_quicksettings.png diff --git a/QuickSettings/res/mipmap-xxxhdpi/ic_launcher_quicksettings.png b/QuickSettings/res/mipmap-xxxhdpi/ic_launcher_quicksettings.png Binary files differnew file mode 100644 index 00000000..23bf9beb --- /dev/null +++ b/QuickSettings/res/mipmap-xxxhdpi/ic_launcher_quicksettings.png diff --git a/QuickSettings/res/values/colors.xml b/QuickSettings/res/values/colors.xml new file mode 100644 index 00000000..a2215eff --- /dev/null +++ b/QuickSettings/res/values/colors.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" ?> +<resources> + <color name="menu_default_text_color">#FFEEEEEE</color> + <color name="side_panel_title_background">#00A6F6</color> + <color name="side_panel_background">#384248</color> + <color name="side_panel_focused_background">#FF5C6467</color> + <color name="setting_text_title_color">#FFEEEEEE</color> + <color name="setting_text_title_unfocused_color">#80EEEEEE</color> + <color name="setting_text_value_color">#A0EEEEEE</color> + <color name="panel_bg">#E6000000</color> +</resources> diff --git a/QuickSettings/res/values/config.xml b/QuickSettings/res/values/config.xml new file mode 100644 index 00000000..f2004776 --- /dev/null +++ b/QuickSettings/res/values/config.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="setting_preset_name">Preset mode</string> + <string name="setting_reset_defaults_name">Reset to defaults</string> + + <string-array name="setting_names"> + <item>Backlight</item> + <item>Contrast</item> + <item>Brightness</item> + <item>Sharpness</item> + <item>Color</item> + <item>Tint</item> + </string-array> + <string-array name="setting_preset_choices"> + <item>Standard</item> + <item>Cinema</item> + <item>Vivid</item> + <item>Game</item> + <item>Custom</item> + </string-array> + + <integer name="standard_setting_index">0</integer> + <integer name="cinema_setting_index">1</integer> + <integer name="vivid_setting_index">2</integer> + <integer name="game_setting_index">3</integer> + <integer name="custom_setting_index">4</integer> + + <integer-array name="standard_setting_values"> + <item>50</item> + <item>40</item> + <item>50</item> + <item>100</item> + <item>50</item> + <item>50</item> + </integer-array> + <integer-array name="cinema_setting_values"> + <item>10</item> + <item>20</item> + <item>90</item> + <item>20</item> + <item>30</item> + <item>60</item> + </integer-array> + <integer-array name="vivid_setting_values"> + <item>20</item> + <item>60</item> + <item>90</item> + <item>50</item> + <item>0</item> + <item>0</item> + </integer-array> + <integer-array name="game_setting_values"> + <item>40</item> + <item>30</item> + <item>30</item> + <item>20</item> + <item>90</item> + <item>90</item> + </integer-array> + <integer-array name="setting_max_values"> + <item>100</item> + <item>100</item> + <item>100</item> + <item>100</item> + <item>100</item> + <item>100</item> + </integer-array> + +</resources>
\ No newline at end of file diff --git a/QuickSettings/res/values/dimens.xml b/QuickSettings/res/values/dimens.xml new file mode 100644 index 00000000..99c0fbb8 --- /dev/null +++ b/QuickSettings/res/values/dimens.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <dimen name="panel_corner_radius">2dp</dimen> + <dimen name="panel_width">360dp</dimen> + <dimen name="panel_z">12dp</dimen> + <dimen name="panel_y_offset">60dp</dimen> + <dimen name="panel_vertical_padding">10dp</dimen> + <dimen name="panel_horizontal_padding">12dp</dimen> + + <dimen name="main_panel_text_width_minus_padding">180dp</dimen> + <dimen name="main_panel_text_width">200dp</dimen> + <dimen name="main_panel_text_height">30dp</dimen> + <dimen name="main_panel_text_height_half">15dp</dimen> + <dimen name="main_panel_width">500dp</dimen> + <dimen name="main_panel_height">90dp</dimen> + + <dimen name="side_panel_title_padding_top">27dp</dimen> + <dimen name="side_panel_title_padding_left">32dp</dimen> + <dimen name="side_panel_title_padding_right">56dp</dimen> + <dimen name="side_panel_title_text_height">60dp</dimen> + <dimen name="side_panel_title_text_size">24sp</dimen> + + <dimen name="side_panel_list_padding_top">48dp</dimen> + <dimen name="side_panel_list_padding_bottom">48dp</dimen> + + <dimen name="setting_padding_top">9dp</dimen> + <dimen name="setting_padding_bottom">16dp</dimen> + <dimen name="setting_text_padding_left">32dp</dimen> + <dimen name="setting_text_padding_right">56dp</dimen> + <dimen name="setting_text_title_size">18sp</dimen> + <dimen name="setting_text_value_size">12sp</dimen> + + <dimen name="slider_width">200dp</dimen> + <dimen name="slider_vertical_padding">6dp</dimen> + <dimen name="slider_horizontal_padding">20dp</dimen> +</resources> diff --git a/QuickSettings/res/values/strings.xml b/QuickSettings/res/values/strings.xml new file mode 100644 index 00000000..6049fe06 --- /dev/null +++ b/QuickSettings/res/values/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> + +<resources> + <string name="quicksettings_label">Picture Mode</string> + <string name="quicksettings_label_launcher">Picture Mode</string> + <string name="main_label">Picture</string> + <string name="reset_dialog_message">Reset picture settings to defaults?</string> +</resources> diff --git a/QuickSettings/res/values/themes.xml b/QuickSettings/res/values/themes.xml new file mode 100644 index 00000000..8a0d66ab --- /dev/null +++ b/QuickSettings/res/values/themes.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> + <!-- Copyright (C) 2014 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. +--> + +<resources> + + <!-- Based on Theme.Material.Dialog.NoFrame --> + <style name="Theme.QuickSettings" parent="android:Theme.Material"> + <item name="android:windowFrame">@null</item> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowNoTitle">true</item> + <item name="android:windowBackground">@android:color/transparent</item> + <item name="android:backgroundDimEnabled">false</item> + <item name="android:windowIsFloating">true</item> + <item name="android:windowContentOverlay">@null</item> + <!-- TODO: consider an animation for these --> + <item name="android:windowAnimationStyle">@null</item> + <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item> + <item name="android:windowActionBar">false</item> + <item name="android:windowActionModeOverlay">true</item> + <item name="android:windowCloseOnTouchOutside">false</item> + + <item name="android:colorBackgroundCacheHint">@null</item> + + <item name="android:textAppearance">@android:style/TextAppearance.Material</item> + <item name="android:textAppearanceInverse">@android:style/TextAppearance.Material.Inverse</item> + + <item name="android:listPreferredItemPaddingLeft">16dip</item> + <item name="android:listPreferredItemPaddingRight">16dip</item> + <item name="android:listPreferredItemPaddingStart">16dip</item> + <item name="android:listPreferredItemPaddingEnd">16dip</item> + + <item name="@*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item> + </style> +</resources> diff --git a/QuickSettings/src/com/android/tv/quicksettings/DialogAdapter.java b/QuickSettings/src/com/android/tv/quicksettings/DialogAdapter.java new file mode 100644 index 00000000..ffc76963 --- /dev/null +++ b/QuickSettings/src/com/android/tv/quicksettings/DialogAdapter.java @@ -0,0 +1,93 @@ + +package com.android.tv.quicksettings; + +import android.content.Intent; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.ArrayList; + +public class DialogAdapter extends RecyclerView.Adapter<DialogAdapter.ViewHolder> { + + private static final float FOCUSED_SCALE = 1f; + private static final float UNFOCUSED_SCALE = 0.5f; + + private final ArrayList<Setting> mSettings; + private final int mPivotX; + private final int mPivotY; + private final SettingClickedListener mSettingClickedListener; + + public DialogAdapter(ArrayList<Setting> settings, int pivotX, int pivotY, + SettingClickedListener settingClickedListener) { + mSettings = settings; + mPivotX = pivotX; + mPivotY = pivotY; + mSettingClickedListener = settingClickedListener; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.dialog_setting, parent, + false); + final ViewHolder vh = new ViewHolder(v); + v.setPivotX(mPivotX); + v.setPivotY(mPivotY); + v.setScaleX(UNFOCUSED_SCALE); + v.setScaleY(UNFOCUSED_SCALE); + v.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Setting s = vh.mSetting; + if (s != null) { + mSettingClickedListener.onSettingClicked(s); + } + } + }); + v.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean focusGained) { + float scale = focusGained ? FOCUSED_SCALE : UNFOCUSED_SCALE; + v.animate().cancel(); + v.animate().scaleX(scale).scaleY(scale).setDuration( + v.getContext().getResources() + .getInteger(android.R.integer.config_shortAnimTime)) + .start(); + } + }); + return vh; + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + Setting s = mSettings.get(position); + holder.setSetting(s); + holder.mTitle.setText(s.getTitle()); + } + + @Override + public void onViewRecycled(ViewHolder holder) { + holder.setSetting(null); + } + + @Override + public int getItemCount() { + return mSettings.size(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + private final TextView mTitle; + private Setting mSetting; + + public ViewHolder(View itemView) { + super(itemView); + mTitle = (TextView) itemView.findViewById(R.id.setting_title); + } + + public void setSetting(Setting setting) { + mSetting = setting; + } + } +} diff --git a/QuickSettings/src/com/android/tv/quicksettings/PanelAdapter.java b/QuickSettings/src/com/android/tv/quicksettings/PanelAdapter.java new file mode 100644 index 00000000..96831e98 --- /dev/null +++ b/QuickSettings/src/com/android/tv/quicksettings/PanelAdapter.java @@ -0,0 +1,97 @@ + +package com.android.tv.quicksettings; + +import android.content.Intent; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.ArrayList; + +public class PanelAdapter extends RecyclerView.Adapter<PanelAdapter.ViewHolder> { + + static class ViewHolder extends RecyclerView.ViewHolder { + private final TextView mTitle; + private final TextView mValue; + private Setting mSetting; + + public ViewHolder(View itemView) { + super(itemView); + mTitle = (TextView) itemView.findViewById(R.id.setting_title); + mValue = (TextView) itemView.findViewById(R.id.setting_value); + } + + public void setSetting(Setting setting) { + mSetting = setting; + } + } + + private static final String TAG = "QuickSettings"; + + private final SettingClickedListener mSettingClickedListener; + private ArrayList<Setting> mSettings; + + public PanelAdapter(ArrayList<Setting> settings, SettingClickedListener settingClickedListener) { + mSettings = settings; + mSettingClickedListener = settingClickedListener; + } + + @Override + public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.setting, parent, false); + final ViewHolder vh = new ViewHolder(v); + v.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Setting s = vh.mSetting; + if (s != null) { + mSettingClickedListener.onSettingClicked(s); + } + } + }); + return vh; + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + Setting s = mSettings.get(position); + holder.setSetting(s); + holder.mTitle.setText(s.getTitle()); + switch (s.getType()) { + case Setting.TYPE_INT: + holder.mValue.setText(Integer.toString(s.getIntValue())); + break; + case Setting.TYPE_STRING: + holder.mValue.setText(s.getStringValue()); + break; + default: + holder.mValue.setText(""); + break; + } + if (TextUtils.isEmpty(holder.mValue.getText())) { + holder.mValue.setVisibility(View.GONE); + } else { + holder.mValue.setVisibility(View.VISIBLE); + } + } + + @Override + public void onViewRecycled(ViewHolder holder) { + holder.setSetting(null); + } + + @Override + public int getItemCount() { + return mSettings.size(); + } + + public void setSettings(ArrayList<Setting> settings) { + mSettings = settings; + notifyDataSetChanged(); + } +} diff --git a/QuickSettings/src/com/android/tv/quicksettings/QuickSettings.java b/QuickSettings/src/com/android/tv/quicksettings/QuickSettings.java new file mode 100644 index 00000000..5afab8bc --- /dev/null +++ b/QuickSettings/src/com/android/tv/quicksettings/QuickSettings.java @@ -0,0 +1,148 @@ + +package com.android.tv.quicksettings; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.v17.leanback.widget.VerticalGridView; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.TextView; + +import com.android.tv.quicksettings.SettingsDialog; + +import java.util.ArrayList; +import java.util.List; + +public class QuickSettings extends Activity { + + private static final String TAG = "QuickSettings"; + private static final int REQUEST_CODE_SET_SETTINGS = 1; + static final int PRESET_SETTING_INDEX = 0; + static final int INTEGER_SETTING_START_INDEX = 1; + + private int mSlidOutTranslationX; + private View mRootView; + private ArrayList<Setting> mSettings; + private PanelAdapter mAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + WindowManager.LayoutParams lp = getWindow().getAttributes(); + lp.gravity = Gravity.RIGHT; + getWindow().setAttributes(lp); + + setContentView(R.layout.side_quicksettings); + getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.MATCH_PARENT); + + mSlidOutTranslationX = getResources().getDimensionPixelSize(R.dimen.panel_width); + + mRootView = getWindow().getDecorView().findViewById(android.R.id.content); + mRootView.setTranslationX(mSlidOutTranslationX); + + final VerticalGridView panelList = (VerticalGridView) findViewById(R.id.side_panel_list); + + mSettings = getSettings(); + mAdapter = new PanelAdapter(mSettings, new SettingClickedListener() { + @Override + public void onSettingClicked(Setting s) { + Log.d(TAG, "Clicked Setting " + s.getTitle()); + if (s.getType() != Setting.TYPE_UNKNOWN) { + Intent intent = new Intent(QuickSettings.this, SettingsDialog.class); + intent.putExtra(SettingsDialog.EXTRA_START_POS, + panelList.getSelectedPosition()); + intent.putExtra(SettingsDialog.EXTRA_SETTINGS, mSettings); + startActivityForResult(intent, REQUEST_CODE_SET_SETTINGS); + } else { + new AlertDialog.Builder(QuickSettings.this).setPositiveButton( + android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // User clicked OK button + String[] presetSettingChoices = getResources().getStringArray( + R.array.setting_preset_choices); + mSettings.get(PRESET_SETTING_INDEX).setValue( + presetSettingChoices[getResources().getInteger( + R.integer.standard_setting_index)]); + int[] newSettingValues = getResources().getIntArray( + R.array.standard_setting_values); + for (int i = 0; i < newSettingValues.length; i++) { + mSettings.get(i + INTEGER_SETTING_START_INDEX).setValue( + newSettingValues[i]); + } + mAdapter.notifyDataSetChanged(); + } + }).setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog - do nothing + } + }).setTitle(R.string.reset_dialog_message).create().show(); + + } + } + }); + + panelList.setAdapter(mAdapter); + panelList.setSelectedPosition(0); + panelList.requestFocus(); + } + + @Override + protected void onResume() { + super.onResume(); + mRootView.animate().cancel(); + mRootView.animate().translationX(0).start(); + } + + @Override + protected void onPause() { + mRootView.animate().cancel(); + mRootView.animate().translationX(mSlidOutTranslationX).start(); + super.onPause(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_CODE_SET_SETTINGS) { + if (resultCode == RESULT_OK) { + mSettings = data.getParcelableArrayListExtra( + SettingsDialog.RESULT_EXTRA_NEW_SETTINGS_VALUES); + mAdapter.setSettings(mSettings); + } + } else { + super.onActivityResult(requestCode, resultCode, data); + } + } + + private ArrayList<Setting> getSettings() { + ArrayList<Setting> settings = new ArrayList<Setting>(); + + String[] presetSettingChoices = getResources().getStringArray( + R.array.setting_preset_choices); + settings.add(new Setting(getString(R.string.setting_preset_name), + presetSettingChoices[getResources().getInteger(R.integer.standard_setting_index)])); + String[] settingNames = getResources().getStringArray(R.array.setting_names); + int[] standardSettingValues = getResources().getIntArray(R.array.standard_setting_values); + int[] maxSettingValues = getResources().getIntArray(R.array.setting_max_values); + for (int i = 0; i < settingNames.length; i++) { + settings.add( + new Setting(settingNames[i], standardSettingValues[i], maxSettingValues[i])); + } + settings.add(new Setting(getString(R.string.setting_reset_defaults_name))); + + return settings; + } +} diff --git a/QuickSettings/src/com/android/tv/quicksettings/Setting.java b/QuickSettings/src/com/android/tv/quicksettings/Setting.java new file mode 100644 index 00000000..eed45b37 --- /dev/null +++ b/QuickSettings/src/com/android/tv/quicksettings/Setting.java @@ -0,0 +1,136 @@ + +package com.android.tv.quicksettings; + +import android.content.Intent; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.List; + +public class Setting implements Parcelable { + + static final int TYPE_UNKNOWN = 0; + static final int TYPE_INT = 1; + static final int TYPE_STRING = 2; + + private String mTitle; + private int mIntValue; + private String mStringValue; + private int mSettingType; + + private int mMaxValue; + private List<String> mStringChoices = new ArrayList<String>(); + + public Setting() { + } + + public Setting(String title) { + mTitle = title; + mSettingType = TYPE_UNKNOWN; + } + + public Setting(String title, int value) { + this(title, value, 0); + } + + public Setting(String title, int value, int max) { + this(title); + mIntValue = value; + mMaxValue = max; + mSettingType = TYPE_INT; + } + + public Setting(String title, String value) { + this(title); + mStringValue = value; + mSettingType = TYPE_STRING; + } + + public int getType() { + return mSettingType; + } + + public String getTitle() { + return mTitle; + } + + public void setTitle(String title) { + mTitle = title; + } + + public int getMaxValue() { + return mMaxValue; + } + + public void setMaxValue(int max) { + mMaxValue = max; + mSettingType = TYPE_INT; + } + + public List<String> getStringChoices() { + return mStringChoices; + } + + public void setStringChoices(List<String> choices) { + mStringChoices = choices; + mSettingType = TYPE_STRING; + } + + public void addStringChoice(String choice) { + mStringChoices.add(choice); + } + + public int getIntValue() { + return mIntValue; + } + + public String getStringValue() { + return mStringValue; + } + + public void setValue(int value) { + mIntValue = value; + mSettingType = TYPE_INT; + } + + public void setValue(String value) { + mStringValue = value; + mSettingType = TYPE_STRING; + } + + public static Parcelable.Creator<Setting> CREATOR = new Parcelable.Creator<Setting>() { + @Override + public Setting createFromParcel(Parcel source) { + Setting setting = new Setting(); + setting.mTitle = source.readString(); + setting.mIntValue = source.readInt(); + setting.mStringValue = source.readString(); + setting.mSettingType = source.readInt(); + setting.mMaxValue = source.readInt(); + source.readStringList(setting.mStringChoices); + return setting; + } + + @Override + public Setting[] newArray(int size) { + return new Setting[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mTitle); + dest.writeInt(mIntValue); + dest.writeString(mStringValue); + dest.writeInt(mSettingType); + dest.writeInt(mMaxValue); + dest.writeStringList(mStringChoices); + } +} diff --git a/QuickSettings/src/com/android/tv/quicksettings/SettingClickedListener.java b/QuickSettings/src/com/android/tv/quicksettings/SettingClickedListener.java new file mode 100644 index 00000000..8ee3d6d9 --- /dev/null +++ b/QuickSettings/src/com/android/tv/quicksettings/SettingClickedListener.java @@ -0,0 +1,6 @@ + +package com.android.tv.quicksettings; + +public interface SettingClickedListener { + void onSettingClicked(Setting s); +} diff --git a/QuickSettings/src/com/android/tv/quicksettings/SettingsDialog.java b/QuickSettings/src/com/android/tv/quicksettings/SettingsDialog.java new file mode 100644 index 00000000..87c6c3ad --- /dev/null +++ b/QuickSettings/src/com/android/tv/quicksettings/SettingsDialog.java @@ -0,0 +1,236 @@ + +package com.android.tv.quicksettings; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.Parcelable; +import android.support.v17.leanback.widget.OnChildSelectedListener; +import android.support.v17.leanback.widget.VerticalGridView; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.ScaleAnimation; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SettingsDialog extends Activity { + + private static final String TAG = "SettingsDialog"; + private static final boolean DEBUG = true; + + static final String EXTRA_START_POS = "com.android.tv.quicksettings.START_POS"; + static final String EXTRA_SETTINGS = "com.android.tv.quicksettings.SETTINGS"; + static final String + RESULT_EXTRA_NEW_SETTINGS_VALUES = "com.android.tv.quicksettings.NEW_SETTINGS_VALUES"; + private static final int SETTING_INT_VALUE_MIN = 0; + private static final int SETTING_INT_VALUE_STEP = 10; + + private VerticalGridView mPanelList; + private SeekBar mSeekBar; + private TextView mSettingValue; + private DialogAdapter mAdapter; + private SettingSelectedListener mSettingSelectedListener = new SettingSelectedListener(); + private Setting mFocusedSetting; + private ArrayList<Setting> mSettings; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + WindowManager.LayoutParams lp = getWindow().getAttributes(); + lp.height = WindowManager.LayoutParams.MATCH_PARENT; + lp.gravity = Gravity.BOTTOM | Gravity.CENTER; + lp.y = getResources().getDimensionPixelSize(R.dimen.panel_y_offset); + getWindow().setAttributes(lp); + + setContentView(R.layout.main_quicksettings); + + Intent intent = getIntent(); + int startPos = intent.getIntExtra(EXTRA_START_POS, -1); + if (DEBUG) + Log.d(TAG, "startPos=" + startPos); + + mPanelList = (VerticalGridView) findViewById(R.id.main_panel_list); + mPanelList.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE); + mPanelList.setOnChildSelectedListener(mSettingSelectedListener); + + mSettings = getIntent().getParcelableArrayListExtra(EXTRA_SETTINGS); + int pivotX = getResources().getDimensionPixelSize( + R.dimen.main_panel_text_width_minus_padding); + int pivotY = getResources().getDimensionPixelSize(R.dimen.main_panel_text_height_half); + + mAdapter = new DialogAdapter(mSettings, pivotX, pivotY, new SettingClickedListener() { + @Override + public void onSettingClicked(Setting s) { + if (s.getType() != Setting.TYPE_UNKNOWN) { + setResult(RESULT_OK, new Intent().putExtra(RESULT_EXTRA_NEW_SETTINGS_VALUES, + mSettings)); + finish(); + } else { + new AlertDialog.Builder(SettingsDialog.this).setPositiveButton( + android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // User clicked OK button + String[] presetSettingChoices = getResources().getStringArray( + R.array.setting_preset_choices); + mSettings.get(QuickSettings.PRESET_SETTING_INDEX).setValue( + presetSettingChoices[getResources().getInteger( + R.integer.standard_setting_index)]); + int[] newSettingValues = getResources().getIntArray( + R.array.standard_setting_values); + for (int i = 0; i < newSettingValues.length; i++) { + mSettings.get(i + QuickSettings.INTEGER_SETTING_START_INDEX) + .setValue( + newSettingValues[i]); + } + } + }).setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog - do nothing + } + }).setTitle(R.string.reset_dialog_message).create().show(); + } + } + }); + + mPanelList.setAdapter(mAdapter); + mPanelList.setSelectedPosition(startPos); + mPanelList.requestFocus(); + + mSeekBar = (SeekBar) findViewById(R.id.main_slider); + + mSettingValue = (TextView) findViewById(R.id.setting_value); + } + + private class SettingSelectedListener implements OnChildSelectedListener { + private static final float ALPHA_UNSELECTED = 0.3f; + private static final float ALPHA_SELECTED = 1.0f; + private static final float SCALE_UNSELECTED = 1.0f; + private static final float SCALE_SELECTED = 1.3f; + + @Override + public void onChildSelected(ViewGroup parent, View view, int position, long id) { + mFocusedSetting = mSettings.get(position); + switch (mFocusedSetting.getType()) { + case Setting.TYPE_STRING: + mSettingValue.setVisibility(View.VISIBLE); + mSettingValue.setText(mFocusedSetting.getStringValue()); + mSeekBar.setVisibility(View.GONE); + break; + case Setting.TYPE_INT: + mSettingValue.setVisibility(View.VISIBLE); + mSettingValue.setText(Integer.toString(mFocusedSetting.getIntValue())); + mSeekBar.setMax(mFocusedSetting.getMaxValue()); + mSeekBar.setProgress(mFocusedSetting.getIntValue()); + mSeekBar.setVisibility(View.VISIBLE); + break; + default: + mSettingValue.setVisibility(View.GONE); + mSeekBar.setVisibility(View.GONE); + break; + } + } + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (mFocusedSetting == null) { + return super.onKeyUp(keyCode, event); + } + switch (mFocusedSetting.getType()) { + case Setting.TYPE_INT: + return integerSettingHandleKeyCode(keyCode, event); + case Setting.TYPE_STRING: + return stringSettingHandleKeyCode(keyCode, event); + default: + return super.onKeyUp(keyCode, event); + } + } + + private boolean integerSettingHandleKeyCode(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_RIGHT: + setFocusedSettingToValue(Math.min( + mFocusedSetting.getIntValue() + SETTING_INT_VALUE_STEP, + mFocusedSetting.getMaxValue())); + return true; + case KeyEvent.KEYCODE_DPAD_LEFT: + setFocusedSettingToValue(Math.max( + mFocusedSetting.getIntValue() - SETTING_INT_VALUE_STEP, + SETTING_INT_VALUE_MIN)); + return true; + default: + return super.onKeyUp(keyCode, event); + } + } + + private void setFocusedSettingToValue(int value) { + mFocusedSetting.setValue(value); + mSeekBar.setProgress(mFocusedSetting.getIntValue()); + mSettingValue.setText(Integer.toString(mFocusedSetting.getIntValue())); + String[] presetSettingChoices = getResources().getStringArray( + R.array.setting_preset_choices); + mSettings.get(QuickSettings.PRESET_SETTING_INDEX).setValue( + presetSettingChoices[getResources().getInteger(R.integer.custom_setting_index)]); + } + + private boolean stringSettingHandleKeyCode(int keyCode, KeyEvent event) { + if (!mFocusedSetting.getTitle().equals(getString(R.string.setting_preset_name))) { + return super.onKeyUp(keyCode, event); + } + + String[] presetSettingChoices = getResources().getStringArray( + R.array.setting_preset_choices); + + int currentIndex = Arrays.asList(presetSettingChoices).indexOf( + mFocusedSetting.getStringValue()); + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_RIGHT: + currentIndex++; + break; + case KeyEvent.KEYCODE_DPAD_LEFT: + currentIndex--; + break; + default: + return super.onKeyUp(keyCode, event); + } + int newIndex = (currentIndex + presetSettingChoices.length) % presetSettingChoices.length; + mFocusedSetting.setValue(presetSettingChoices[newIndex]); + mSettingValue.setText(mFocusedSetting.getStringValue()); + int[] newSettingValues = null; + if (newIndex == getResources().getInteger(R.integer.standard_setting_index)) { + newSettingValues = getResources().getIntArray(R.array.standard_setting_values); + } else if (newIndex == getResources().getInteger(R.integer.cinema_setting_index)) { + newSettingValues = getResources().getIntArray(R.array.cinema_setting_values); + } else if (newIndex == getResources().getInteger(R.integer.vivid_setting_index)) { + newSettingValues = getResources().getIntArray(R.array.vivid_setting_values); + } else if (newIndex == getResources().getInteger(R.integer.game_setting_index)) { + newSettingValues = getResources().getIntArray(R.array.game_setting_values); + } + if (newSettingValues != null) { + for (int i = 0; i < newSettingValues.length; i++) { + mSettings.get(i + QuickSettings.INTEGER_SETTING_START_INDEX).setValue( + newSettingValues[i]); + } + } + return true; + } +} |