More traditional list item style for dreams settings.

Other improvements:
 - remove "Start dreaming now", promote "When to dream" to action bar
 - added logging
 - hide dream settings button if n/a
 - new flat style for settings/preview + dividers
 - refresh dreams list when packages are installed/uninstalled
 - added placeholder for help url

Bug:7010260
Change-Id: Ia443b4f76678eaf1a52b907d50aefb0d8f7e4748
This commit is contained in:
John Spurlock
2012-08-30 14:58:16 -04:00
parent 2dff5b109b
commit 7af2aa52ac
11 changed files with 144 additions and 90 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 B

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012 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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/dream_info_bg_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/dream_info_bg_unpressed" android:state_pressed="false"/>
</selector>

View File

@@ -16,19 +16,26 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/dream_info_bg"
android:orientation="vertical" >
android:background="?android:attr/selectableItemBackground"
android:divider="?android:attr/dividerHorizontal"
android:orientation="vertical"
android:showDividers="middle" >
<RelativeLayout
android:id="@android:id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
android:layout_height="wrap_content"
android:layout_alignParentTop="true" >
<ImageView
android:id="@android:id/icon"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_centerVertical="true"
android:layout_margin="8dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="6dp"
android:layout_marginTop="10dp"
android:contentDescription="@null"
android:scaleType="fitCenter" />
@@ -38,7 +45,6 @@
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_margin="8dp"
android:duplicateParentState="true" />
<TextView
@@ -49,33 +55,42 @@
android:layout_toLeftOf="@android:id/button1"
android:layout_toRightOf="@android:id/icon"
android:ellipsize="end"
android:fontFamily="sans-serif-light"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge" />
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
<RelativeLayout
android:id="@android:id/widget_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
android:layout_height="wrap_content"
android:visibility="gone" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
android:layout_height="wrap_content"
android:divider="?android:attr/dividerVertical"
android:dividerPadding="12dp"
android:showDividers="middle" >
<Button
android:id="@android:id/button2"
style="@android:style/Widget.ActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/screensaver_settings_dream_settings" />
android:text="@string/screensaver_settings_dream_settings"
android:textAllCaps="true"
android:textSize="12dp" />
<Button
android:id="@android:id/button3"
style="@android:style/Widget.ActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/screensaver_settings_dream_preview" />
android:text="@string/screensaver_settings_dream_preview"
android:textAllCaps="true"
android:textSize="12dp" />
</LinearLayout>
</RelativeLayout>

View File

@@ -4167,6 +4167,8 @@
<string name="help_url_backup_reset" translatable="false"></string>
<!-- Help URL, Tethering [DO NOT TRANSLATE] -->
<string name="help_url_tether" translatable="false"></string>
<!-- Help URL, Dreams [DO NOT TRANSLATE] -->
<string name="help_url_dreams" translatable="false"></string>
<!-- User account title [CHAR LIMIT=30] -->
<string name="user_account_title">Account for content</string>

View File

@@ -31,6 +31,7 @@ import android.os.ServiceManager;
import android.provider.Settings;
import android.service.dreams.Dream;
import android.service.dreams.IDreamManager;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collections;
@@ -38,6 +39,7 @@ import java.util.Comparator;
import java.util.List;
public class DreamBackend {
private static final String TAG = DreamSettings.class.getSimpleName() + ".Backend";
public static class DreamInfo {
CharSequence caption;
@@ -45,6 +47,18 @@ public class DreamBackend {
boolean isActive;
public ComponentName componentName;
public ComponentName settingsComponentName;
@Override
public String toString() {
StringBuilder sb = new StringBuilder(DreamInfo.class.getSimpleName());
sb.append('[').append(caption);
if (isActive)
sb.append(",active");
sb.append(',').append(componentName);
if (settingsComponentName != null)
sb.append("settings=").append(settingsComponentName);
return sb.append(']').toString();
}
}
private final Context mContext;
@@ -58,6 +72,7 @@ public class DreamBackend {
}
public List<DreamInfo> getDreamInfos() {
logd("getDreamInfos()");
ComponentName activeDream = getActiveDream();
PackageManager pm = mContext.getPackageManager();
Intent dreamIntent = new Intent(Intent.ACTION_MAIN)
@@ -86,6 +101,7 @@ public class DreamBackend {
try {
return mDreamManager.getDefaultDreamComponent();
} catch (RemoteException e) {
Log.w(TAG, "Failed to get default dream", e);
return null;
}
}
@@ -95,6 +111,7 @@ public class DreamBackend {
}
public void setEnabled(boolean value) {
logd("setEnabled(%s)", value);
setBoolean(SCREENSAVER_ENABLED, value);
}
@@ -103,6 +120,7 @@ public class DreamBackend {
}
public void setActivatedOnDock(boolean value) {
logd("setActivatedOnDock(%s)", value);
setBoolean(SCREENSAVER_ACTIVATE_ON_DOCK, value);
}
@@ -111,6 +129,7 @@ public class DreamBackend {
}
public void setActivatedOnSleep(boolean value) {
logd("setActivatedOnSleep(%s)", value);
setBoolean(SCREENSAVER_ACTIVATE_ON_SLEEP, value);
}
@@ -122,23 +141,15 @@ public class DreamBackend {
Settings.Secure.putInt(mContext.getContentResolver(), key, value ? 1 : 0);
}
public void startDreamingNow() {
if (mDreamManager == null)
return;
try {
mDreamManager.dream();
} catch (RemoteException e) {
}
}
public void setActiveDream(ComponentName dream) {
logd("setActiveDream(%s)", dream);
if (mDreamManager == null)
return;
try {
ComponentName[] dreams = { dream };
mDreamManager.setDreamComponents(dream == null ? null : dreams);
} catch (RemoteException e) {
// noop
Log.w(TAG, "Failed to set active dream to " + dream, e);
}
}
@@ -149,39 +160,49 @@ public class DreamBackend {
ComponentName[] dreams = mDreamManager.getDreamComponents();
return dreams != null && dreams.length > 0 ? dreams[0] : null;
} catch (RemoteException e) {
Log.w(TAG, "Failed to get active dream", e);
return null;
}
}
public void launchSettings(DreamInfo dreamInfo) {
logd("launchSettings(%s)", dreamInfo);
if (dreamInfo == null || dreamInfo.settingsComponentName == null)
return;
mContext.startActivity(new Intent().setComponent(dreamInfo.settingsComponentName));
}
public void preview(DreamInfo dreamInfo) {
logd("preview(%s)", dreamInfo);
if (mDreamManager == null || dreamInfo == null || dreamInfo.componentName == null)
return;
try {
mDreamManager.testDream(dreamInfo.componentName);
} catch (RemoteException e) {
// noop
Log.w(TAG, "Failed to preview " + dreamInfo, e);
}
}
private static ComponentName getDreamComponentName(ResolveInfo ri) {
if (ri == null || ri.serviceInfo == null)
private static ComponentName getDreamComponentName(ResolveInfo resolveInfo) {
if (resolveInfo == null || resolveInfo.serviceInfo == null)
return null;
return new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name);
return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
}
private static ComponentName getSettingsComponentName(ResolveInfo ri) {
if (ri == null || ri.serviceInfo == null || ri.serviceInfo.metaData == null)
private static ComponentName getSettingsComponentName(ResolveInfo resolveInfo) {
if (resolveInfo == null
|| resolveInfo.serviceInfo == null
|| resolveInfo.serviceInfo.metaData == null)
return null;
String cn = ri.serviceInfo.metaData.getString(Dream.METADATA_NAME_CONFIG_ACTIVITY);
String cn = resolveInfo.serviceInfo.metaData.getString(Dream.METADATA_NAME_CONFIG_ACTIVITY);
return cn == null ? null : ComponentName.unflattenFromString(cn);
}
private static void logd(String msg, Object... args) {
if (DreamSettings.DEBUG)
Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
}
private static class DreamInfoComparator implements Comparator<DreamInfo> {
private final ComponentName mDefaultDream;

View File

@@ -20,11 +20,15 @@ import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -51,24 +55,35 @@ import com.android.settings.DreamBackend.DreamInfo;
import java.util.List;
public class DreamSettings extends SettingsPreferenceFragment {
private static final String TAG = DreamSettings.class.getSimpleName();
static final boolean DEBUG = false;
private static final int DIALOG_WHEN_TO_DREAM = 1;
private static final int DIVIDER_HEIGHT = 15;
private static final String PACKAGE_SCHEME = "package";
private final PackageReceiver mPackageReceiver = new PackageReceiver();
private Context mContext;
private DreamBackend mBackend;
private DreamInfoAdapter mAdapter;
private Switch mSwitch;
private MenuItem[] mDependentMenuItems;
private MenuItem mWhenToDream;
private boolean mRefreshing;
@Override
public int getHelpResource() {
return R.string.help_url_dreams;
}
@Override
public void onAttach(Activity activity) {
logd("onAttach(%s)", activity.getClass().getSimpleName());
super.onAttach(activity);
mContext = activity;
}
@Override
public void onCreate(Bundle icicle) {
logd("onCreate(%s)", icicle);
super.onCreate(icicle);
Activity activity = getActivity();
@@ -102,6 +117,7 @@ public class DreamSettings extends SettingsPreferenceFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
logd("onActivityCreated(%s)", savedInstanceState);
super.onActivityCreated(savedInstanceState);
ListView listView = getListView();
@@ -112,48 +128,24 @@ public class DreamSettings extends SettingsPreferenceFragment {
mAdapter = new DreamInfoAdapter(mContext);
listView.setAdapter(mAdapter);
listView.setDivider(null);
listView.setDividerHeight(DIVIDER_HEIGHT);
listView.setBackgroundColor(Color.BLACK);
listView.setPadding(0, DIVIDER_HEIGHT, 0, DIVIDER_HEIGHT);
listView.setHeaderDividersEnabled(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
logd("onCreateOptionsMenu()");
super.onCreateOptionsMenu(menu, inflater);
boolean isEnabled = mBackend.isEnabled();
MenuItem whenToDream = createMenuItem(menu,
mWhenToDream = createMenuItem(menu,
R.string.screensaver_settings_when_to_dream,
MenuItem.SHOW_AS_ACTION_NEVER,
MenuItem.SHOW_AS_ACTION_ALWAYS,
isEnabled,
new Runnable() {
@Override
public void run() {
showDialog(DIALOG_WHEN_TO_DREAM);
}});
createMenuItem(menu,
R.string.help_label,
MenuItem.SHOW_AS_ACTION_NEVER,
true,
new Runnable() {
@Override
public void run() {
// TODO show help url
}});
MenuItem startDreaming = createMenuItem(menu,
R.string.screensaver_settings_start_dreaming,
MenuItem.SHOW_AS_ACTION_ALWAYS,
isEnabled,
new Runnable(){
@Override
public void run() {
mBackend.startDreamingNow();
}});
mDependentMenuItems = new MenuItem[] { whenToDream, startDreaming };
}
private MenuItem createMenuItem(Menu menu,
@@ -173,6 +165,7 @@ public class DreamSettings extends SettingsPreferenceFragment {
@Override
public Dialog onCreateDialog(int dialogId) {
logd("onCreateDialog(%s)", dialogId);
if (dialogId == DIALOG_WHEN_TO_DREAM)
return createWhenToDreamDialog();
return super.onCreateDialog(dialogId);
@@ -201,10 +194,27 @@ public class DreamSettings extends SettingsPreferenceFragment {
.create();
}
@Override
public void onPause() {
logd("onPause()");
super.onPause();
mContext.unregisterReceiver(mPackageReceiver);
}
@Override
public void onResume() {
logd("onResume()");
super.onResume();
refreshFromBackend();
// listen for package changes
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addDataScheme(PACKAGE_SCHEME);
mContext.registerReceiver(mPackageReceiver , filter);
}
public static int getSummaryResource(Context context) {
@@ -221,6 +231,7 @@ public class DreamSettings extends SettingsPreferenceFragment {
}
private void refreshFromBackend() {
logd("refreshFromBackend()");
mRefreshing = true;
boolean dreamsEnabled = mBackend.isEnabled();
if (mSwitch.isChecked() != dreamsEnabled)
@@ -231,12 +242,17 @@ public class DreamSettings extends SettingsPreferenceFragment {
List<DreamInfo> dreamInfos = mBackend.getDreamInfos();
mAdapter.addAll(dreamInfos);
}
if (mDependentMenuItems != null)
for (MenuItem item : mDependentMenuItems)
item.setEnabled(dreamsEnabled);
if (mWhenToDream != null)
mWhenToDream.setEnabled(dreamsEnabled);
mRefreshing = false;
}
private static void logd(String msg, Object... args) {
if (DEBUG)
Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
}
private class DreamInfoAdapter extends ArrayAdapter<DreamInfo> {
private final LayoutInflater mInflater;
@@ -248,6 +264,7 @@ public class DreamSettings extends SettingsPreferenceFragment {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
DreamInfo dreamInfo = getItem(position);
logd("getView(%s)", dreamInfo.caption);
final View row = convertView != null ? convertView : createDreamInfoRow(parent);
row.setTag(dreamInfo);
@@ -258,8 +275,9 @@ public class DreamSettings extends SettingsPreferenceFragment {
((TextView) row.findViewById(android.R.id.text1)).setText(dreamInfo.caption);
// bind radio button
((RadioButton) row.findViewById(android.R.id.button1)).setChecked(dreamInfo.isActive);
((RadioButton) row.findViewById(android.R.id.button1)).setOnTouchListener(new OnTouchListener() {
RadioButton radioButton = (RadioButton) row.findViewById(android.R.id.button1);
radioButton.setChecked(dreamInfo.isActive);
radioButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
row.onTouchEvent(event);
@@ -267,11 +285,13 @@ public class DreamSettings extends SettingsPreferenceFragment {
}});
// bind button container
row.findViewById(android.R.id.widget_frame).setVisibility(dreamInfo.isActive ? View.VISIBLE : View.GONE);
View widgetFrame = row.findViewById(android.R.id.widget_frame);
widgetFrame.setVisibility(dreamInfo.isActive ? View.VISIBLE : View.GONE);
// bind settings button
((Button) row.findViewById(android.R.id.button2)).setEnabled(dreamInfo.settingsComponentName != null);
((Button) row.findViewById(android.R.id.button2)).setOnClickListener(new OnClickListener(){
Button settingsButton = (Button) row.findViewById(android.R.id.button2);
settingsButton.setVisibility(dreamInfo.settingsComponentName != null ? View.VISIBLE : View.GONE);
settingsButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
mBackend.launchSettings((DreamInfo)row.getTag());
@@ -298,7 +318,17 @@ public class DreamSettings extends SettingsPreferenceFragment {
return row;
}
private DreamInfo getCurrentSelection() {
for (int i = 0; i < getCount(); i++) {
DreamInfo dreamInfo = getItem(i);
if (dreamInfo.isActive)
return dreamInfo;
}
return null;
}
private void activate(DreamInfo dreamInfo) {
if (dreamInfo.equals(getCurrentSelection()))
return;
for (int i = 0; i < getCount(); i++) {
getItem(i).isActive = false;
}
@@ -307,4 +337,12 @@ public class DreamSettings extends SettingsPreferenceFragment {
notifyDataSetChanged();
}
}
private class PackageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
logd("PackageReceiver.onReceive");
refreshFromBackend();
}
}
}