@@ -116,6 +116,8 @@ public interface OnTriggerListener {
116116
117117 private float mOuterRadius = 0.0f ;
118118 private float mSnapMargin = 0.0f ;
119+ private float mFirstItemOffset = 0.0f ;
120+ private boolean mMagneticTargets = false ;
119121 private boolean mDragging ;
120122 private int mNewTargetResources ;
121123
@@ -212,6 +214,9 @@ public GlowPadView(Context context, AttributeSet attrs) {
212214 mInnerRadius = a .getDimension (R .styleable .GlowPadView_innerRadius , mInnerRadius );
213215 mOuterRadius = a .getDimension (R .styleable .GlowPadView_outerRadius , mOuterRadius );
214216 mSnapMargin = a .getDimension (R .styleable .GlowPadView_snapMargin , mSnapMargin );
217+ mFirstItemOffset = (float ) Math .toRadians (
218+ a .getFloat (R .styleable .GlowPadView_firstItemOffset ,
219+ (float ) Math .toDegrees (mFirstItemOffset )));
215220 mVibrationDuration = a .getInt (R .styleable .GlowPadView_vibrationDuration ,
216221 mVibrationDuration );
217222 mFeedbackCount = a .getInt (R .styleable .GlowPadView_feedbackCount ,
@@ -223,6 +228,7 @@ public GlowPadView(Context context, AttributeSet attrs) {
223228 getResourceId (a , R .styleable .GlowPadView_outerRingDrawable ));
224229
225230 mAlwaysTrackFinger = a .getBoolean (R .styleable .GlowPadView_alwaysTrackFinger , false );
231+ mMagneticTargets = a .getBoolean (R .styleable .GlowPadView_magneticTargets , mMagneticTargets );
226232
227233 int pointId = getResourceId (a , R .styleable .GlowPadView_pointDrawable );
228234 Drawable pointDrawable = pointId != 0 ? res .getDrawable (pointId ) : null ;
@@ -820,6 +826,7 @@ private void handleMove(MotionEvent event) {
820826 int ntargets = targets .size ();
821827 float x = 0.0f ;
822828 float y = 0.0f ;
829+ float activeAngle = 0.0f ;
823830 int actionIndex = event .findPointerIndex (mPointerId );
824831
825832 if (actionIndex == -1 ) {
@@ -852,15 +859,18 @@ private void handleMove(MotionEvent event) {
852859 for (int i = 0 ; i < ntargets ; i ++) {
853860 TargetDrawable target = targets .get (i );
854861
855- double targetMinRad = (i - 0.5 ) * 2 * Math .PI / ntargets ;
856- double targetMaxRad = (i + 0.5 ) * 2 * Math .PI / ntargets ;
862+ double targetMinRad = mFirstItemOffset + (i - 0.5 ) * 2 * Math .PI / ntargets ;
863+ double targetMaxRad = mFirstItemOffset + (i + 0.5 ) * 2 * Math .PI / ntargets ;
857864 if (target .isEnabled ()) {
858865 boolean angleMatches =
859866 (angleRad > targetMinRad && angleRad <= targetMaxRad ) ||
860867 (angleRad + 2 * Math .PI > targetMinRad &&
861- angleRad + 2 * Math .PI <= targetMaxRad );
868+ angleRad + 2 * Math .PI <= targetMaxRad ) ||
869+ (angleRad - 2 * Math .PI > targetMinRad &&
870+ angleRad - 2 * Math .PI <= targetMaxRad );
862871 if (angleMatches && (dist2 (tx , ty ) > snapDistance2 )) {
863872 activeTarget = i ;
873+ activeAngle = (float ) -angleRad ;
864874 }
865875 }
866876 }
@@ -888,13 +898,19 @@ private void handleMove(MotionEvent event) {
888898 if (target .hasState (TargetDrawable .STATE_FOCUSED )) {
889899 target .setState (TargetDrawable .STATE_INACTIVE );
890900 }
901+ if (mMagneticTargets ) {
902+ updateTargetPosition (mActiveTarget , mWaveCenterX , mWaveCenterY );
903+ }
891904 }
892905 // Focus the new target
893906 if (activeTarget != -1 ) {
894907 TargetDrawable target = targets .get (activeTarget );
895908 if (target .hasState (TargetDrawable .STATE_FOCUSED )) {
896909 target .setState (TargetDrawable .STATE_FOCUSED );
897910 }
911+ if (mMagneticTargets ) {
912+ updateTargetPosition (activeTarget , mWaveCenterX , mWaveCenterY , activeAngle );
913+ }
898914 if (AccessibilityManager .getInstance (mContext ).isEnabled ()) {
899915 String targetContentDescription = getTargetDescription (activeTarget );
900916 announceForAccessibility (targetContentDescription );
@@ -1039,21 +1055,45 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
10391055 if (DEBUG ) dump ();
10401056 }
10411057
1042- private void updateTargetPositions (float centerX , float centerY ) {
1043- // Reposition the target drawables if the view changed.
1044- ArrayList <TargetDrawable > targets = mTargetDrawables ;
1045- final int size = targets .size ();
1046- final float alpha = (float ) (-2.0f * Math .PI / size );
1047- for (int i = 0 ; i < size ; i ++) {
1058+ private void updateTargetPosition (int i , float centerX , float centerY ) {
1059+ final float angle = getAngle (getSliceAngle (), i );
1060+ updateTargetPosition (i , centerX , centerY , angle );
1061+ }
1062+
1063+ private void updateTargetPosition (int i , float centerX , float centerY , float angle ) {
1064+ if (i >= 0 ) {
1065+ ArrayList <TargetDrawable > targets = mTargetDrawables ;
10481066 final TargetDrawable targetIcon = targets .get (i );
1049- final float angle = alpha * i ;
10501067 targetIcon .setPositionX (centerX );
10511068 targetIcon .setPositionY (centerY );
10521069 targetIcon .setX (mOuterRadius * (float ) Math .cos (angle ));
10531070 targetIcon .setY (mOuterRadius * (float ) Math .sin (angle ));
10541071 }
10551072 }
10561073
1074+ private void updateTargetPositions (float centerX , float centerY ) {
1075+ updateTargetPositions (centerX , centerY , false );
1076+ }
1077+
1078+ private void updateTargetPositions (float centerX , float centerY , boolean skipActive ) {
1079+ final int size = mTargetDrawables .size ();
1080+ final float alpha = getSliceAngle ();
1081+ // Reposition the target drawables if the view changed.
1082+ for (int i = 0 ; i < size ; i ++) {
1083+ if (!skipActive || i != mActiveTarget ) {
1084+ updateTargetPosition (i , centerX , centerY , getAngle (alpha , i ));
1085+ }
1086+ }
1087+ }
1088+
1089+ private float getAngle (float alpha , int i ) {
1090+ return mFirstItemOffset + alpha * i ;
1091+ }
1092+
1093+ private float getSliceAngle () {
1094+ return (float ) (-2.0f * Math .PI / mTargetDrawables .size ());
1095+ }
1096+
10571097 private void updatePointCloudPosition (float centerX , float centerY ) {
10581098 mPointCloud .setCenter (centerX , centerY );
10591099 }
0 commit comments