@@ -113,6 +113,7 @@ public interface OnTriggerListener {
113113 private float mWaveCenterY ;
114114 private int mMaxTargetHeight ;
115115 private int mMaxTargetWidth ;
116+ private float mRingScaleFactor = 1f ;
116117
117118 private float mOuterRadius = 0.0f ;
118119 private float mSnapMargin = 0.0f ;
@@ -319,6 +320,22 @@ protected int getSuggestedMinimumHeight() {
319320 return (int ) (Math .max (mOuterRing .getHeight (), 2 * mOuterRadius ) + mMaxTargetHeight );
320321 }
321322
323+ /**
324+ * This gets the suggested width accounting for the ring's scale factor.
325+ */
326+ protected int getScaledSuggestedMinimumWidth () {
327+ return (int ) (mRingScaleFactor * Math .max (mOuterRing .getWidth (), 2 * mOuterRadius )
328+ + mMaxTargetWidth );
329+ }
330+
331+ /**
332+ * This gets the suggested height accounting for the ring's scale factor.
333+ */
334+ protected int getScaledSuggestedMinimumHeight () {
335+ return (int ) (mRingScaleFactor * Math .max (mOuterRing .getHeight (), 2 * mOuterRadius )
336+ + mMaxTargetHeight );
337+ }
338+
322339 private int resolveMeasured (int measureSpec , int desired )
323340 {
324341 int result = 0 ;
@@ -337,16 +354,6 @@ private int resolveMeasured(int measureSpec, int desired)
337354 return result ;
338355 }
339356
340- @ Override
341- protected void onMeasure (int widthMeasureSpec , int heightMeasureSpec ) {
342- final int minimumWidth = getSuggestedMinimumWidth ();
343- final int minimumHeight = getSuggestedMinimumHeight ();
344- int computedWidth = resolveMeasured (widthMeasureSpec , minimumWidth );
345- int computedHeight = resolveMeasured (heightMeasureSpec , minimumHeight );
346- computeInsets ((computedWidth - minimumWidth ), (computedHeight - minimumHeight ));
347- setMeasuredDimension (computedWidth , computedHeight );
348- }
349-
350357 private void switchToState (int state , float x , float y ) {
351358 switch (state ) {
352359 case STATE_IDLE :
@@ -504,8 +511,9 @@ private void hideTargets(boolean animate, boolean expanded) {
504511 "onUpdate" , mUpdateListener ));
505512 }
506513
507- final float ringScaleTarget = expanded ?
514+ float ringScaleTarget = expanded ?
508515 RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED ;
516+ ringScaleTarget *= mRingScaleFactor ;
509517 mTargetAnimations .add (Tweener .to (mOuterRing , duration ,
510518 "ease" , interpolator ,
511519 "alpha" , 0.0f ,
@@ -535,11 +543,13 @@ private void showTargets(boolean animate) {
535543 "delay" , delay ,
536544 "onUpdate" , mUpdateListener ));
537545 }
546+
547+ float ringScale = mRingScaleFactor * RING_SCALE_EXPANDED ;
538548 mTargetAnimations .add (Tweener .to (mOuterRing , duration ,
539549 "ease" , Ease .Cubic .easeOut ,
540550 "alpha" , 1.0f ,
541- "scaleX" , 1.0f ,
542- "scaleY" , 1.0f ,
551+ "scaleX" , ringScale ,
552+ "scaleY" , ringScale ,
543553 "delay" , delay ,
544554 "onUpdate" , mUpdateListener ,
545555 "onComplete" , mTargetUpdateListener ));
@@ -1018,6 +1028,74 @@ private void computeInsets(int dx, int dy) {
10181028 }
10191029 }
10201030
1031+ /**
1032+ * Given the desired width and height of the ring and the allocated width and height, compute
1033+ * how much we need to scale the ring.
1034+ */
1035+ private float computeScaleFactor (int desiredWidth , int desiredHeight ,
1036+ int actualWidth , int actualHeight ) {
1037+ final int layoutDirection = getLayoutDirection ();
1038+ final int absoluteGravity = Gravity .getAbsoluteGravity (mGravity , layoutDirection );
1039+
1040+ float scaleX = 1f ;
1041+ float scaleY = 1f ;
1042+
1043+ // We use the gravity as a cue for whether we want to scale on a particular axis.
1044+ // We only scale to fit horizontally if we're not pinned to the left or right. Likewise,
1045+ // we only scale to fit vertically if we're not pinned to the top or bottom. In these
1046+ // cases, we want the ring to hang off the side or top/bottom, respectively.
1047+ switch (absoluteGravity & Gravity .HORIZONTAL_GRAVITY_MASK ) {
1048+ case Gravity .LEFT :
1049+ case Gravity .RIGHT :
1050+ break ;
1051+ case Gravity .CENTER_HORIZONTAL :
1052+ default :
1053+ if (desiredWidth > actualWidth ) {
1054+ scaleX = (1f * actualWidth - mMaxTargetWidth ) /
1055+ (desiredWidth - mMaxTargetWidth );
1056+ }
1057+ break ;
1058+ }
1059+ switch (absoluteGravity & Gravity .VERTICAL_GRAVITY_MASK ) {
1060+ case Gravity .TOP :
1061+ case Gravity .BOTTOM :
1062+ break ;
1063+ case Gravity .CENTER_VERTICAL :
1064+ default :
1065+ if (desiredHeight > actualHeight ) {
1066+ scaleY = (1f * actualHeight - mMaxTargetHeight ) /
1067+ (desiredHeight - mMaxTargetHeight );
1068+ }
1069+ break ;
1070+ }
1071+ return Math .min (scaleX , scaleY );
1072+ }
1073+
1074+ @ Override
1075+ protected void onMeasure (int widthMeasureSpec , int heightMeasureSpec ) {
1076+ final int minimumWidth = getSuggestedMinimumWidth ();
1077+ final int minimumHeight = getSuggestedMinimumHeight ();
1078+ int computedWidth = resolveMeasured (widthMeasureSpec , minimumWidth );
1079+ int computedHeight = resolveMeasured (heightMeasureSpec , minimumHeight );
1080+
1081+ mRingScaleFactor = computeScaleFactor (minimumWidth , minimumHeight ,
1082+ computedWidth , computedHeight );
1083+
1084+ int scaledWidth = getScaledSuggestedMinimumWidth ();
1085+ int scaledHeight = getScaledSuggestedMinimumHeight ();
1086+
1087+ computeInsets (computedWidth - scaledWidth , computedHeight - scaledHeight );
1088+ setMeasuredDimension (computedWidth , computedHeight );
1089+ }
1090+
1091+ private float getRingWidth () {
1092+ return mRingScaleFactor * Math .max (mOuterRing .getWidth (), 2 * mOuterRadius );
1093+ }
1094+
1095+ private float getRingHeight () {
1096+ return mRingScaleFactor * Math .max (mOuterRing .getHeight (), 2 * mOuterRadius );
1097+ }
1098+
10211099 @ Override
10221100 protected void onLayout (boolean changed , int left , int top , int right , int bottom ) {
10231101 super .onLayout (changed , left , top , right , bottom );
@@ -1026,8 +1104,8 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
10261104
10271105 // Target placement width/height. This puts the targets on the greater of the ring
10281106 // width or the specified outer radius.
1029- final float placementWidth = Math . max ( mOuterRing . getWidth (), 2 * mOuterRadius );
1030- final float placementHeight = Math . max ( mOuterRing . getHeight (), 2 * mOuterRadius );
1107+ final float placementWidth = getRingWidth ( );
1108+ final float placementHeight = getRingHeight ( );
10311109 float newWaveCenterX = mHorizontalInset
10321110 + Math .max (width , mMaxTargetWidth + placementWidth ) / 2 ;
10331111 float newWaveCenterY = mVerticalInset
@@ -1042,6 +1120,8 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
10421120 mOuterRing .setPositionX (newWaveCenterX );
10431121 mOuterRing .setPositionY (newWaveCenterY );
10441122
1123+ mPointCloud .setScale (mRingScaleFactor );
1124+
10451125 mHandleDrawable .setPositionX (newWaveCenterX );
10461126 mHandleDrawable .setPositionY (newWaveCenterY );
10471127
@@ -1061,13 +1141,15 @@ private void updateTargetPosition(int i, float centerX, float centerY) {
10611141 }
10621142
10631143 private void updateTargetPosition (int i , float centerX , float centerY , float angle ) {
1144+ final float placementRadiusX = getRingWidth () / 2 ;
1145+ final float placementRadiusY = getRingHeight () / 2 ;
10641146 if (i >= 0 ) {
10651147 ArrayList <TargetDrawable > targets = mTargetDrawables ;
10661148 final TargetDrawable targetIcon = targets .get (i );
10671149 targetIcon .setPositionX (centerX );
10681150 targetIcon .setPositionY (centerY );
1069- targetIcon .setX (mOuterRadius * (float ) Math .cos (angle ));
1070- targetIcon .setY (mOuterRadius * (float ) Math .sin (angle ));
1151+ targetIcon .setX (placementRadiusX * (float ) Math .cos (angle ));
1152+ targetIcon .setY (placementRadiusY * (float ) Math .sin (angle ));
10711153 }
10721154 }
10731155
0 commit comments