Update look and feel of list preference screen am: f4dae1faf3
Change-Id: I5aaa49c020249f949a4902b2cdad4594d6135ee2
diff --git a/car-ui-lib/res/layout/car_ui_radio_button_item.xml b/car-ui-lib/res/layout/car_ui_radio_button_item.xml
deleted file mode 100644
index b7718d1..0000000
--- a/car-ui-lib/res/layout/car_ui_radio_button_item.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright 2019 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.
- -->
-<androidx.constraintlayout.widget.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:background="?android:attr/selectableItemBackground"
- android:layout_width="match_parent"
- android:layout_height="@dimen/car_ui_list_item_radio_button_height">
-
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/car_ui_radio_button_start_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- app:layout_constraintGuide_begin="@dimen/car_ui_list_item_radio_button_start_inset" />
-
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/car_ui_radio_button_end_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- app:layout_constraintGuide_end="@dimen/car_ui_list_item_radio_button_end_inset" />
-
- <FrameLayout
- android:id="@+id/radio_button_container"
- android:layout_width="@dimen/car_ui_list_item_radio_button_icon_container_width"
- android:layout_height="0dp"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="@+id/car_ui_radio_button_start_guideline"
- app:layout_constraintTop_toTopOf="parent">
-
- <RadioButton
- android:id="@+id/radio_button"
- android:clickable="false"
- android:focusable="false"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center" />
- </FrameLayout>
-
- <TextView
- android:id="@+id/text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
- android:textAppearance="@style/TextAppearance.CarUi.ListItem"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="@+id/car_ui_radio_button_end_guideline"
- app:layout_constraintStart_toEndOf="@+id/radio_button_container"
- app:layout_constraintTop_toTopOf="parent" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/car-ui-lib/res/values/styles.xml b/car-ui-lib/res/values/styles.xml
index 9b9419a..d22753f 100644
--- a/car-ui-lib/res/values/styles.xml
+++ b/car-ui-lib/res/values/styles.xml
@@ -137,13 +137,6 @@
<item name="android:scaleType">fitCenter</item>
</style>
- <style name="Preference.CarUi.ListPreference" parent="android:Theme.DeviceDefault.Dialog">
- <item name="android:windowNoTitle">true</item>
- <!-- Set this to true if you want Full Screen without status bar -->
- <item name="android:windowFullscreen">true</item>
- <item name="android:windowIsFloating">false</item>
- </style>
-
<!-- Preference Styles -->
<style name="Preference.CarUi">
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiRecyclerViewRadioButtonAdapter.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiRecyclerViewRadioButtonAdapter.java
deleted file mode 100644
index 41e1351..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiRecyclerViewRadioButtonAdapter.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2019 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.car.ui.preference;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RadioButton;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-
-import java.util.List;
-
-/**
- * The adapter for the recyclerview containing radio buttons as the items.
- */
-public class CarUiRecyclerViewRadioButtonAdapter extends
- RecyclerView.Adapter<CarUiRecyclerViewRadioButtonAdapter.ViewHolder> {
-
- /**
- * Callback that will be issued after any radio button is clicked.
- */
- public interface OnRadioButtonClickedListener {
- /**
- * Will be called when radio button is clicked.
- *
- * @param position of the radio button.
- */
- void onClick(int position);
- }
-
- private OnRadioButtonClickedListener mOnRadioButtonClickedListener;
-
- private final List<String> mList;
- private int mSelectedPosition = -1;
-
- public CarUiRecyclerViewRadioButtonAdapter(List<String> list, int position) {
- mList = list;
- mSelectedPosition = position;
- }
-
- @NonNull
- @Override
- public CarUiRecyclerViewRadioButtonAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- View view = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.car_ui_radio_button_item, parent, false);
- return new CarUiRecyclerViewRadioButtonAdapter.ViewHolder(view);
- }
-
- @Override
- public void onBindViewHolder(CarUiRecyclerViewRadioButtonAdapter.ViewHolder holder,
- int position) {
- String entry = mList.get(position);
- //since only one radio button is allowed to be selected,
- // this condition un-checks previous selections
- holder.mRadioButton.setChecked(mSelectedPosition == position);
- holder.mTextView.setText(entry);
- }
-
- @Override
- public int getItemCount() {
- return mList.size();
- }
-
- /** Registers a new {@link OnRadioButtonClickedListener} listener. */
- public void registerListener(OnRadioButtonClickedListener listener) {
- mOnRadioButtonClickedListener = listener;
- }
-
- /** Unregisters a {@link OnRadioButtonClickedListener} listener\. */
- public void unregisterOnBackListener(OnRadioButtonClickedListener listener) {
- mOnRadioButtonClickedListener = null;
- }
-
- /** The viewholder class for recyclerview containing radio buttons. */
- class ViewHolder extends RecyclerView.ViewHolder {
-
- RadioButton mRadioButton;
- TextView mTextView;
-
- ViewHolder(View view) {
- super(view);
- mRadioButton = view.findViewById(R.id.radio_button);
- mTextView = view.findViewById(R.id.text);
-
- view.setOnClickListener(v -> {
- mSelectedPosition = getAdapterPosition();
- notifyDataSetChanged();
- if (mOnRadioButtonClickedListener != null) {
- mOnRadioButtonClickedListener.onClick(mSelectedPosition);
- }
- });
- }
- }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java b/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java
index 7df7411..f8ff7c7 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java
@@ -31,6 +31,9 @@
import androidx.preference.Preference;
import com.android.car.ui.R;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
import com.android.car.ui.recyclerview.CarUiRecyclerView;
import com.android.car.ui.toolbar.Toolbar;
@@ -41,11 +44,10 @@
* A fragment that provides a layout with a list of options associated with a {@link
* ListPreference}.
*/
-public class ListPreferenceFragment extends Fragment implements
- CarUiRecyclerViewRadioButtonAdapter.OnRadioButtonClickedListener {
+public class ListPreferenceFragment extends Fragment {
private ListPreference mPreference;
- private int mClickedDialogEntryIndex;
+ private CarUiContentListItem mSelectedItem;
/**
* Returns a new instance of {@link ListPreferenceFragment} for the {@link ListPreference} with
@@ -70,21 +72,21 @@
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- final CarUiRecyclerView mCarUiRecyclerView = view.requireViewById(R.id.list);
+ final CarUiRecyclerView carUiRecyclerView = view.requireViewById(R.id.list);
final Toolbar toolbar = view.requireViewById(R.id.toolbar);
- mCarUiRecyclerView.setPadding(0, toolbar.getHeight(), 0, 0);
+ carUiRecyclerView.setPadding(0, toolbar.getHeight(), 0, 0);
toolbar.registerToolbarHeightChangeListener(newHeight -> {
- if (mCarUiRecyclerView.getPaddingTop() == newHeight) {
+ if (carUiRecyclerView.getPaddingTop() == newHeight) {
return;
}
- int oldHeight = mCarUiRecyclerView.getPaddingTop();
- mCarUiRecyclerView.setPadding(0, newHeight, 0, 0);
- mCarUiRecyclerView.scrollBy(0, oldHeight - newHeight);
+ int oldHeight = carUiRecyclerView.getPaddingTop();
+ carUiRecyclerView.setPadding(0, newHeight, 0, 0);
+ carUiRecyclerView.scrollBy(0, oldHeight - newHeight);
});
- mCarUiRecyclerView.setClipToPadding(false);
+ carUiRecyclerView.setClipToPadding(false);
mPreference = getListPreference();
toolbar.setTitle(mPreference.getTitle());
@@ -101,16 +103,42 @@
"ListPreference entries array length does not match entryValues array length.");
}
- mClickedDialogEntryIndex = mPreference.findIndexOfValue(mPreference.getValue());
- List<String> entryStrings = new ArrayList<>(entries.length);
- for (CharSequence entry : entries) {
- entryStrings.add(entry.toString());
+ int selectedEntryIndex = mPreference.findIndexOfValue(mPreference.getValue());
+ List<CarUiListItem> listItems = new ArrayList<>();
+ CarUiListItemAdapter adapter = new CarUiListItemAdapter(listItems);
+
+ for (int i = 0; i < entries.length; i++) {
+ String entry = entries[i].toString();
+ CarUiContentListItem item = new CarUiContentListItem();
+ item.setAction(CarUiContentListItem.Action.RADIO_BUTTON);
+ item.setTitle(entry);
+
+ if (i == selectedEntryIndex) {
+ item.setChecked(true);
+ mSelectedItem = item;
+ }
+
+ item.setOnCheckedChangedListener((listItem, isChecked) -> {
+ mSelectedItem.setChecked(false);
+ adapter.notifyItemChanged(listItems.indexOf(mSelectedItem));
+ mSelectedItem = listItem;
+ });
+
+ listItems.add(item);
}
- CarUiRecyclerViewRadioButtonAdapter adapter = new CarUiRecyclerViewRadioButtonAdapter(
- entryStrings, mClickedDialogEntryIndex);
- mCarUiRecyclerView.setAdapter(adapter);
- adapter.registerListener(this);
+ toolbar.registerOnBackListener(() -> {
+ int selectedIndex = listItems.indexOf(mSelectedItem);
+ String entryValue = entryValues[selectedIndex].toString();
+
+ if (mPreference.callChangeListener(entryValue)) {
+ mPreference.setValue(entryValue);
+ }
+
+ return false;
+ });
+
+ carUiRecyclerView.setAdapter(adapter);
}
private ListPreference getListPreference() {
@@ -143,27 +171,4 @@
return (ListPreference) preference;
}
-
- @Override
- public void onClick(int position) {
- CharSequence[] entryValues = mPreference.getEntryValues();
-
- if (position < 0 || position > entryValues.length - 1) {
- throw new IllegalStateException(
- "Clicked preference has invalid index.");
- }
-
- mClickedDialogEntryIndex = position;
- String value = entryValues[mClickedDialogEntryIndex].toString();
- if (mPreference.callChangeListener(value)) {
- mPreference.setValue(value);
- }
-
- if (getActivity() == null) {
- throw new IllegalStateException(
- "ListPreference fragment is not attached to an Activity.");
- }
-
- getActivity().getSupportFragmentManager().popBackStack();
- }
}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java b/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
index 17362f5..e505708 100644
--- a/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
+++ b/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
@@ -118,7 +118,7 @@
item.setAction(CarUiContentListItem.Action.CHECK_BOX);
item.setTitle(entry);
item.setChecked(selectedItems[i]);
- item.setOnCheckedChangedListener(isChecked -> {
+ item.setOnCheckedChangedListener((listItem, isChecked) -> {
if (isChecked) {
mNewValues.add(entryValue);
} else {
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java
index fd5bf50..724b639 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java
@@ -34,9 +34,10 @@
/**
* Called when the checked state of a list item has changed.
*
+ * @param item The item whose checked state changed.
* @param isChecked new checked state of list item.
*/
- void onCheckedChanged(boolean isChecked);
+ void onCheckedChanged(CarUiContentListItem item, boolean isChecked);
}
/**
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
index b39bbd9..1b71411 100644
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
+++ b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
@@ -223,6 +223,7 @@
break;
case SWITCH:
mSwitch.setVisibility(View.VISIBLE);
+ mSwitch.setOnCheckedChangeListener(null);
mSwitch.setChecked(item.isChecked());
mSwitch.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
@@ -230,7 +231,7 @@
CarUiContentListItem.OnCheckedChangedListener itemListener =
item.getOnCheckedChangedListener();
if (itemListener != null) {
- itemListener.onCheckedChanged(isChecked);
+ itemListener.onCheckedChanged(item, isChecked);
}
});
@@ -245,6 +246,7 @@
break;
case CHECK_BOX:
mCheckBox.setVisibility(View.VISIBLE);
+ mCheckBox.setOnCheckedChangeListener(null);
mCheckBox.setChecked(item.isChecked());
mCheckBox.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
@@ -252,7 +254,7 @@
CarUiContentListItem.OnCheckedChangedListener itemListener =
item.getOnCheckedChangedListener();
if (itemListener != null) {
- itemListener.onCheckedChanged(isChecked);
+ itemListener.onCheckedChanged(item, isChecked);
}
});
@@ -267,6 +269,7 @@
break;
case RADIO_BUTTON:
mRadioButton.setVisibility(View.VISIBLE);
+ mRadioButton.setOnCheckedChangeListener(null);
mRadioButton.setChecked(item.isChecked());
mRadioButton.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
@@ -274,7 +277,7 @@
CarUiContentListItem.OnCheckedChangedListener itemListener =
item.getOnCheckedChangedListener();
if (itemListener != null) {
- itemListener.onCheckedChanged(isChecked);
+ itemListener.onCheckedChanged(item, isChecked);
}
});
diff --git a/car-ui-lib/tests/apitest/current.xml b/car-ui-lib/tests/apitest/current.xml
index c428165..5f21189 100644
--- a/car-ui-lib/tests/apitest/current.xml
+++ b/car-ui-lib/tests/apitest/current.xml
@@ -208,7 +208,6 @@
<public type="style" name="Preference.CarUi.DropDown"/>
<public type="style" name="Preference.CarUi.Icon"/>
<public type="style" name="Preference.CarUi.Information"/>
- <public type="style" name="Preference.CarUi.ListPreference"/>
<public type="style" name="Preference.CarUi.Preference"/>
<public type="style" name="Preference.CarUi.PreferenceScreen"/>
<public type="style" name="Preference.CarUi.SeekBarPreference"/>
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
index c307cb3..a5aeeee 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
@@ -88,7 +88,7 @@
item.setTitle("Title -- Item with checkbox");
item.setBody("Will present toast on change of selection state.");
item.setOnCheckedChangedListener(
- (isChecked) -> Toast.makeText(context,
+ (listItem, isChecked) -> Toast.makeText(context,
"Item checked state is: " + isChecked, Toast.LENGTH_SHORT).show());
item.setAction(CarUiContentListItem.Action.CHECK_BOX);
mData.add(item);
@@ -114,7 +114,7 @@
radioItem1.setBody("Item is initially unchecked checked");
radioItem1.setAction(CarUiContentListItem.Action.RADIO_BUTTON);
radioItem1.setChecked(false);
- radioItem1.setOnCheckedChangedListener(isChecked -> {
+ radioItem1.setOnCheckedChangedListener((listItem, isChecked) -> {
if (isChecked) {
radioItem2.setChecked(false);
mAdapter.notifyItemChanged(mData.indexOf(radioItem2));
@@ -126,7 +126,7 @@
radioItem2.setTitle("Item is mutually exclusive with item above");
radioItem2.setAction(CarUiContentListItem.Action.RADIO_BUTTON);
radioItem2.setChecked(true);
- radioItem2.setOnCheckedChangedListener(isChecked -> {
+ radioItem2.setOnCheckedChangedListener((listItem, isChecked) -> {
if (isChecked) {
radioItem1.setChecked(false);
mAdapter.notifyItemChanged(mData.indexOf(radioItem1));
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
index 8c10ede..dec4c19 100644
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
@@ -241,7 +241,7 @@
switchWidget.performClick();
assertThat(switchWidget.isChecked()).isEqualTo(false);
verify(mOnCheckedChangedListener, times(1))
- .onCheckedChanged(false);
+ .onCheckedChanged(item, false);
}
@Test
@@ -262,7 +262,7 @@
checkBox.performClick();
assertThat(checkBox.isChecked()).isEqualTo(true);
verify(mOnCheckedChangedListener, times(1))
- .onCheckedChanged(true);
+ .onCheckedChanged(item, true);
}
@Test