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

Commit 4addb592 authored by Fan Zhang's avatar Fan Zhang
Browse files

Remove divider lines from all PreferenceFragments.

(this is partially revert of ag/I0ce486f7ac6)

- Only draw divider lines on top of PreferenceCategory and
  FooterPreference

Bug: 33601143
Test: make RunSettingsRoboTests
Change-Id: I26146dcae1603dc807e54ea431910685107be94c
parent d5b48454
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -17,13 +17,20 @@
package com.android.settings.core;

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.android.settings.core.instrumentation.Instrumentable;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
import com.android.settings.core.lifecycle.ObservablePreferenceFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.PreferenceDividerDecoration;

/**
 * Instrumented fragment that logs visibility state.
@@ -48,6 +55,9 @@ public abstract class InstrumentedPreferenceFragment extends ObservablePreferenc
    protected final int GESTURE_DOUBLE_TAP_SCREEN = PLACEHOLDER_METRIC + 11;
    protected final int GESTURE_DOUBLE_TWIST = PLACEHOLDER_METRIC + 12;

    private final PreferenceDividerDecoration mDividerDecoration =
            new PreferenceDividerDecoration();

    public InstrumentedPreferenceFragment() {
        // Mixin that logs visibility change for activity.
        getLifecycle().addObserver(new VisibilityLoggerMixin(getMetricsCategory()));
@@ -59,7 +69,21 @@ public abstract class InstrumentedPreferenceFragment extends ObservablePreferenc
        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final View view = super.onCreateView(inflater, container, savedInstanceState);
        getListView().addItemDecoration(mDividerDecoration);
        return view;
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    }

    @Override
    public void setDivider(Drawable divider) {
        mDividerDecoration.setDivider(divider);
        super.setDivider(new ColorDrawable(Color.TRANSPARENT));
    }
}
+0 −13
Original line number Diff line number Diff line
@@ -17,9 +17,6 @@ package com.android.settings.dashboard;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
@@ -117,16 +114,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
        refreshAllPreferences(getLogTag());
    }

    @Override
    public void setDivider(Drawable divider) {
        if (mDashboardFeatureProvider.isEnabled()) {
            // Intercept divider and set it transparent so system divider decoration is disabled.
            super.setDivider(new ColorDrawable(Color.TRANSPARENT));
        } else {
            super.setDivider(divider);
        }
    }

    @Override
    public void onStart() {
        super.onStart();
+79 −0
Original line number Diff line number Diff line
/*
 * 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.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewCompat;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceGroupAdapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration {

    private Drawable mDivider;
    private int mDividerHeight;

    public void setDivider(Drawable divider) {
        if (divider != null) {
            mDividerHeight = divider.getIntrinsicHeight();
        } else {
            mDividerHeight = 0;
        }
        mDivider = divider;
    }

    public void setDividerHeight(int dividerHeight) {
        mDividerHeight = dividerHeight;
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mDivider == null) {
            return;
        }
        final int childCount = parent.getChildCount();
        final int width = parent.getWidth();
        for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) {
            final View view = parent.getChildAt(childViewIndex);
            if (shouldDrawDividerAbove(view, parent)) {
                int top = (int) ViewCompat.getY(view);
                mDivider.setBounds(0, top, width, top + mDividerHeight);
                mDivider.draw(c);
            }
        }
    }

    private boolean shouldDrawDividerAbove(View view, RecyclerView parent) {
        final RecyclerView.Adapter adapter = parent.getAdapter();
        if (adapter == null || !(adapter instanceof PreferenceGroupAdapter)) {
            return false;
        }
        final PreferenceGroupAdapter prefAdapter = (PreferenceGroupAdapter) adapter;
        final int adapterPosition = parent.getChildAdapterPosition(view);
        if (adapterPosition == RecyclerView.NO_POSITION) {
            return false;
        }
        final Preference pref = prefAdapter.getItem(adapterPosition);
        if (pref instanceof PreferenceCategory) {
            return adapterPosition != 0;
        }
        return pref instanceof FooterPreference;
    }
}
+113 −0
Original line number Diff line number Diff line
/*
 * 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.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceGroupAdapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;

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.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.never;
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 PreferenceDividerDecorationTest {

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private Context mContext;
    @Mock
    private Drawable mDrawable;
    @Mock
    private Canvas mCanvas;
    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private RecyclerView mRecyclerView;
    @Mock
    private PreferenceGroupAdapter mAdapter;
    @Mock
    private PreferenceCategory mPrefCategory;
    @Mock
    private Preference mNormalPref;
    @Mock
    private FooterPreference mFooterPref;
    private PreferenceDividerDecoration mDecoration;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mDecoration = new PreferenceDividerDecoration();
        mDecoration.setDivider(mDrawable);
        mDecoration.setDividerHeight(3);
    }

    @Test
    public void drawOver_footerPreference_shouldDrawDivider() {
        when(mRecyclerView.getAdapter()).thenReturn(mAdapter);
        when(mRecyclerView.getChildCount()).thenReturn(1);
        when(mAdapter.getItem(anyInt())).thenReturn(mFooterPref);

        mDecoration.onDrawOver(mCanvas, mRecyclerView, null /* state */);

        verify(mDrawable).draw(mCanvas);
    }

    @Test
    public void drawOver_preferenceCategory_shouldSkipFirst() {
        when(mRecyclerView.getAdapter()).thenReturn(mAdapter);
        when(mRecyclerView.getChildCount()).thenReturn(3);
        when(mAdapter.getItem(anyInt())).thenReturn(mPrefCategory);
        when(mRecyclerView.getChildAdapterPosition(any(View.class)))
                .thenReturn(0)
                .thenReturn(1)
                .thenReturn(2);

        mDecoration.onDrawOver(mCanvas, mRecyclerView, null /* state */);

        // 3 prefCategory, should skip first draw
        verify(mDrawable, times(2)).draw(mCanvas);
    }

    @Test
    public void drawOver_preference_doNotDrawDivider() {
        when(mRecyclerView.getAdapter()).thenReturn(mAdapter);
        when(mRecyclerView.getChildCount()).thenReturn(1);
        when(mAdapter.getItem(anyInt())).thenReturn(mNormalPref);

        mDecoration.onDrawOver(mCanvas, mRecyclerView, null /* state */);

        verify(mDrawable, never()).draw(mCanvas);
    }
}