Add new expandable preference component

Bug: 177406865
Bug: 185187729
Test: make SettingsRoboTests
Test: make SettingsGoogleRoboTests
Change-Id: Id2b2a1f4fa557467efcaa013aa9e978b2c66d974
This commit is contained in:
ykhung
2021-04-21 15:53:51 +08:00
committed by YUKAI HUNG
parent ee2086872e
commit b8721cf980
5 changed files with 308 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2021 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"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M18.59,16.41L20,15l-8,-8 -8,8 1.41,1.41L12,9.83"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2021 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"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M5.41,7.59L4,9l8,8 8,-8 -1.41,-1.41L12,14.17"/>
</vector>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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/listPreferredItemHeightSmall"
android:gravity="center_vertical"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:clipToPadding="false"
android:baselineAligned="false">
<TextView
android:id="@+id/expand_title"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingEnd="4dp"
android:singleLine="true"
android:textAlignment="viewStart"
android:text="@string/battery_system_usage_for_past_24"
style="@style/PreferenceCategoryTitleTextStyle"/>
<ImageView
android:id="@+id/expand_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_settings_expand_more"/>
</LinearLayout>

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2021 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.fuelgauge;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
/** A preference for expandable section divider. */
public class ExpandDividerPreference extends Preference {
private static final String TAG = "ExpandDividerPreference";
@VisibleForTesting
static final String PREFERENCE_KEY = "expandable_divider";
@VisibleForTesting TextView mTextView;
@VisibleForTesting ImageView mImageView;
private OnExpandListener mOnExpandListener;
private boolean mIsExpanded = false;
/** A callback listener for expand state is changed by users. */
public interface OnExpandListener {
void onExpand(boolean isExpanded);
}
public ExpandDividerPreference(Context context) {
this(context, /*attrs=*/ null);
}
public ExpandDividerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.preference_expand_divider);
setKey(PREFERENCE_KEY);
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
mTextView = (TextView) view.findViewById(R.id.expand_title);
mImageView = (ImageView) view.findViewById(R.id.expand_icon);
refreshState();
}
@Override
public void onClick() {
mIsExpanded = !mIsExpanded;
refreshState();
if (mOnExpandListener != null) {
mOnExpandListener.onExpand(mIsExpanded);
}
}
void setTitle(String titleContent) {
if (mTextView != null) {
mTextView.setText(titleContent);
}
}
void setIsExpanded(boolean isExpanded) {
mIsExpanded = isExpanded;
refreshState();
}
void setOnExpandListener(OnExpandListener listener) {
mOnExpandListener = listener;
}
private void refreshState() {
final int iconId =
mIsExpanded
? R.drawable.ic_settings_expand_less
: R.drawable.ic_settings_expand_more;
if (mImageView != null) {
mImageView.setImageResource(iconId);
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2021 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.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.settings.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public final class ExpandDividerPreferenceTest {
private Context mContext;
private ExpandDividerPreference mExpandDividerPreference;
@Mock private ImageView mImageView;
@Mock private TextView mTextView;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mExpandDividerPreference = new ExpandDividerPreference(mContext);
doReturn(R.id.expand_title).when(mTextView).getId();
doReturn(R.id.expand_icon).when(mImageView).getId();
}
@Test
public void testConstructor_returnExpectedResult() {
assertThat(mExpandDividerPreference.getKey())
.isEqualTo(ExpandDividerPreference.PREFERENCE_KEY);
assertThat(mExpandDividerPreference.getLayoutResource())
.isEqualTo(R.layout.preference_expand_divider);
}
@Test
public void testSetTitle_setTitleContentIntoTextView() {
final String titleContent = "title content";
mExpandDividerPreference.mTextView = mTextView;
mExpandDividerPreference.setTitle(titleContent);
verify(mTextView).setText(titleContent);
}
@Test
public void testOnClick_switchExpandStateAndInvokeCallback() {
final boolean[] isExpandedArray = new boolean[] {false};
mExpandDividerPreference.mImageView = mImageView;
mExpandDividerPreference.setOnExpandListener(
isExpanded -> isExpandedArray[0] = isExpanded);
// Click the item first time from false -> true.
mExpandDividerPreference.onClick();
// Verifies the first time click result.
verify(mImageView).setImageResource(R.drawable.ic_settings_expand_less);
assertThat(isExpandedArray[0]).isTrue();
// Clicks the item second time from true -> false.
mExpandDividerPreference.onClick();
// Verifies the second time click result.
verify(mImageView).setImageResource(R.drawable.ic_settings_expand_more);
assertThat(isExpandedArray[0]).isFalse();
}
@Test
public void testSetIsExpanded_updateStateButNotInvokeCallback() {
final boolean[] isExpandedArray = new boolean[] {false};
mExpandDividerPreference.mImageView = mImageView;
mExpandDividerPreference.setOnExpandListener(
isExpanded -> isExpandedArray[0] = isExpanded);
mExpandDividerPreference.setIsExpanded(true);
verify(mImageView).setImageResource(R.drawable.ic_settings_expand_less);
assertThat(isExpandedArray[0]).isFalse();
}
}