Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8721cf9 authored by ykhung's avatar ykhung Committed by YUKAI HUNG
Browse files

Add new expandable preference component

Bug: 177406865
Bug: 185187729
Test: make SettingsRoboTests
Test: make SettingsGoogleRoboTests
Change-Id: Id2b2a1f4fa557467efcaa013aa9e978b2c66d974
parent ee208687
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
<!--
    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>
+25 −0
Original line number Diff line number Diff line
<!--
    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>
+50 −0
Original line number Diff line number Diff line
<?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>
+98 −0
Original line number Diff line number Diff line
/*
 * 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);
        }
    }
}
+110 −0
Original line number Diff line number Diff line
/*
 * 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();
    }
}