Extends SeekBarPreference to add labels and callbacks

Adds title, left and right labels to the SeekBarPreference. Also adds
a listener for the seek stop event.

Bug: 146004827
Test: make RunSettingsRoboTests ROBOTEST_FILTER=GestureNavigationSeekBarPreferenceTest

Change-Id: I0ecca4e92cfc52abb8bb975b710f72f75ed5b50d
diff --git a/res/layout/preference_gesture_navigation_slider.xml b/res/layout/preference_gesture_navigation_slider.xml
new file mode 100644
index 0000000..ac7f334
--- /dev/null
+++ b/res/layout/preference_gesture_navigation_slider.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 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
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:gravity="center_vertical"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingStart="56dp"
+    android:paddingEnd="8dp"
+    android:paddingTop="16dp"
+    android:paddingBottom="8dp">
+
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_alignParentTop="true"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal"
+        android:singleLine="true"
+        android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+        android:textColor="?android:attr/textColorPrimary" />
+
+    <SeekBar
+        android:id="@*android:id/seekbar"
+        android:layout_below="@android:id/title"
+        android:layout_gravity="center_vertical"
+        android:layout_width="match_parent"
+        android:layout_height="70dp"
+        android:layout_marginTop="-20dp"
+        android:layout_marginBottom="-28dp"
+        style="@android:style/Widget.Material.SeekBar.Discrete" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@*android:id/seekbar"
+        android:paddingBottom="8dp"
+        android:orientation="horizontal">
+
+        <TextView
+            android:id="@android:id/text1"
+            android:layout_marginStart="16dp"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|top"
+            android:gravity="start"
+            android:text="@string/low_label"
+            android:layout_weight="1"/>
+
+        <TextView
+            android:id="@android:id/text2"
+            android:layout_marginEnd="16dp"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end|top"
+            android:gravity="end"
+            android:text="@string/high_label"
+            android:layout_weight="1"/>
+
+    </LinearLayout>
+
+</RelativeLayout>
+
diff --git a/src/com/android/settings/gestures/GestureNavigationSeekBarPreference.java b/src/com/android/settings/gestures/GestureNavigationSeekBarPreference.java
new file mode 100644
index 0000000..085411b
--- /dev/null
+++ b/src/com/android/settings/gestures/GestureNavigationSeekBarPreference.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 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.settings.gestures;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+import androidx.core.content.res.TypedArrayUtils;
+
+import com.android.settings.R;
+import com.android.settings.widget.SeekBarPreference;
+
+/** A slider preference that is used to set the back gesture's sensitivity **/
+public class GestureNavigationSeekBarPreference extends SeekBarPreference {
+
+    private OnPreferenceChangeListener mStopListener;
+
+    public GestureNavigationSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+
+        super(context, attrs, defStyleAttr, defStyleRes);
+        setLayoutResource(R.layout.preference_gesture_navigation_slider);
+    }
+
+    public GestureNavigationSeekBarPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, TypedArrayUtils.getAttr(context,
+                androidx.preference.R.attr.seekBarPreferenceStyle,
+                com.android.internal.R.attr.seekBarPreferenceStyle), 0);
+    }
+
+    public void setOnPreferenceChangeStopListener(OnPreferenceChangeListener listener) {
+        mStopListener = listener;
+    }
+
+    @Override
+    public void onStopTrackingTouch(SeekBar seekBar) {
+        super.onStopTrackingTouch(seekBar);
+
+        if (mStopListener != null) {
+            mStopListener.onPreferenceChange(this, seekBar.getProgress());
+        }
+    }
+}
+
diff --git a/tests/robotests/src/com/android/settings/gestures/GestureNavigationSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/gestures/GestureNavigationSeekBarPreferenceTest.java
new file mode 100644
index 0000000..82c3262
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/GestureNavigationSeekBarPreferenceTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 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.settings.gestures;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+import androidx.preference.Preference;
+
+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 class GestureNavigationSeekBarPreferenceTest {
+
+    private Context mContext;
+    private SeekBar mSeekBar;
+    private GestureNavigationSeekBarPreference mSeekBarPreference;
+
+    @Mock
+    private Preference.OnPreferenceChangeListener mListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mSeekBarPreference = new GestureNavigationSeekBarPreference(mContext, null);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        final View view =
+                inflater.inflate(mSeekBarPreference.getLayoutResource(),
+                        new LinearLayout(mContext), false);
+        mSeekBar = view.findViewById(com.android.internal.R.id.seekbar);
+    }
+
+    @Test
+    public void seekBarPreferenceOnStopTrackingTouch_callsListener() {
+        mSeekBar.setProgress(2);
+
+        mSeekBarPreference.setOnPreferenceChangeStopListener(mListener);
+        mSeekBarPreference.onStopTrackingTouch(mSeekBar);
+
+        verify(mListener, times(1)).onPreferenceChange(mSeekBarPreference, 2);
+    }
+}