77import android .content .Intent ;
88import android .content .IntentFilter ;
99import android .content .SharedPreferences ;
10+ import android .content .res .Configuration ;
1011import android .graphics .PixelFormat ;
12+ import android .graphics .Point ;
1113import android .os .Build ;
14+ import android .os .CountDownTimer ;
1215import android .os .IBinder ;
1316import android .preference .PreferenceManager ;
1417import android .support .annotation .Nullable ;
1720import android .util .DisplayMetrics ;
1821import android .view .Gravity ;
1922import android .view .LayoutInflater ;
23+ import android .view .MotionEvent ;
2024import android .view .View ;
2125import android .view .WindowManager ;
2226import android .view .animation .Animation ;
@@ -46,8 +50,14 @@ public class FloatingVolumeService extends Service implements FloatingViewListen
4650 private SeekBar mediaControl , ringerControl , alarmControl , voiceCallControl ;
4751 private static final String PREF_KEY_LAST_POSITION_X = "last_position_x" ;
4852 private static final String PREF_KEY_LAST_POSITION_Y = "last_position_y" ;
53+ private static final String PREF_KEY_LAST_POSITION_X_EXPANDED = "last_position_x_expanded" ;
54+ private static final String PREF_KEY_LAST_POSITION_Y_EXPANDED = "last_position_y_expanded" ;
4955 private BroadcastReceiver RingerModeReceiver ;
50- private boolean isDarkThemeEnabled ;
56+ private boolean isDarkThemeEnabled , isDisableStaticUiEnabled , isUseLastPosition , isBounceEnabled ;
57+ private int x_init_cord , y_init_cord , x_init_margin , y_init_margin ;
58+ private final Point szWindow = new Point ();
59+ private SharedPreferences .Editor editor ;
60+ private SharedPreferences sharedPref ;
5161
5262 @ Nullable
5363 @ Override
@@ -62,6 +72,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
6272 return START_STICKY ;
6373 }
6474
75+ sharedPref = PreferenceManager .getDefaultSharedPreferences (this );
6576 final DisplayMetrics metrics = new DisplayMetrics ();
6677 final WindowManager windowManager = (WindowManager ) getSystemService (Context .WINDOW_SERVICE );
6778 Objects .requireNonNull (windowManager ).getDefaultDisplay ().getMetrics (metrics );
@@ -70,7 +81,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
7081 iconView .setOnClickListener (new View .OnClickListener () {
7182 @ Override
7283 public void onClick (View v ) {
73- expandView (inflater );
84+ expandView (inflater , metrics );
7485 }
7586 });
7687
@@ -83,14 +94,17 @@ public void onClick(View v) {
8394 return START_REDELIVER_INTENT ;
8495 }
8596
86- private void expandView (LayoutInflater inflater ) {
97+ private void expandView (LayoutInflater inflater , DisplayMetrics displayMetrics ) {
8798 mWindowManager = (WindowManager ) getSystemService (WINDOW_SERVICE );
8899 audioManager = (AudioManager ) getSystemService (Context .AUDIO_SERVICE );
89100
90- isDarkThemeEnabled = PreferenceManager .getDefaultSharedPreferences (this )
91- .getBoolean ("enable_dark_mode_switch" ,false );
101+ isDarkThemeEnabled = sharedPref .getBoolean ("enable_dark_mode_switch" , false );
102+ isDisableStaticUiEnabled = sharedPref .getBoolean ("disable_fixed_ui" , false );
103+ isUseLastPosition = sharedPref .getBoolean ("settings_save_last_position" , false );
104+ isBounceEnabled = sharedPref .getBoolean ("enable_bounce_effect" , false );
92105
93- addFloatingWidgetView (inflater );
106+ addFloatingWidgetView (inflater , displayMetrics );
107+ if (isDisableStaticUiEnabled ) implementTouchListenerToFloatingWidgetView (this );
94108
95109 CardView expanded_card_view = mFloatingWidgetView .findViewById (R .id .expanded_card_view );
96110 expanded_card_view .setCardBackgroundColor (
@@ -142,7 +156,8 @@ private void expandView(LayoutInflater inflater) {
142156 }
143157
144158 @ SuppressLint ("InflateParams" )
145- private void addFloatingWidgetView (LayoutInflater inflater ) {
159+ private void addFloatingWidgetView (LayoutInflater inflater , DisplayMetrics displayMetrics ) {
160+ getWindowManagerDefaultDisplay ();
146161 mFloatingWidgetView = inflater .inflate (R .layout .floating_layout , null , false );
147162
148163 final WindowManager .LayoutParams params = new WindowManager .LayoutParams (
@@ -153,9 +168,21 @@ private void addFloatingWidgetView(LayoutInflater inflater) {
153168 WindowManager .LayoutParams .TYPE_APPLICATION_OVERLAY ,
154169 WindowManager .LayoutParams .FLAG_NOT_FOCUSABLE ,
155170 PixelFormat .TRANSLUCENT );
156- params .gravity = Gravity .CENTER ;
157- params .x = 0 ;
158- params .y = 0 ;
171+ if (isDisableStaticUiEnabled ) {
172+ params .gravity = Gravity .TOP | Gravity .START ;
173+ if (isUseLastPosition ) {
174+ params .x = sharedPref .getInt (PREF_KEY_LAST_POSITION_X_EXPANDED , 0 );
175+ params .y = sharedPref .getInt (PREF_KEY_LAST_POSITION_Y_EXPANDED , 0 );
176+ } else {
177+ int height = displayMetrics .heightPixels ;
178+ params .x = displayMetrics .widthPixels - mFloatingWidgetView .getWidth ();
179+ params .y = (height / 4 );
180+ }
181+ } else {
182+ params .gravity = Gravity .CENTER ;
183+ params .x = 0 ;
184+ params .y = 0 ;
185+ }
159186 params .windowAnimations = android .R .style .Animation_Dialog ;
160187
161188 mWindowManager .addView (mFloatingWidgetView , params );
@@ -193,16 +220,16 @@ private void implementVolumeFeatures() {
193220
194221 change_ringer_mode = mFloatingWidgetView .findViewById (R .id .imageViewModeSwitch );
195222 final Animation fab_open = AnimationUtils .loadAnimation (this , R .anim .fab_open_0_to_1 );
196- RingerModeReceiver =new BroadcastReceiver (){
223+ RingerModeReceiver = new BroadcastReceiver () {
197224 @ Override
198225 public void onReceive (Context context , Intent intent ) {
199226 change_ringer_mode .setImageResource (getCurrentRingerModeDrawable ());
200227 change_ringer_mode .startAnimation (fab_open );
201228 }
202229 };
203- IntentFilter filter = new IntentFilter (
230+ IntentFilter filter = new IntentFilter (
204231 AudioManager .RINGER_MODE_CHANGED_ACTION );
205- registerReceiver (RingerModeReceiver ,filter );
232+ registerReceiver (RingerModeReceiver , filter );
206233 change_ringer_mode .setOnClickListener (this );
207234 }
208235
@@ -324,7 +351,7 @@ public void onFinishFloatingView() {
324351 @ Override
325352 public void onTouchFinished (boolean isFinishing , int x , int y ) {
326353 if (!isFinishing ) {
327- final SharedPreferences . Editor editor = PreferenceManager .getDefaultSharedPreferences (this ).edit ();
354+ editor = PreferenceManager .getDefaultSharedPreferences (this ).edit ();
328355 editor .putInt (PREF_KEY_LAST_POSITION_X , x );
329356 editor .putInt (PREF_KEY_LAST_POSITION_Y , y );
330357 editor .apply ();
@@ -364,7 +391,6 @@ private FloatingViewManager.Options loadOptions(DisplayMetrics metrics) {
364391 final FloatingViewManager .Options options = new FloatingViewManager .Options ();
365392 final SharedPreferences sharedPref = PreferenceManager .getDefaultSharedPreferences (this );
366393
367- final boolean isUseLastPosition = sharedPref .getBoolean ("settings_save_last_position" , false );
368394 if (isUseLastPosition ) {
369395 final int defaultX = options .floatingViewX ;
370396 final int defaultY = options .floatingViewY ;
@@ -378,4 +404,151 @@ private FloatingViewManager.Options loadOptions(DisplayMetrics metrics) {
378404
379405 return options ;
380406 }
407+
408+ private void implementTouchListenerToFloatingWidgetView (final Context context ) {
409+ mFloatingWidgetView .findViewById (R .id .root_container ).setOnTouchListener (new View .OnTouchListener () {
410+ @ SuppressLint ("ClickableViewAccessibility" )
411+ @ Override
412+ public boolean onTouch (View v , MotionEvent event ) {
413+ WindowManager .LayoutParams layoutParams = (WindowManager .LayoutParams ) mFloatingWidgetView .getLayoutParams ();
414+
415+ int x_cord = (int ) event .getRawX ();
416+ int y_cord = (int ) event .getRawY ();
417+
418+ int x_cord_Destination , y_cord_Destination ;
419+
420+ switch (event .getAction ()) {
421+ case MotionEvent .ACTION_DOWN :
422+
423+ x_init_cord = x_cord ;
424+ y_init_cord = y_cord ;
425+
426+ x_init_margin = layoutParams .x ;
427+ y_init_margin = layoutParams .y ;
428+
429+ return true ;
430+ case MotionEvent .ACTION_UP :
431+ boolean isClicked = false ;
432+ int x_diff = x_cord - x_init_cord ;
433+ int y_diff = y_cord - y_init_cord ;
434+
435+ if (Math .abs (x_diff ) < 5 && Math .abs (y_diff ) < 5 ) isClicked = true ;
436+
437+ y_cord_Destination = y_init_margin + y_diff ;
438+
439+ int barHeight = getStatusBarHeight ();
440+ if (y_cord_Destination < 0 ) y_cord_Destination = 0 ;
441+ else if (y_cord_Destination + (mFloatingWidgetView .getHeight () + barHeight ) > szWindow .y ) {
442+ y_cord_Destination = szWindow .y - (mFloatingWidgetView .getHeight () + barHeight );
443+ }
444+
445+ layoutParams .y = y_cord_Destination ;
446+
447+ if (!isClicked ) resetPosition (x_cord );
448+
449+ return true ;
450+ case MotionEvent .ACTION_MOVE :
451+ int x_diff_move = x_cord - x_init_cord ;
452+ int y_diff_move = y_cord - y_init_cord ;
453+
454+ x_cord_Destination = x_init_margin + x_diff_move ;
455+ y_cord_Destination = y_init_margin + y_diff_move ;
456+
457+ layoutParams .x = x_cord_Destination ;
458+ layoutParams .y = y_cord_Destination ;
459+
460+ mWindowManager .updateViewLayout (mFloatingWidgetView , layoutParams );
461+ editor = PreferenceManager .getDefaultSharedPreferences (context ).edit ();
462+ editor .putInt (PREF_KEY_LAST_POSITION_X_EXPANDED , layoutParams .x );
463+ editor .putInt (PREF_KEY_LAST_POSITION_Y_EXPANDED , layoutParams .y );
464+ editor .apply ();
465+ return true ;
466+ }
467+ return false ;
468+ }
469+ });
470+ }
471+
472+ private void resetPosition (int x_cord_now ) {
473+ if (x_cord_now <= szWindow .x / 2 ) moveToLeft (x_cord_now );
474+ else moveToRight (x_cord_now );
475+ }
476+
477+ private void moveToLeft (final int current_x_cord ) {
478+ new CountDownTimer (500 , 5 ) {
479+ final WindowManager .LayoutParams mParams = (WindowManager .LayoutParams ) mFloatingWidgetView .getLayoutParams ();
480+
481+ public void onTick (long t ) {
482+ long step = (500 - t ) / 5 ;
483+
484+ mParams .x = 0 - (int ) (current_x_cord * current_x_cord * step );
485+
486+ if (isBounceEnabled )
487+ mParams .x = 0 - (int ) (double ) bounceValue (step , current_x_cord );
488+
489+ mWindowManager .updateViewLayout (mFloatingWidgetView , mParams );
490+ }
491+
492+ public void onFinish () {
493+ mParams .x = 0 ;
494+
495+ mWindowManager .updateViewLayout (mFloatingWidgetView , mParams );
496+ }
497+ }.start ();
498+ }
499+
500+ private void moveToRight (final int current_x_cord ) {
501+
502+ new CountDownTimer (500 , 5 ) {
503+ final WindowManager .LayoutParams mParams = (WindowManager .LayoutParams ) mFloatingWidgetView .getLayoutParams ();
504+
505+ public void onTick (long t ) {
506+ long step = (500 - t ) / 5 ;
507+
508+ mParams .x = (int ) (szWindow .x + (current_x_cord * current_x_cord * step ) - mFloatingWidgetView .getWidth ());
509+
510+ if (isBounceEnabled )
511+ mParams .x = szWindow .x + (int ) (double ) bounceValue (step , current_x_cord ) - mFloatingWidgetView .getWidth ();
512+
513+ mWindowManager .updateViewLayout (mFloatingWidgetView , mParams );
514+ }
515+
516+ public void onFinish () {
517+ mParams .x = szWindow .x - mFloatingWidgetView .getWidth ();
518+
519+ mWindowManager .updateViewLayout (mFloatingWidgetView , mParams );
520+ }
521+ }.start ();
522+ }
523+
524+ private int getStatusBarHeight () {
525+ return (int ) Math .ceil (25 * getApplicationContext ().getResources ().getDisplayMetrics ().density );
526+ }
527+
528+ private double bounceValue (long step , long scale ) {
529+ return scale * Math .exp (-0.055 * step ) * Math .cos (0.08 * step );
530+ }
531+
532+ @ Override
533+ public void onConfigurationChanged (Configuration newConfig ) {
534+ super .onConfigurationChanged (newConfig );
535+
536+ getWindowManagerDefaultDisplay ();
537+
538+ WindowManager .LayoutParams layoutParams = (WindowManager .LayoutParams ) mFloatingWidgetView .getLayoutParams ();
539+
540+ if (newConfig .orientation == Configuration .ORIENTATION_LANDSCAPE ) {
541+ if (layoutParams .y + (mFloatingWidgetView .getHeight () + getStatusBarHeight ()) > szWindow .y ) {
542+ layoutParams .y = szWindow .y - (mFloatingWidgetView .getHeight () + getStatusBarHeight ());
543+ mWindowManager .updateViewLayout (mFloatingWidgetView , layoutParams );
544+ }
545+ if (layoutParams .x != 0 && layoutParams .x < szWindow .x ) resetPosition (szWindow .x );
546+ } else if (newConfig .orientation == Configuration .ORIENTATION_PORTRAIT ) {
547+ if (layoutParams .x > szWindow .x ) resetPosition (szWindow .x );
548+ }
549+ }
550+
551+ private void getWindowManagerDefaultDisplay () {
552+ mWindowManager .getDefaultDisplay ().getSize (szWindow );
553+ }
381554}
0 commit comments