3232import android .util .AttributeSet ;
3333import android .util .Log ;
3434import android .util .TypedValue ;
35+ import android .view .Gravity ;
3536import android .view .MotionEvent ;
3637import android .view .View ;
3738import android .view .accessibility .AccessibilityEvent ;
@@ -99,8 +100,11 @@ public interface OnTriggerListener {
99100 private float mTapRadius ;
100101 private float mWaveCenterX ;
101102 private float mWaveCenterY ;
102- private float mVerticalOffset ;
103+ private int mMaxTargetHeight ;
104+ private int mMaxTargetWidth ;
103105 private float mHorizontalOffset ;
106+ private float mVerticalOffset ;
107+
104108 private float mOuterRadius = 0.0f ;
105109 private float mHitRadius = 0.0f ;
106110 private float mSnapMargin = 0.0f ;
@@ -142,6 +146,9 @@ public void onAnimationEnd(Animator animator) {
142146 private int mTargetDescriptionsResourceId ;
143147 private int mDirectionDescriptionsResourceId ;
144148 private boolean mAlwaysTrackFinger ;
149+ private int mHorizontalInset ;
150+ private int mVerticalInset ;
151+ private int mGravity = Gravity .TOP ;
145152
146153 public MultiWaveView (Context context ) {
147154 this (context , null );
@@ -153,10 +160,9 @@ public MultiWaveView(Context context, AttributeSet attrs) {
153160
154161 TypedArray a = context .obtainStyledAttributes (attrs , R .styleable .MultiWaveView );
155162 mOuterRadius = a .getDimension (R .styleable .MultiWaveView_outerRadius , mOuterRadius );
156- mHorizontalOffset = a .getDimension (R .styleable .MultiWaveView_horizontalOffset ,
157- mHorizontalOffset );
158- mVerticalOffset = a .getDimension (R .styleable .MultiWaveView_verticalOffset ,
159- mVerticalOffset );
163+ // mHorizontalOffset = a.getDimension(R.styleable.MultiWaveView_horizontalOffset,
164+ // mHorizontalOffset);
165+ // mVerticalOffset = a.getDimension(R.styleable.MultiWaveView_verticalOffset, mVerticalOffset);
160166 mHitRadius = a .getDimension (R .styleable .MultiWaveView_hitRadius , mHitRadius );
161167 mSnapMargin = a .getDimension (R .styleable .MultiWaveView_snapMargin , mSnapMargin );
162168 mVibrationDuration = a .getInt (R .styleable .MultiWaveView_vibrationDuration ,
@@ -169,6 +175,7 @@ public MultiWaveView(Context context, AttributeSet attrs) {
169175 mOuterRing = new TargetDrawable (res ,
170176 a .peekValue (R .styleable .MultiWaveView_waveDrawable ).resourceId );
171177 mAlwaysTrackFinger = a .getBoolean (R .styleable .MultiWaveView_alwaysTrackFinger , false );
178+ mGravity = a .getInt (R .styleable .MultiWaveView_gravity , Gravity .TOP );
172179
173180 // Read chevron animation drawables
174181 final int chevrons [] = { R .styleable .MultiWaveView_leftChevronDrawable ,
@@ -231,16 +238,16 @@ private void dump() {
231238
232239 @ Override
233240 protected int getSuggestedMinimumWidth () {
234- // View should be large enough to contain the background + target drawable on either edge
235- return mOuterRing . getWidth ()
236- + ( mTargetDrawables . size () > 0 ? ( mTargetDrawables . get ( 0 ). getWidth ()/ 2 ) : 0 ) ;
241+ // View should be large enough to contain the background + handle and
242+ // target drawable on either edge.
243+ return mOuterRing . getWidth () + mMaxTargetWidth ;
237244 }
238245
239246 @ Override
240247 protected int getSuggestedMinimumHeight () {
241- // View should be large enough to contain the unlock ring + target drawable on either edge
242- return mOuterRing . getHeight ()
243- + ( mTargetDrawables . size () > 0 ? ( mTargetDrawables . get ( 0 ). getHeight ()/ 2 ) : 0 ) ;
248+ // View should be large enough to contain the unlock ring + target and
249+ // target drawable on either edge
250+ return mOuterRing . getHeight () + mMaxTargetHeight ;
244251 }
245252
246253 private int resolveMeasured (int measureSpec , int desired )
@@ -265,9 +272,10 @@ private int resolveMeasured(int measureSpec, int desired)
265272 protected void onMeasure (int widthMeasureSpec , int heightMeasureSpec ) {
266273 final int minimumWidth = getSuggestedMinimumWidth ();
267274 final int minimumHeight = getSuggestedMinimumHeight ();
268- int viewWidth = resolveMeasured (widthMeasureSpec , minimumWidth );
269- int viewHeight = resolveMeasured (heightMeasureSpec , minimumHeight );
270- setMeasuredDimension (viewWidth , viewHeight );
275+ int computedWidth = resolveMeasured (widthMeasureSpec , minimumWidth );
276+ int computedHeight = resolveMeasured (heightMeasureSpec , minimumHeight );
277+ setupGravity ((computedWidth - minimumWidth ), (computedHeight - minimumHeight ));
278+ setMeasuredDimension (computedWidth , computedHeight );
271279 }
272280
273281 private void switchToState (int state , float x , float y ) {
@@ -521,14 +529,25 @@ private void internalSetTargetResources(int resourceId) {
521529 TypedArray array = res .obtainTypedArray (resourceId );
522530 int count = array .length ();
523531 ArrayList <TargetDrawable > targetDrawables = new ArrayList <TargetDrawable >(count );
532+ int maxWidth = mHandleDrawable .getWidth ();
533+ int maxHeight = mHandleDrawable .getHeight ();
524534 for (int i = 0 ; i < count ; i ++) {
525535 TypedValue value = array .peekValue (i );
526- targetDrawables .add (new TargetDrawable (res , value != null ? value .resourceId : 0 ));
536+ TargetDrawable target = new TargetDrawable (res , value != null ? value .resourceId : 0 );
537+ targetDrawables .add (target );
538+ maxWidth = Math .max (maxWidth , target .getWidth ());
539+ maxHeight = Math .max (maxHeight , target .getHeight ());
540+ }
541+ if (mMaxTargetWidth != maxWidth || mMaxTargetHeight != maxHeight ) {
542+ mMaxTargetWidth = maxWidth ;
543+ mMaxTargetHeight = maxHeight ;
544+ requestLayout (); // required to resize layout and call updateTargetPositions()
545+ } else {
546+ updateTargetPositions ();
527547 }
528548 array .recycle ();
529549 mTargetResourceId = resourceId ;
530550 mTargetDrawables = targetDrawables ;
531- updateTargetPositions ();
532551 }
533552
534553 /**
@@ -638,23 +657,27 @@ public boolean onTouchEvent(MotionEvent event) {
638657 boolean handled = false ;
639658 switch (action ) {
640659 case MotionEvent .ACTION_DOWN :
660+ if (DEBUG ) Log .v (TAG , "*** DOWN ***" );
641661 handleDown (event );
642662 handled = true ;
643663 break ;
644664
645665 case MotionEvent .ACTION_MOVE :
666+ if (DEBUG ) Log .v (TAG , "*** MOVE ***" );
646667 handleMove (event );
647668 handled = true ;
648669 break ;
649670
650671 case MotionEvent .ACTION_UP :
672+ if (DEBUG ) Log .v (TAG , "*** UP ***" );
651673 handleMove (event );
652674 handleUp (event );
653675 handled = true ;
654676 break ;
655677
656678 case MotionEvent .ACTION_CANCEL :
657- handleMove (event );
679+ if (DEBUG ) Log .v (TAG , "*** CANCEL ***" );
680+ // handleMove(event);
658681 handleCancel (event );
659682 handled = true ;
660683 break ;
@@ -795,6 +818,11 @@ private void setGrabbedState(int newState) {
795818 }
796819 mGrabbedState = newState ;
797820 if (mOnTriggerListener != null ) {
821+ if (newState == OnTriggerListener .NO_HANDLE ) {
822+ mOnTriggerListener .onReleased (this , OnTriggerListener .CENTER_HANDLE );
823+ } else {
824+ mOnTriggerListener .onGrabbed (this , OnTriggerListener .CENTER_HANDLE );
825+ }
798826 mOnTriggerListener .onGrabbedStateChange (this , mGrabbedState );
799827 }
800828 }
@@ -832,13 +860,45 @@ private void performInitialLayout(float centerX, float centerY) {
832860 moveHandleTo (centerX , centerY , false );
833861 }
834862
863+ private void setupGravity (int dx , int dy ) {
864+ final int layoutDirection = getResolvedLayoutDirection ();
865+ final int absoluteGravity = Gravity .getAbsoluteGravity (mGravity , layoutDirection );
866+
867+ switch (absoluteGravity & Gravity .HORIZONTAL_GRAVITY_MASK ) {
868+ case Gravity .LEFT :
869+ mHorizontalInset = 0 ;
870+ break ;
871+ case Gravity .RIGHT :
872+ mHorizontalInset = dx ;
873+ break ;
874+ case Gravity .CENTER_HORIZONTAL :
875+ default :
876+ mHorizontalInset = dx / 2 ;
877+ break ;
878+ }
879+ switch (absoluteGravity & Gravity .VERTICAL_GRAVITY_MASK ) {
880+ case Gravity .TOP :
881+ mVerticalInset = 0 ;
882+ break ;
883+ case Gravity .BOTTOM :
884+ mVerticalInset = dy ;
885+ break ;
886+ case Gravity .CENTER_VERTICAL :
887+ default :
888+ mVerticalInset = dy / 2 ;
889+ break ;
890+ }
891+ }
892+
835893 @ Override
836894 protected void onLayout (boolean changed , int left , int top , int right , int bottom ) {
837895 super .onLayout (changed , left , top , right , bottom );
838896 final int width = right - left ;
839897 final int height = bottom - top ;
840- float newWaveCenterX = mHorizontalOffset + Math .max (width , mOuterRing .getWidth () ) / 2 ;
841- float newWaveCenterY = mVerticalOffset + Math .max (height , mOuterRing .getHeight ()) / 2 ;
898+ float newWaveCenterX = mHorizontalOffset + mHorizontalInset
899+ + Math .max (width , mMaxTargetWidth + mOuterRing .getWidth ()) / 2 ;
900+ float newWaveCenterY = mVerticalOffset + mVerticalInset
901+ + Math .max (height , + mMaxTargetHeight + mOuterRing .getHeight ()) / 2 ;
842902 if (newWaveCenterX != mWaveCenterX || newWaveCenterY != mWaveCenterY ) {
843903 if (mWaveCenterX == 0 && mWaveCenterY == 0 ) {
844904 performInitialLayout (newWaveCenterX , newWaveCenterY );
@@ -848,9 +908,8 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
848908
849909 mOuterRing .setX (mWaveCenterX );
850910 mOuterRing .setY (Math .max (mWaveCenterY , mWaveCenterY ));
851-
852- updateTargetPositions ();
853911 }
912+ updateTargetPositions ();
854913 if (DEBUG ) dump ();
855914 }
856915
0 commit comments