aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPardis Beikzadeh <pardis@google.com>2020-05-28 16:52:08 -0700
committerPardis Beikzadeh <pardis@google.com>2020-06-05 09:55:04 -0700
commit97c16099017c074fc8292c17959966a5e4e26f61 (patch)
treee84cdb14ee114291c73d916d77e9c55629e7a6ee
parent77ffcfd13c0eff5ef307144535e59bf78e1b23a7 (diff)
downloadtests-97c16099017c074fc8292c17959966a5e4e26f61.tar.gz
Reduce code duplication further.
Given that onPause() method needs to also disable DM mode, I moved the logic around some more so it can be reused there and by the DirectManipulationHandler class. Also fixed a bug I found that didn't consume nudge and rotation events when no handler delegate was provided for them. Not consuming the nudge events means that in DM mode user can nudge out of the view that should be directly manipulated. The rotation one doesn't cause an issue as far as I can tell but I am consuming them because that is what the javadoc claims to do (provide a "noop" impl if a delegate not provided = consume event and do nothing). BUG: 156978213 Test: make, install, run code Change-Id: I417b2dcbd5e0fd36e11db58681a8baff9bbfcf8e
-rw-r--r--RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationHandler.java57
-rw-r--r--RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationState.java61
-rw-r--r--RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java22
3 files changed, 64 insertions, 76 deletions
diff --git a/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationHandler.java b/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationHandler.java
index 5773b04..8a87467 100644
--- a/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationHandler.java
+++ b/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationHandler.java
@@ -16,7 +16,6 @@
package com.android.car.rotaryplayground;
-import android.graphics.Color;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -26,8 +25,6 @@ import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.core.util.Preconditions;
-import com.android.car.ui.utils.DirectManipulationHelper;
-
/**
* A {@link View.OnKeyListener} and {@link View.OnGenericMotionListener} that adds a
* "Direct Manipulation" mode to any {@link View} that uses it.
@@ -57,12 +54,6 @@ import com.android.car.ui.utils.DirectManipulationHelper;
public class DirectManipulationHandler implements View.OnKeyListener,
View.OnGenericMotionListener {
- /** Background color of a view when it's in direct manipulation mode. */
- private static final int BACKGROUND_COLOR_IN_DIRECT_MANIPULATION_MODE = Color.BLUE;
-
- /** Background color of a view when it's not in direct manipulation mode. */
- private static final int BACKGROUND_COLOR_NOT_IN_DIRECT_MANIPULATION_MODE = Color.TRANSPARENT;
-
private final DirectManipulationState mDirectManipulationMode;
private final View.OnKeyListener mNudgeDelegate;
private final View.OnGenericMotionListener mRotationDelegate;
@@ -112,51 +103,23 @@ public class DirectManipulationHandler implements View.OnKeyListener,
@Override
public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
boolean isActionUp = keyEvent.getAction() == KeyEvent.ACTION_UP;
- Log.d("RotaryPlayGround", "View: " + view + "\n is handling " + keyCode
+ Log.d("RotaryPlayGround", "View: " + view + " is handling " + keyCode
+ " and action " + keyEvent.getAction()
- + " having entered direct manipulation mode from "
- + mDirectManipulationMode.getStartingView());
+ + " direct manipulation mode is "
+ + (mDirectManipulationMode.isActive() ? "active" : "inactive"));
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
// If not yet in Direct Manipulation mode, switch to that mode.
- // We generally want to give some kind of visual indication that this change
- // has happened. In this example we change the background color.
+
if (!mDirectManipulationMode.isActive() && isActionUp) {
- mDirectManipulationMode.setStartingView(view);
- /*
- * A more robust approach would be to fetch the current background color from
- * the view object and store it back onto the View itself using the {@link
- * View#setTag(int, java.lang.Object)} API. This could then be fetched back
- * and used to restore the background color without needing to keep a constant
- * reference to the color here which could fall out of sync with the xml files.
- */
- view.setBackgroundColor(BACKGROUND_COLOR_IN_DIRECT_MANIPULATION_MODE);
- DirectManipulationHelper.enableDirectManipulationMode(view, true);
+ mDirectManipulationMode.enable(view);
}
return true;
case KeyEvent.KEYCODE_BACK:
// If in Direct Manipulation mode, exit, and clean up state.
if (mDirectManipulationMode.isActive() && isActionUp) {
- // This may or may not be the same as argument v. It is possible
- // for us to enter Direct Manipulation mode from view A and exit from
- // view B. dmStartingView represents A and v represents B.
- View dmStartingView = mDirectManipulationMode.getStartingView();
- // For ViewGroup objects, restore descendant focusability to
- // FOCUS_BLOCK_DESCENDANTS so during non-Direct Manipulation mode, aka,
- // general rotary navigation, we don't go through the individual inner UI
- // elements.
- if (dmStartingView instanceof ViewGroup) {
- ViewGroup viewGroup = (ViewGroup) dmStartingView;
- viewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- }
- // Restore any visual indicators that the view was in Direct Manipulation.
- dmStartingView.setBackgroundColor(
- BACKGROUND_COLOR_NOT_IN_DIRECT_MANIPULATION_MODE);
- // Actually go ahead and disable Direct Manipulation mode for the view.
- DirectManipulationHelper.enableDirectManipulationMode(dmStartingView, false);
- // Update mode.
- mDirectManipulationMode.setStartingView(null);
+ mDirectManipulationMode.disable();
}
return true;
default:
@@ -165,9 +128,9 @@ public class DirectManipulationHandler implements View.OnKeyListener,
if (!mDirectManipulationMode.isActive()) {
return false;
}
- // If no delegate present, ignore events.
+ // If no delegate present, silently consume the events.
if (mNudgeDelegate == null) {
- return false;
+ return true;
}
return mNudgeDelegate.onKey(view, keyCode, keyEvent);
}
@@ -180,9 +143,9 @@ public class DirectManipulationHandler implements View.OnKeyListener,
if (!mDirectManipulationMode.isActive()) {
return false;
}
- // If no delegate present, ignore events.
+ // If no delegate present, silently consume the events.
if (mRotationDelegate == null) {
- return false;
+ return true;
}
return mRotationDelegate.onGenericMotion(v, event);
}
diff --git a/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationState.java b/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationState.java
index 0227643..05d236b 100644
--- a/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationState.java
+++ b/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationState.java
@@ -16,10 +16,15 @@
package com.android.car.rotaryplayground;
+import android.graphics.Color;
import android.view.View;
+import android.view.ViewGroup;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.car.ui.utils.DirectManipulationHelper;
+
/**
* Keeps track of the state of "direct manipulation" Rotary mode for this application window by
* tracking a reference to the {@link View} from which the user first enters into "direct
@@ -29,25 +34,65 @@ import androidx.annotation.Nullable;
*/
public class DirectManipulationState {
+
+ /** Background color of a view when it's in direct manipulation mode. */
+ private static final int BACKGROUND_COLOR_IN_DIRECT_MANIPULATION_MODE = Color.BLUE;
+
+ /** Background color of a view when it's not in direct manipulation mode. */
+ private static final int BACKGROUND_COLOR_NOT_IN_DIRECT_MANIPULATION_MODE = Color.TRANSPARENT;
+
/** The view that is in direct manipulation mode, or null if none. */
@Nullable private View mViewInDirectManipulationMode;
- public void setStartingView(@Nullable View view) {
+ private void setStartingView(@Nullable View view) {
mViewInDirectManipulationMode = view;
}
/**
- * Returns the {@link View} from which we entered into Direct Manipulation mode when that mode
- * is active, and null otherwise.
+ * Returns true if Direct Manipulation mode is active, false otherwise.
+ */
+ public boolean isActive() {
+ return mViewInDirectManipulationMode != null;
+ }
+
+ /**
+ * Enables Direct Manipulation mode, and keeps track of {@code view} as the starting point
+ * of this transition.
+ * <p>
+ * We generally want to give some kind of visual indication that this change has happened. In
+ * this example we change the background color of {@code view}.
+ *
+ * @param view - the {@link View} from which we entered into Direct Manipulation mode.
*/
- @Nullable public View getStartingView() {
- return mViewInDirectManipulationMode;
+ public void enable(@NonNull View view) {
+ /*
+ * A more robust approach would be to fetch the current background color from
+ * the view object and store it back onto the View itself using the {@link
+ * View#setTag(int, java.lang.Object)} API. This could then be fetched back
+ * and used to restore the background color without needing to keep a constant
+ * reference to the color here which could fall out of sync with the xml files.
+ */
+ view.setBackgroundColor(BACKGROUND_COLOR_IN_DIRECT_MANIPULATION_MODE);
+ DirectManipulationHelper.enableDirectManipulationMode(view, /* enable= */ true);
+ setStartingView(view);
}
/**
- * Returns true if Direct Manipulation mode is active, false otherwise.
+ * Disables Direct Manipulation mode and restores any visual indicators for the {@link View}
+ * from which we entered into Direct Manipulation mode.
*/
- public boolean isActive() {
- return mViewInDirectManipulationMode != null;
+ public void disable() {
+ mViewInDirectManipulationMode.setBackgroundColor(
+ BACKGROUND_COLOR_NOT_IN_DIRECT_MANIPULATION_MODE);
+ DirectManipulationHelper.enableDirectManipulationMode(
+ mViewInDirectManipulationMode, /* enable= */ false);
+ // For ViewGroup objects, restore descendant focusability to FOCUS_BLOCK_DESCENDANTS so
+ // during non-Direct Manipulation mode, aka, general rotary navigation, we don't go
+ // through the individual inner UI elements.
+ if (mViewInDirectManipulationMode instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) mViewInDirectManipulationMode;
+ viewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ }
+ setStartingView(null);
}
}
diff --git a/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java b/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java
index a4715c3..9184597 100644
--- a/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java
+++ b/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java
@@ -16,7 +16,6 @@
package com.android.car.rotaryplayground;
-import android.graphics.Color;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -28,12 +27,9 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.NumberPicker;
import android.widget.TimePicker;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
-import com.android.car.ui.utils.DirectManipulationHelper;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -51,12 +47,6 @@ public class RotaryDirectManipulationWidgets extends Fragment {
// TODO(agathaman): refactor a common class that takes in a fragment xml id and inflates it, to
// share between this and RotaryCards.
- /** Background color of a view when it's in direct manipulation mode. */
- private static final int BACKGROUND_COLOR_IN_DIRECT_MANIPULATION_MODE = Color.BLUE;
-
- /** Background color of a view when it's not in direct manipulation mode. */
- private static final int BACKGROUND_COLOR_NOT_IN_DIRECT_MANIPULATION_MODE = Color.TRANSPARENT;
-
private final DirectManipulationState mDirectManipulationMode = new DirectManipulationState();
@Override
@@ -133,21 +123,11 @@ public class RotaryDirectManipulationWidgets extends Fragment {
if (mDirectManipulationMode.isActive()) {
// To ensure that the user doesn't get stuck in direct manipulation mode, disable direct
// manipulation mode when the fragment is not interactive (e.g., a dialog shows up).
- enableDirectManipulationMode(mDirectManipulationMode.getStartingView(), false);
+ mDirectManipulationMode.disable();
}
super.onPause();
}
- private void enableDirectManipulationMode(@NonNull View view, boolean enable) {
- view.setBackgroundColor(enable
- ? BACKGROUND_COLOR_IN_DIRECT_MANIPULATION_MODE
- : BACKGROUND_COLOR_NOT_IN_DIRECT_MANIPULATION_MODE);
- view.invalidate();
- DirectManipulationHelper.enableDirectManipulationMode(view, enable);
- View currentView = enable ? view : null;
- mDirectManipulationMode.setStartingView(currentView);
- }
-
/**
* Register the given {@link DirectManipulationHandler} as both the
* {@link View.OnKeyListener} and {@link View.OnGenericMotionListener} for the given