Skip to content

Instantly share code, notes, and snippets.

@vedhavyas
Created April 10, 2016 12:07
Show Gist options
  • Save vedhavyas/b6a97eed865433abb8e982bf865f9f15 to your computer and use it in GitHub Desktop.
Save vedhavyas/b6a97eed865433abb8e982bf865f9f15 to your computer and use it in GitHub Desktop.
Android Floating label
package com.instamojo.mink.services;
import android.animation.ValueAnimator;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.os.IBinder;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import com.instamojo.mink.R;
import com.instamojo.mink.helpers.Logger;
public class FloatingService extends Service {
WindowManager.LayoutParams params;
private WindowManager windowManager;
private ImageView floatingView;
private Point defaultSize;
public FloatingService() {
}
public static void startService(Context context) {
Intent intent = new Intent(context, FloatingService.class);
context.startService(intent);
}
@Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
defaultSize = new Point();
windowManager.getDefaultDisplay().getSize(defaultSize);
floatingView = new ImageView(this);
floatingView.setImageResource(R.drawable.ic_mink_icon);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PRIORITY_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.START;
params.x = defaultSize.x - floatingView.getWidth();
params.y = 0;
floatingView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Logger.log("clicked");
}
});
floatingView.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
private long dropTime;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dropTime = System.currentTimeMillis();
initialX = params.x;
initialY = params.y;
if (params.x > defaultSize.x - floatingView.getWidth()) {
initialX = defaultSize.x - floatingView.getWidth();
}
if (params.x < 0) {
initialX = 0;
}
if (params.y > defaultSize.y / 2 - floatingView.getHeight() / 2) {
initialY = defaultSize.y / 2 - floatingView.getHeight() / 2;
}
if (params.y < -defaultSize.y / 2 + floatingView.getHeight() / 2) {
initialY = -defaultSize.y / 2 + floatingView.getHeight() / 2;
}
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
if (System.currentTimeMillis() - dropTime < 200) {
floatingView.performClick();
}
int finalX;
if (params.x + floatingView.getWidth() / 2 >= defaultSize.x / 2) {
finalX = defaultSize.x - floatingView.getWidth();
} else {
finalX = 0;
}
overlayAnimation(floatingView, params.x, finalX);
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX
+ (int) (event.getRawX() - initialTouchX);
params.y = initialY
+ (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(floatingView, params);
return true;
}
return false;
}
});
windowManager.addView(floatingView, params);
}
private void overlayAnimation(final View view2animate, int viewX, int endX) {
ValueAnimator translateLeft = ValueAnimator.ofInt(viewX, endX);
translateLeft.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params.x = (Integer) valueAnimator.getAnimatedValue();
windowManager.updateViewLayout(view2animate, params);
}
});
translateLeft.setDuration(200);
translateLeft.start();
}
@Override
public void onDestroy() {
if (floatingView != null) {
windowManager.removeView(floatingView);
}
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
//Permissions in Manifest
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment