aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Huang <yabinh@google.com>2020-05-19 20:03:29 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-05-19 20:03:29 +0000
commit653bdf987bcf2e2bb7e94288f52eba06cc5d4e38 (patch)
treeeaba452e9bdf6951067f439077f9ea0dbf2b6e26
parent26038d631c5e4a7fa99af86040ba109c1b6b5179 (diff)
parent56e5ab553a063664118d8f55ab6ac9d2d6e75be5 (diff)
downloadtests-653bdf987bcf2e2bb7e94288f52eba06cc5d4e38.tar.gz
Merge "Exit direct manipulation mode when the fragment is not active" into rvc-dev
-rw-r--r--RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java176
1 files changed, 109 insertions, 67 deletions
diff --git a/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java b/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java
index fb02105..fc99676 100644
--- a/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java
+++ b/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java
@@ -32,8 +32,8 @@ import com.android.car.ui.utils.DirectManipulationHelper;
/**
* Fragment that demos rotary interactions directly manipulating the state of UI widgets such as a
- * {@link android.widget.SeekBar}, {@link android.widget.DatePicker}, and
- * {@link android.widget.RadialTimePickerView}.
+ * {@link android.widget.SeekBar}, {@link android.widget.DatePicker},
+ * {@link android.widget.RadialTimePickerView}, and {@link DirectManipulationView}.
*/
public class RotaryDirectManipulationWidgets extends Fragment {
// TODO(agathaman): refactor a common class that takes in a fragment xml id and inflates it, to
@@ -45,105 +45,147 @@ public class RotaryDirectManipulationWidgets extends Fragment {
/** How many pixels do we want to zoom the {@link DirectManipulationView} for a rotation. */
private static final float DIRECT_MANIPULATION_VIEW_PX_PER_ROTATION = 10f;
- /** Background color of {@link DirectManipulationView} when it's in direct manipulation mode. */
+ /** 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 {@link DirectManipulationView} when it's not in direct manipulation
- * mode.
- */
+ /** 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;
- /** Whether any view in this Fragment is in direct manipulation mode. */
- private boolean mInDirectManipulationMode;
+ /** The view that is in direct manipulation mode, or null if none. */
+ private View mViewInDirectManipulationMode;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.rotary_direct_manipulation, container, false);
- DirectManipulationView directManipulationView =
- view.findViewById(R.id.direct_manipulation_view);
- initDirectManipulationView(directManipulationView);
+ DirectManipulationView dmv = view.findViewById(R.id.direct_manipulation_view);
+ initDirectManipulationMode(dmv, /* handleNudge= */ true, /* handleRotate= */ true);
return view;
}
+ @Override
+ public void onPause() {
+ if (mViewInDirectManipulationMode != null) {
+ // 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(mViewInDirectManipulationMode, false);
+ }
+ super.onPause();
+ }
+
/**
- * Initializes the {@link DirectManipulationView} so that it can enter/exit direct manipulation
- * mode and interact with the rotary controller directly. In direct manipulation mode, the
- * circle of the DirectManipulationView can move when the controller nudges, and the circle of
- * the DirectManipulationView can zoom when the controller rotates.
+ * Initializes the given view so that it can enter/exit direct manipulation mode and interact
+ * with the rotary controller directly.
+ *
+ * @param dmv the view to enable direct manipulation mode
+ * @param handleNudge whether to handle controller nudge in direct manipulation mode
+ * @param handleRotate whether to handle controller rotate in direct manipulation mode
*/
- private void initDirectManipulationView(@NonNull DirectManipulationView dmv) {
+ private void initDirectManipulationMode(
+ @NonNull View dmv, boolean handleNudge, boolean handleRotate) {
dmv.setOnKeyListener((view, keyCode, keyEvent) -> {
boolean isActionUp = keyEvent.getAction() == KeyEvent.ACTION_UP;
switch (keyCode) {
// Always consume KEYCODE_DPAD_CENTER and KEYCODE_BACK event.
case KeyEvent.KEYCODE_DPAD_CENTER:
- if (!mInDirectManipulationMode && isActionUp) {
- mInDirectManipulationMode = true;
- dmv.setBackgroundColor(BACKGROUND_COLOR_IN_DIRECT_MANIPULATION_MODE);
- dmv.invalidate();
- DirectManipulationHelper.enableDirectManipulationMode(dmv, true);
+ if (mViewInDirectManipulationMode == null && isActionUp) {
+ enableDirectManipulationMode(dmv, true);
}
return true;
case KeyEvent.KEYCODE_BACK:
- if (mInDirectManipulationMode && isActionUp) {
- mInDirectManipulationMode = false;
- dmv.setBackgroundColor(BACKGROUND_COLOR_NOT_IN_DIRECT_MANIPULATION_MODE);
- dmv.invalidate();
- DirectManipulationHelper.enableDirectManipulationMode(dmv, false);
+ if (mViewInDirectManipulationMode != null && isActionUp) {
+ enableDirectManipulationMode(dmv, false);
}
return true;
- // Consume controller nudge event (KEYCODE_DPAD_UP, KEYCODE_DPAD_DOWN,
- // KEYCODE_DPAD_LEFT, or KEYCODE_DPAD_RIGHT) only when in direct manipulation mode.
- // When handling nudge event, move the circle of the DirectManipulationView.
+ // Consume nudge event if the view handles controller nudge in direct manipulation
+ // mode.
case KeyEvent.KEYCODE_DPAD_UP:
- if (!mInDirectManipulationMode) {
- return false;
- }
- if (isActionUp) {
- dmv.move(0f, -DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE);
- }
- return true;
case KeyEvent.KEYCODE_DPAD_DOWN:
- if (!mInDirectManipulationMode) {
- return false;
- }
- if (isActionUp) {
- dmv.move(0f, DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE);
- }
- return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
- if (!mInDirectManipulationMode) {
- return false;
- }
- if (isActionUp) {
- dmv.move(-DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE, 0f);
- }
- return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (!mInDirectManipulationMode) {
- return false;
- }
- if (isActionUp) {
- dmv.move(DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE, 0f);
- }
- return true;
+ return handleNudge? handleNudgeEvent(keyEvent) : false;
// Don't consume other key events.
default:
return false;
}
});
- // When in direct manipulation mode, zoom the circle of the DirectManipulationView on
- // controller rotate event.
- dmv.setOnGenericMotionListener(((view, motionEvent) -> {
- if (!mInDirectManipulationMode) {
- return false;
- }
- float scroll = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL);
- dmv.zoom(DIRECT_MANIPULATION_VIEW_PX_PER_ROTATION * scroll);
+ // Consume rotate event if the view handles controller rotate in direct manipulation mode.
+ if (handleRotate) {
+ dmv.setOnGenericMotionListener(((view, motionEvent) -> {
+ float scroll = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL);
+ return handleRotateEvent(scroll);
+ }));
+ }
+ }
+
+ 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);
+ mViewInDirectManipulationMode = enable ? view : null;
+ }
+
+ /** Handles controller nudge event. Returns whether the event was consumed. */
+ private boolean handleNudgeEvent(KeyEvent keyEvent) {
+ if (mViewInDirectManipulationMode == null) {
+ return false;
+ }
+ if (keyEvent.getAction() != KeyEvent.ACTION_UP) {
return true;
- }));
+ }
+ int keyCode = keyEvent.getKeyCode();
+ if (mViewInDirectManipulationMode instanceof DirectManipulationView) {
+ DirectManipulationView dmv = (DirectManipulationView) mViewInDirectManipulationMode;
+ handleNudgeEvent(dmv, keyCode);
+ return true;
+ }
+
+ // TODO: support other views.
+
+ return true;
+ }
+
+ /** Handles controller rotate event. Returns whether the event was consumed. */
+ private boolean handleRotateEvent(float scroll) {
+ if (mViewInDirectManipulationMode == null) {
+ return false;
+ }
+ if (mViewInDirectManipulationMode instanceof DirectManipulationView) {
+ DirectManipulationView dmv = (DirectManipulationView) mViewInDirectManipulationMode;
+ handleRotateEvent(dmv, scroll);
+ return true;
+ }
+
+ // TODO: support other views.
+
+ return true;
+ }
+
+ /** Moves the circle of the DirectManipulationView when the controller nudges. */
+ private void handleNudgeEvent(@NonNull DirectManipulationView dmv, int keyCode) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ dmv.move(0f, -DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE);
+ return;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ dmv.move(0f, DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE);
+ return;
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ dmv.move(-DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE, 0f);
+ return;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ dmv.move(DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE, 0f);
+ return;
+ default:
+ throw new IllegalArgumentException("Invalid keycode :" + keyCode);
+ }
+ }
+
+ /** Zooms the circle of the DirectManipulationView when the controller rotates. */
+ private void handleRotateEvent(@NonNull DirectManipulationView dmv, float scroll) {
+ dmv.zoom(DIRECT_MANIPULATION_VIEW_PX_PER_ROTATION * scroll);
}
}