Build a new FooterPreference UI.

- Create a new layout for footer prefs.
- Create a new FooterPreference type to use the layout
- Create a Mixin to create and add the pref to screen
- Create a new lifecycle observer type to invoke mixin at right time
- Switch SettingsPreferenceFragment to use footer mixin.
- Switch FingerprintSettings to use the new footer pref.

Bug: 33579394
Test: RunSettingsRoboTests
Change-Id: I548ac39a0d120196a7ffed09b4f98bd9a80bae90
This commit is contained in:
Fan Zhang
2016-12-13 12:42:50 -08:00
parent 1b89a9a4e1
commit d5b48454a3
16 changed files with 454 additions and 94 deletions

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 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="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/textColorSecondary">
<path
android:fillColor="#000000"
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
</vector>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2015 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
-->
<com.android.settings.widget.LinkTextView
xmlns:android="http://schemas.android.com/apk/res/android"
style="@android:style/TextAppearance.Material.Body1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorSecondary"
android:paddingTop="32dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:selectable="false" />

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/selectableItemBackground"
android:clipToPadding="false">
<LinearLayout
android:id="@+id/icon_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="60dp"
android:gravity="start|center_vertical"
android:orientation="horizontal"
android:paddingEnd="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<com.android.internal.widget.PreferenceImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<com.android.settings.widget.LinkTextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:paddingTop="16dp"
android:maxLines="10"
android:textColor="?android:attr/textColorSecondary"
android:ellipsize="marquee"/>
</LinearLayout>

View File

@@ -48,6 +48,7 @@ import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.instrumentation.Instrumentable; import com.android.settings.core.instrumentation.Instrumentable;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.widget.FooterPreferenceMixin;
import com.android.settingslib.HelpUtils; import com.android.settingslib.HelpUtils;
import java.util.UUID; import java.util.UUID;
@@ -70,6 +71,9 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted"; private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";
protected final FooterPreferenceMixin mFooterPreferenceMixin =
new FooterPreferenceMixin(this, getLifecycle());
private SettingsDialogFragment mDialogFragment; private SettingsDialogFragment mDialogFragment;
private String mHelpUri; private String mHelpUri;
@@ -123,7 +127,6 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
private LayoutPreference mHeader; private LayoutPreference mHeader;
private LayoutPreference mFooter;
private View mEmptyView; private View mEmptyView;
private LinearLayoutManager mLayoutManager; private LinearLayoutManager mLayoutManager;
private HighlightablePreferenceGroupAdapter mAdapter; private HighlightablePreferenceGroupAdapter mAdapter;
@@ -277,10 +280,6 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
return mHeader; return mHeader;
} }
public LayoutPreference getFooterView() {
return mFooter;
}
protected void setHeaderView(int resource) { protected void setHeaderView(int resource) {
mHeader = new LayoutPreference(getPrefContext(), resource); mHeader = new LayoutPreference(getPrefContext(), resource);
addPreferenceToTop(mHeader); addPreferenceToTop(mHeader);
@@ -298,29 +297,6 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
} }
} }
protected void setFooterView(int resource) {
setFooterView(resource != 0 ? new LayoutPreference(getPrefContext(), resource) : null);
}
protected void setFooterView(View v) {
setFooterView(v != null ? new LayoutPreference(getPrefContext(), v) : null);
}
private void setFooterView(LayoutPreference footer) {
if (getPreferenceScreen() != null && mFooter != null) {
getPreferenceScreen().removePreference(mFooter);
}
if (footer != null) {
mFooter = footer;
mFooter.setOrder(ORDER_LAST);
if (getPreferenceScreen() != null) {
getPreferenceScreen().addPreference(mFooter);
}
} else {
mFooter = null;
}
}
@Override @Override
public void setPreferenceScreen(PreferenceScreen preferenceScreen) { public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
if (preferenceScreen != null && !preferenceScreen.isAttached()) { if (preferenceScreen != null && !preferenceScreen.isAttached()) {
@@ -332,9 +308,6 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
if (mHeader != null) { if (mHeader != null) {
preferenceScreen.addPreference(mHeader); preferenceScreen.addPreference(mHeader);
} }
if (mFooter != null) {
preferenceScreen.addPreference(mFooter);
}
} }
} }
@@ -343,7 +316,7 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
if (getPreferenceScreen() != null) { if (getPreferenceScreen() != null) {
boolean show = (getPreferenceScreen().getPreferenceCount() boolean show = (getPreferenceScreen().getPreferenceCount()
- (mHeader != null ? 1 : 0) - (mHeader != null ? 1 : 0)
- (mFooter != null ? 1 : 0)) <= 0; - (mFooterPreferenceMixin.hasFooter() ? 1 : 0)) <= 0;
mEmptyView.setVisibility(show ? View.VISIBLE : View.GONE); mEmptyView.setVisibility(show ? View.VISIBLE : View.GONE);
} else { } else {
mEmptyView.setVisibility(View.VISIBLE); mEmptyView.setVisibility(View.VISIBLE);

View File

@@ -35,7 +35,7 @@ public interface ApplicationFeatureProvider {
/** /**
* Callback that receives the total number of packages installed on the device. * Callback that receives the total number of packages installed on the device.
*/ */
public interface NumberOfInstalledAppsCallback { interface NumberOfInstalledAppsCallback {
void onNumberOfInstalledAppsResult(int num); void onNumberOfInstalledAppsResult(int num);
} }
} }

View File

@@ -50,6 +50,7 @@ import com.android.settings.location.ScanningSettings;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable; import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw; import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.widget.FooterPreference;
import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBar;
import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothDeviceFilter; import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
@@ -97,7 +98,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
// accessed from inner class (not private to avoid thunks) // accessed from inner class (not private to avoid thunks)
Preference mMyDevicePreference; FooterPreference mMyDevicePreference;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override @Override
@@ -120,7 +121,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
final Resources res = context.getResources(); final Resources res = context.getResources();
final Locale locale = res.getConfiguration().getLocales().get(0); final Locale locale = res.getConfiguration().getLocales().get(0);
final BidiFormatter bidiFormatter = BidiFormatter.getInstance(locale); final BidiFormatter bidiFormatter = BidiFormatter.getInstance(locale);
mMyDevicePreference.setSummary(res.getString( mMyDevicePreference.setTitle(res.getString(
R.string.bluetooth_is_visible_message, R.string.bluetooth_is_visible_message,
bidiFormatter.unicodeWrap(mLocalAdapter.getName()))); bidiFormatter.unicodeWrap(mLocalAdapter.getName())));
} }
@@ -171,10 +172,8 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
mAvailableDevicesCategory.setOrder(2); mAvailableDevicesCategory.setOrder(2);
getPreferenceScreen().addPreference(mAvailableDevicesCategory); getPreferenceScreen().addPreference(mAvailableDevicesCategory);
mMyDevicePreference = new Preference(getPrefContext()); mMyDevicePreference = mFooterPreferenceMixin.createFooterPreference();
mMyDevicePreference.setSelectable(false); mMyDevicePreference.setSelectable(false);
mMyDevicePreference.setOrder(3);
getPreferenceScreen().addPreference(mMyDevicePreference);
setHasOptionsMenu(true); setHasOptionsMenu(true);
} }
@@ -356,7 +355,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
final Resources res = getResources(); final Resources res = getResources();
final Locale locale = res.getConfiguration().getLocales().get(0); final Locale locale = res.getConfiguration().getLocales().get(0);
final BidiFormatter bidiFormatter = BidiFormatter.getInstance(locale); final BidiFormatter bidiFormatter = BidiFormatter.getInstance(locale);
mMyDevicePreference.setSummary(res.getString( mMyDevicePreference.setTitle(res.getString(
R.string.bluetooth_is_visible_message, R.string.bluetooth_is_visible_message,
bidiFormatter.unicodeWrap(mLocalAdapter.getName()))); bidiFormatter.unicodeWrap(mLocalAdapter.getName())));

View File

@@ -18,6 +18,7 @@ package com.android.settings.core.lifecycle;
import android.annotation.UiThread; import android.annotation.UiThread;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.core.lifecycle.events.OnAttach; import com.android.settings.core.lifecycle.events.OnAttach;
import com.android.settings.core.lifecycle.events.OnCreate; import com.android.settings.core.lifecycle.events.OnCreate;
@@ -27,6 +28,7 @@ import com.android.settings.core.lifecycle.events.OnResume;
import com.android.settings.core.lifecycle.events.OnSaveInstanceState; import com.android.settings.core.lifecycle.events.OnSaveInstanceState;
import com.android.settings.core.lifecycle.events.OnStart; import com.android.settings.core.lifecycle.events.OnStart;
import com.android.settings.core.lifecycle.events.OnStop; import com.android.settings.core.lifecycle.events.OnStop;
import com.android.settings.core.lifecycle.events.SetPreferenceScreen;
import com.android.settings.utils.ThreadUtils; import com.android.settings.utils.ThreadUtils;
import java.util.ArrayList; import java.util.ArrayList;
@@ -73,6 +75,14 @@ public class Lifecycle {
} }
} }
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
for (LifecycleObserver observer : mObservers) {
if (observer instanceof SetPreferenceScreen) {
((SetPreferenceScreen) observer).setPreferenceScreen(preferenceScreen);
}
}
}
public void onResume() { public void onResume() {
for (LifecycleObserver observer : mObservers) { for (LifecycleObserver observer : mObservers) {
if (observer instanceof OnResume) { if (observer instanceof OnResume) {

View File

@@ -20,6 +20,7 @@ import android.annotation.CallSuper;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v14.preference.PreferenceFragment; import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.PreferenceScreen;
/** /**
* {@link PreferenceFragment} that has hooks to observe fragment lifecycle events. * {@link PreferenceFragment} that has hooks to observe fragment lifecycle events.
@@ -46,6 +47,12 @@ public abstract class ObservablePreferenceFragment extends PreferenceFragment {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@Override
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
mLifecycle.setPreferenceScreen(preferenceScreen);
super.setPreferenceScreen(preferenceScreen);
}
@CallSuper @CallSuper
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2016 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.settings.core.lifecycle.events;
import android.support.v7.preference.PreferenceScreen;
public interface SetPreferenceScreen {
void setPreferenceScreen(PreferenceScreen preferenceScreen);
}

View File

@@ -17,7 +17,6 @@
package com.android.settings.fingerprint; package com.android.settings.fingerprint;
import android.annotation.Nullable;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
@@ -26,7 +25,6 @@ import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.Fingerprint;
@@ -49,15 +47,12 @@ import android.text.Annotation;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan; import android.text.style.URLSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -68,6 +63,8 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.SubSettings; import com.android.settings.SubSettings;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.widget.FooterPreference;
import com.android.settings.widget.FooterPreferenceMixin;
import com.android.settingslib.HelpUtils; import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
@@ -298,21 +295,14 @@ public class FingerprintSettings extends SubSettings {
mLaunchedConfirm = true; mLaunchedConfirm = true;
launchChooseOrConfirmLock(); launchChooseOrConfirmLock();
} }
}
@Override final FooterPreference pref = mFooterPreferenceMixin.createFooterPreference();
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { final EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
super.onViewCreated(view, savedInstanceState); activity, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId);
TextView v = (TextView) LayoutInflater.from(view.getContext()).inflate( pref.setTitle(LearnMoreSpan.linkify(getText(admin != null
R.layout.fingerprint_settings_footer, null);
EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
getActivity(), DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId);
v.setText(LearnMoreSpan.linkify(getText(admin != null
? R.string.security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled ? R.string.security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled
: R.string.security_settings_fingerprint_enroll_disclaimer), : R.string.security_settings_fingerprint_enroll_disclaimer),
getString(getHelpResource()), admin)); getString(getHelpResource()), admin));
v.setMovementMethod(new LinkMovementMethod());
setFooterView(v);
} }
protected void removeFingerprintPreference(int fingerprintId) { protected void removeFingerprintPreference(int fingerprintId) {

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 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.settings.widget;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.method.LinkMovementMethod;
import android.util.AttributeSet;
import android.widget.TextView;
import com.android.settings.R;
/**
* A custom preference acting as "footer" of a page. It has a field for icon and text. It is added
* to screen as the last preference.
*/
public class FooterPreference extends Preference {
static final int ORDER_FOOTER = Integer.MAX_VALUE - 1;
static final String KEY_FOOTER = "footer_preference";
public FooterPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public FooterPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public FooterPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FooterPreference(Context context) {
super(context);
init();
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
TextView title = (TextView) holder.itemView.findViewById(android.R.id.title);
title.setMovementMethod(new LinkMovementMethod());
}
private void init() {
setLayoutResource(R.layout.preference_footer);
setIcon(R.drawable.ic_info_outline_24dp);
setKey(KEY_FOOTER);
setOrder(ORDER_FOOTER);
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 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.settings.widget;
import android.content.Context;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.SetPreferenceScreen;
public class FooterPreferenceMixin implements LifecycleObserver, SetPreferenceScreen {
private final PreferenceFragment mFragment;
private FooterPreference mFooterPreference;
public FooterPreferenceMixin(PreferenceFragment fragment, Lifecycle lifecycle) {
mFragment = fragment;
lifecycle.addObserver(this);
}
@Override
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
if (mFooterPreference != null) {
preferenceScreen.addPreference(mFooterPreference);
}
}
/**
* Creates a new {@link FooterPreference}.
*/
public FooterPreference createFooterPreference() {
final PreferenceScreen screen = mFragment.getPreferenceScreen();
if (mFooterPreference != null && screen != null) {
screen.removePreference(mFooterPreference);
}
mFooterPreference = new FooterPreference(getPrefContext());
if (screen != null) {
screen.addPreference(mFooterPreference);
}
return mFooterPreference;
}
/**
* Returns an UI context with theme properly set for new Preference objects.
*/
private Context getPrefContext() {
return mFragment.getPreferenceManager().getContext();
}
public boolean hasFooter() {
return mFooterPreference != null;
}
}

View File

@@ -100,24 +100,18 @@ public class SearchResultBuilderTest {
} }
@Test @Test
public void testNoRank_BuildSearchResultException() { public void testNoRank_BuildSearchResult_pass() {
mBuilder.addTitle(mTitle) mBuilder.addTitle(mTitle)
.addSummary(mSummary) .addSummary(mSummary)
.addBreadcrumbs(mBreadcrumbs) .addBreadcrumbs(mBreadcrumbs)
.addIcon(mIcon) .addIcon(mIcon)
.addPayload(mResultPayload); .addPayload(mResultPayload);
SearchResult result = null; assertThat(mBuilder.build()).isNotNull();
try {
result = mBuilder.build();
} catch (IllegalArgumentException e) {
// passes.
}
assertThat(result).isNull();
} }
@Test @Test
public void testNoIcon_BuildSearchResultException() { public void testNoIcon_BuildSearchResult_pass() {
mBuilder.addTitle(mTitle) mBuilder.addTitle(mTitle)
.addSummary(mSummary) .addSummary(mSummary)
.addRank(mRank) .addRank(mRank)

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2016 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.settings.widget;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class FooterPreferenceMixinTest {
@Mock
private PreferenceFragment mFragment;
@Mock
private PreferenceScreen mScreen;
private Lifecycle mLifecycle;
private FooterPreferenceMixin mMixin;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycle = new Lifecycle();
when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
when(mFragment.getPreferenceManager().getContext())
.thenReturn(ShadowApplication.getInstance().getApplicationContext());
mMixin = new FooterPreferenceMixin(mFragment, mLifecycle);
}
@Test
public void createFooter_screenNotAvailable_noCrash() {
assertThat(mMixin.createFooterPreference()).isNotNull();
}
@Test
public void createFooter_screenAvailable_canAttachToScreen() {
when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
final FooterPreference preference = mMixin.createFooterPreference();
assertThat(preference).isNotNull();
verify(mScreen).addPreference(preference);
}
@Test
public void createFooter_screenAvailableDelayed_canAttachToScreen() {
final FooterPreference preference = mMixin.createFooterPreference();
mLifecycle.setPreferenceScreen(mScreen);
assertThat(preference).isNotNull();
verify(mScreen).addPreference(preference);
}
@Test
public void createFooterTwice_screenAvailable_replaceOldFooter() {
when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
mMixin.createFooterPreference();
mMixin.createFooterPreference();
verify(mScreen).removePreference(any(FooterPreference.class));
verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2016 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.settings.widget;
import android.content.Context;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import static com.google.common.truth.Truth.assertThat;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class FooterPreferenceTest {
private Context mContext;
@Before
public void setUp() {
mContext = ShadowApplication.getInstance().getApplicationContext();
}
@Test
public void createNewPreference_shouldSetKeyAndOrder() {
final FooterPreference preference = new FooterPreference(mContext);
assertThat(preference.getKey()).isEqualTo(FooterPreference.KEY_FOOTER);
assertThat(preference.getOrder()).isEqualTo(FooterPreference.ORDER_FOOTER);
}
@Test
public void bindPreference_shouldLinkifyContent() {
final FooterPreference preference = new FooterPreference(mContext);
final PreferenceViewHolder holder = new PreferenceViewHolder(
LayoutInflater.from(mContext).inflate(R.layout.preference_footer, null));
preference.onBindViewHolder(holder);
assertThat(((TextView) holder.findViewById(android.R.id.title)).getMovementMethod())
.isInstanceOf(LinkMovementMethod.class);
}
}

View File

@@ -16,21 +16,21 @@
package com.android.settings.widget; package com.android.settings.widget;
import static junit.framework.Assert.assertEquals;
import android.content.Context; import android.content.Context;
import android.view.View.MeasureSpec; import android.view.View.MeasureSpec;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig; import com.android.settings.TestConfig;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class) import static junit.framework.Assert.assertEquals;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class RingProgressBarTest { public class RingProgressBarTest {