From fc75237d13c10d4b4f438a3ef60dd54ed92a4ecb Mon Sep 17 00:00:00 2001 From: Pardis Beikzadeh Date: Thu, 21 May 2020 23:10:36 -0700 Subject: Refactor code to reduce duplication. BUG: 153886988 Test: make, install and run Change-Id: I64294a3438e297fb8c6e90b078697b883dee8cb4 --- .../rotaryplayground/DirectManipulationView.java | 100 ++++++++++++++++- .../RotaryDirectManipulationWidgets.java | 122 +-------------------- 2 files changed, 103 insertions(+), 119 deletions(-) diff --git a/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationView.java b/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationView.java index 6c37556..733de87 100644 --- a/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationView.java +++ b/RotaryPlayground/src/com/android/car/rotaryplayground/DirectManipulationView.java @@ -15,17 +15,20 @@ */ package com.android.car.rotaryplayground; +import static java.lang.Math.min; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import static java.lang.Math.min; - /** * A {@link View} used to demonstrate direct manipulation mode. *

@@ -95,7 +98,7 @@ public class DirectManipulationView extends View { } /** Changes the radius of the circle by {@code dr} then redraws it. */ - void zoom(float dr) { + void resizeCircle(float dr) { mDeltaRadius += dr; invalidate(); } @@ -113,4 +116,95 @@ public class DirectManipulationView extends View { mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); } + + /** + * A {@link View.OnKeyListener} for handling Direct Manipulation rotary nudge behavior + * for a {@link DirectManipulationView}. + *

+ * This handler expects that it is being used in Direct Manipulation mode, i.e. as a directional + * delegate through a {@link DirectManipulationHandler} which can invoke it at the + * appropriate times. + *

+ * Moves the circle drawn in the {@link DirectManipulationView} in the relevant direction for + * following {@link KeyEvent}s: + *

+ */ + static class NudgeHandler implements View.OnKeyListener { + + /** How many pixels do we want to move the {@link DirectManipulationView} per nudge. */ + private static final float DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE = 10f; + + @Override + public boolean onKey(View v, int keyCode, KeyEvent keyEvent) { + if (keyEvent.getAction() != KeyEvent.ACTION_UP) { + return true; + } + + if (v instanceof DirectManipulationView) { + DirectManipulationView dmv = (DirectManipulationView) v; + handleNudgeEvent(dmv, keyCode); + return true; + } + + throw new UnsupportedOperationException("NudgeHandler shouldn't be registered " + + "as a listener on a view other than a DirectManipulationView."); + } + + /** 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); + } + } + } + + /** + * A {@link View.OnGenericMotionListener} for handling Direct Manipulation rotation events for + * a {@link DirectManipulationView}. It does so by increasing or decreasing the radius of + * the circle drawn depending on the direction of rotation. + */ + static class RotationHandler implements View.OnGenericMotionListener { + + /** + * How many pixels do we want to change the radius of the circle in the + * {@link DirectManipulationView} for a rotation. + */ + private static final float DIRECT_MANIPULATION_VIEW_PX_PER_ROTATION = 10f; + + @Override + public boolean onGenericMotion(View v, MotionEvent event) { + if (v instanceof DirectManipulationView) { + handleRotateEvent( + (DirectManipulationView) v, + event.getAxisValue(MotionEvent.AXIS_SCROLL)); + return true; + } + + throw new UnsupportedOperationException("RotationHandler shouldn't be registered " + + "as a listener on a view other than a DirectManipulationView."); + } + + /** Resizes the circle of the DirectManipulationView when the controller rotates. */ + private void handleRotateEvent(@NonNull DirectManipulationView dmv, float scroll) { + dmv.resizeCircle(DIRECT_MANIPULATION_VIEW_PX_PER_ROTATION * scroll); + } + } } diff --git a/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java b/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java index 79a384c..a4715c3 100644 --- a/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java +++ b/RotaryPlayground/src/com/android/car/rotaryplayground/RotaryDirectManipulationWidgets.java @@ -51,12 +51,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. - /** How many pixels do we want to move the {@link DirectManipulationView} for nudge. */ - private static final float DIRECT_MANIPULATION_VIEW_PX_PER_NUDGE = 10f; - - /** 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 a view when it's in direct manipulation mode. */ private static final int BACKGROUND_COLOR_IN_DIRECT_MANIPULATION_MODE = Color.BLUE; @@ -71,7 +65,12 @@ public class RotaryDirectManipulationWidgets extends Fragment { View view = inflater.inflate(R.layout.rotary_direct_manipulation, container, false); DirectManipulationView dmv = view.findViewById(R.id.direct_manipulation_view); - initDirectManipulationMode(dmv, /* handleNudge= */ true, /* handleRotate= */ true); + registerDirectManipulationHandler(dmv, + new DirectManipulationHandler.Builder(mDirectManipulationMode) + .setNudgeHandler(new DirectManipulationView.NudgeHandler()) + .setRotationHandler(new DirectManipulationView.RotationHandler()) + .build()); + TimePicker spinnerTimePicker = view.findViewById(R.id.spinner_time_picker); registerDirectManipulationHandler(spinnerTimePicker, @@ -139,52 +138,6 @@ public class RotaryDirectManipulationWidgets extends Fragment { super.onPause(); } - /** - * 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 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 (!mDirectManipulationMode.isActive() && isActionUp) { - enableDirectManipulationMode(dmv, true); - } - return true; - case KeyEvent.KEYCODE_BACK: - if (mDirectManipulationMode.isActive() && isActionUp) { - enableDirectManipulationMode(dmv, false); - } - return true; - // Consume nudge event if the view handles controller nudge in direct manipulation - // mode. - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_DOWN: - case KeyEvent.KEYCODE_DPAD_LEFT: - case KeyEvent.KEYCODE_DPAD_RIGHT: - return handleNudge ? handleNudgeEvent(keyEvent) : false; - // Don't consume other key events. - default: - return false; - } - }); - - // 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 @@ -195,69 +148,6 @@ public class RotaryDirectManipulationWidgets extends Fragment { mDirectManipulationMode.setStartingView(currentView); } - /** Handles controller nudge event. Returns whether the event was consumed. */ - private boolean handleNudgeEvent(KeyEvent keyEvent) { - if (!mDirectManipulationMode.isActive()) { - return false; - } - if (keyEvent.getAction() != KeyEvent.ACTION_UP) { - return true; - } - int keyCode = keyEvent.getKeyCode(); - if (mDirectManipulationMode.getStartingView() instanceof DirectManipulationView) { - DirectManipulationView dmv = - (DirectManipulationView) mDirectManipulationMode.getStartingView(); - 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 (!mDirectManipulationMode.isActive()) { - return false; - } - if (mDirectManipulationMode.getStartingView() instanceof DirectManipulationView) { - DirectManipulationView dmv = - (DirectManipulationView) mDirectManipulationMode.getStartingView(); - 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); - } - /** * Register the given {@link DirectManipulationHandler} as both the * {@link View.OnKeyListener} and {@link View.OnGenericMotionListener} for the given -- cgit v1.2.3