parent
0b4a19b2d0
commit
7d2e5a0e52
@ -1,81 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.app.Activity; |
|
||||||
import android.content.Context; |
|
||||||
import android.content.Intent; |
|
||||||
import android.net.Uri; |
|
||||||
import android.os.Build; |
|
||||||
import android.os.Bundle; |
|
||||||
import android.support.annotation.RequiresApi; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* 用于在内部自动申请权限 |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
|
|
||||||
public class FloatActivity extends Activity { |
|
||||||
|
|
||||||
private static List<PermissionListener> mPermissionListenerList; |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void onCreate(Bundle savedInstanceState) { |
|
||||||
super.onCreate(savedInstanceState); |
|
||||||
if (Build.VERSION.SDK_INT >= 23){ |
|
||||||
requestAlertWindowPermission(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@RequiresApi(api = 23) |
|
||||||
private void requestAlertWindowPermission() { |
|
||||||
Intent intent = new Intent("android.settings.action.MANAGE_OVERLAY_PERMISSION"); |
|
||||||
intent.setData(Uri.parse("package:" + getPackageName())); |
|
||||||
startActivityForResult(intent, 123); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(api = 23) |
|
||||||
@Override |
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
|
||||||
super.onActivityResult(requestCode, resultCode, data); |
|
||||||
if (Build.VERSION.SDK_INT >= 23){ |
|
||||||
//todo 用23以上编译即可出现canDrawOverlays
|
|
||||||
if (Util.hasPermission(this)) { |
|
||||||
mPermissionListener.onSuccess(); |
|
||||||
} else { |
|
||||||
mPermissionListener.onFail(); |
|
||||||
} |
|
||||||
} |
|
||||||
finish(); |
|
||||||
} |
|
||||||
|
|
||||||
static synchronized void request(Context context, PermissionListener permissionListener) { |
|
||||||
if (mPermissionListenerList == null) { |
|
||||||
mPermissionListenerList = new ArrayList<>(); |
|
||||||
mPermissionListener = new PermissionListener() { |
|
||||||
@Override |
|
||||||
public void onSuccess() { |
|
||||||
for (PermissionListener listener : mPermissionListenerList) { |
|
||||||
listener.onSuccess(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onFail() { |
|
||||||
for (PermissionListener listener : mPermissionListenerList) { |
|
||||||
listener.onFail(); |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
Intent intent = new Intent(context, FloatActivity.class); |
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
|
||||||
context.startActivity(intent); |
|
||||||
} |
|
||||||
mPermissionListenerList.add(permissionListener); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static PermissionListener mPermissionListener; |
|
||||||
} |
|
@ -1,114 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.app.Activity; |
|
||||||
import android.app.Application; |
|
||||||
import android.content.BroadcastReceiver; |
|
||||||
import android.content.Context; |
|
||||||
import android.content.Intent; |
|
||||||
import android.content.IntentFilter; |
|
||||||
import android.os.Bundle; |
|
||||||
import android.os.Handler; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 17-12-1. |
|
||||||
* 用于控制悬浮窗显示周期 |
|
||||||
* 使用了三种方法针对返回桌面时隐藏悬浮按钮 |
|
||||||
* 1.startCount计数,针对back到桌面可以及时隐藏 |
|
||||||
* 2.监听home键,从而及时隐藏 |
|
||||||
* 3.resumeCount计时,针对一些只执行onPause不执行onStop的奇葩情况 |
|
||||||
*/ |
|
||||||
|
|
||||||
class FloatLifecycle extends BroadcastReceiver implements Application.ActivityLifecycleCallbacks { |
|
||||||
|
|
||||||
private static final long delay = 300; |
|
||||||
private Handler mHandler; |
|
||||||
private Class[] activities; |
|
||||||
private boolean showFlag; |
|
||||||
private int resumeCount; |
|
||||||
private boolean appBackground; |
|
||||||
private LifecycleListener mLifecycleListener; |
|
||||||
|
|
||||||
|
|
||||||
FloatLifecycle(Context applicationContext, boolean showFlag, Class[] activities, LifecycleListener lifecycleListener) { |
|
||||||
this.showFlag = showFlag; |
|
||||||
this.activities = activities; |
|
||||||
mLifecycleListener = lifecycleListener; |
|
||||||
mHandler = new Handler(); |
|
||||||
((Application) applicationContext).registerActivityLifecycleCallbacks(this); |
|
||||||
applicationContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private boolean needShow(Activity activity) { |
|
||||||
if (activities == null) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
for (Class a : activities) { |
|
||||||
if (a.isInstance(activity)) { |
|
||||||
return showFlag; |
|
||||||
} |
|
||||||
} |
|
||||||
return !showFlag; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void onActivityResumed(Activity activity) { |
|
||||||
resumeCount++; |
|
||||||
if (needShow(activity)) { |
|
||||||
mLifecycleListener.onShow(); |
|
||||||
} |
|
||||||
|
|
||||||
if (appBackground) { |
|
||||||
appBackground = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onActivityPaused(Activity activity) { |
|
||||||
resumeCount--; |
|
||||||
mHandler.postDelayed(new Runnable() { |
|
||||||
@Override |
|
||||||
public void run() { |
|
||||||
if (resumeCount == 0) { |
|
||||||
appBackground = true; |
|
||||||
//mLifecycleListener.onPostHide();
|
|
||||||
} |
|
||||||
} |
|
||||||
}, delay); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onActivityStarted(Activity activity) { |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void onActivityStopped(Activity activity) { |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onReceive(Context context, Intent intent) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onActivityDestroyed(Activity activity) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -1,111 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.graphics.PixelFormat; |
|
||||||
import android.os.Build; |
|
||||||
import android.view.View; |
|
||||||
import android.view.WindowManager; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 17-11-14. |
|
||||||
* 7.1及以上需申请权限 |
|
||||||
*/ |
|
||||||
|
|
||||||
class FloatPhone extends FloatView { |
|
||||||
|
|
||||||
private final Context mContext; |
|
||||||
|
|
||||||
private final WindowManager mWindowManager; |
|
||||||
private final WindowManager.LayoutParams mLayoutParams; |
|
||||||
private View mView; |
|
||||||
private int mX, mY; |
|
||||||
|
|
||||||
FloatPhone(Context applicationContext) { |
|
||||||
mContext = applicationContext; |
|
||||||
mWindowManager = (WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE); |
|
||||||
mLayoutParams = new WindowManager.LayoutParams(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setSize(int width, int height) { |
|
||||||
mLayoutParams.width = width; |
|
||||||
mLayoutParams.height = height; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setView(View view) { |
|
||||||
int layout_type; |
|
||||||
layout_type = WindowManager.LayoutParams.TYPE_PHONE; |
|
||||||
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
|
||||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; |
|
||||||
mLayoutParams.type = layout_type; |
|
||||||
mLayoutParams.windowAnimations = 0; |
|
||||||
mView = view; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setGravity(int gravity, int xOffset, int yOffset) { |
|
||||||
mLayoutParams.gravity = gravity; |
|
||||||
mLayoutParams.x = mX = xOffset; |
|
||||||
mLayoutParams.y = mY = yOffset; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void init() { |
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
|
||||||
if (Util.hasPermission(mContext)) { |
|
||||||
mLayoutParams.format = PixelFormat.RGBA_8888; |
|
||||||
mWindowManager.addView(mView, mLayoutParams); |
|
||||||
} else { |
|
||||||
FloatActivity.request(mContext, new PermissionListener() { |
|
||||||
@Override |
|
||||||
public void onSuccess() { |
|
||||||
mLayoutParams.format = PixelFormat.RGBA_8888; |
|
||||||
mWindowManager.addView(mView, mLayoutParams); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onFail() { |
|
||||||
|
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void dismiss() { |
|
||||||
mWindowManager.removeView(mView); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void updateXY(int x, int y) { |
|
||||||
mLayoutParams.x = mX = x; |
|
||||||
mLayoutParams.y = mY = y; |
|
||||||
mWindowManager.updateViewLayout(mView, mLayoutParams); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
void updateX(int x) { |
|
||||||
mLayoutParams.x = mX = x; |
|
||||||
mWindowManager.updateViewLayout(mView, mLayoutParams); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
void updateY(int y) { |
|
||||||
mLayoutParams.y = mY = y; |
|
||||||
mWindowManager.updateViewLayout(mView, mLayoutParams); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
int getX() { |
|
||||||
return mX; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
int getY() { |
|
||||||
return mY; |
|
||||||
} |
|
||||||
} |
|
@ -1,64 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.util.AttributeSet; |
|
||||||
import android.view.Gravity; |
|
||||||
import android.view.ViewGroup; |
|
||||||
import android.widget.FrameLayout; |
|
||||||
import android.widget.VideoView; |
|
||||||
|
|
||||||
|
|
||||||
public class FloatPlayerView extends FrameLayout { |
|
||||||
|
|
||||||
private final static String VIDEO_PATH = "rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov"; |
|
||||||
// private final static String VIDEO_PATH = "storage/emulated/0/beyond.mp4";
|
|
||||||
|
|
||||||
private VideoView mPlayer; |
|
||||||
|
|
||||||
public FloatPlayerView(Context context) { |
|
||||||
super(context); |
|
||||||
init(context); |
|
||||||
} |
|
||||||
|
|
||||||
public FloatPlayerView(Context context, AttributeSet attrs) { |
|
||||||
super(context, attrs); |
|
||||||
init(context); |
|
||||||
} |
|
||||||
|
|
||||||
public FloatPlayerView(Context context, AttributeSet attrs, int defStyleAttr) { |
|
||||||
super(context, attrs, defStyleAttr); |
|
||||||
init(context); |
|
||||||
} |
|
||||||
|
|
||||||
private void init(Context context) { |
|
||||||
mPlayer = new VideoView(context); |
|
||||||
|
|
||||||
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); |
|
||||||
layoutParams.gravity = Gravity.CENTER; |
|
||||||
addView(mPlayer, layoutParams); |
|
||||||
|
|
||||||
mPlayer.setVideoPath(VIDEO_PATH); |
|
||||||
mPlayer.requestFocus(); |
|
||||||
mPlayer.start(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void onPause() { |
|
||||||
if (mPlayer != null){ |
|
||||||
mPlayer.pause(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void onResume() { |
|
||||||
if (mPlayer != null){ |
|
||||||
mPlayer.resume(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void onDestroy(){ |
|
||||||
if (mPlayer != null){ |
|
||||||
mPlayer.stopPlayback(); |
|
||||||
mPlayer = null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,96 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.view.View; |
|
||||||
import android.view.WindowManager; |
|
||||||
import android.widget.Toast; |
|
||||||
|
|
||||||
import java.lang.reflect.Field; |
|
||||||
import java.lang.reflect.Method; |
|
||||||
|
|
||||||
/** |
|
||||||
* 自定义 toast 方式,无需申请权限 |
|
||||||
*/ |
|
||||||
|
|
||||||
class FloatToast extends FloatView { |
|
||||||
|
|
||||||
|
|
||||||
private Toast toast; |
|
||||||
|
|
||||||
private Object mTN; |
|
||||||
private Method show; |
|
||||||
private Method hide; |
|
||||||
|
|
||||||
private int mWidth; |
|
||||||
private int mHeight; |
|
||||||
|
|
||||||
|
|
||||||
FloatToast(Context applicationContext) { |
|
||||||
toast = new Toast(applicationContext); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setSize(int width, int height) { |
|
||||||
mWidth = width; |
|
||||||
mHeight = height; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setView(View view) { |
|
||||||
toast.setView(view); |
|
||||||
initTN(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setGravity(int gravity, int xOffset, int yOffset) { |
|
||||||
toast.setGravity(gravity, xOffset, yOffset); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void init() { |
|
||||||
try { |
|
||||||
show.invoke(mTN); |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void dismiss() { |
|
||||||
try { |
|
||||||
hide.invoke(mTN); |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private void initTN() { |
|
||||||
try { |
|
||||||
//todo android P test
|
|
||||||
Field tnField = toast.getClass().getDeclaredField("mTN"); |
|
||||||
tnField.setAccessible(true); |
|
||||||
mTN = tnField.get(toast); |
|
||||||
show = mTN.getClass().getMethod("show"); |
|
||||||
hide = mTN.getClass().getMethod("hide"); |
|
||||||
|
|
||||||
Field tnParamsField = mTN.getClass().getDeclaredField("mParams"); |
|
||||||
tnParamsField.setAccessible(true); |
|
||||||
WindowManager.LayoutParams params = (WindowManager.LayoutParams) tnParamsField.get(mTN); |
|
||||||
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
|
||||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; |
|
||||||
params.width = mWidth; |
|
||||||
params.height = mHeight; |
|
||||||
params.windowAnimations = 0; |
|
||||||
Field tnNextViewField = mTN.getClass().getDeclaredField("mNextView"); |
|
||||||
tnNextViewField.setAccessible(true); |
|
||||||
tnNextViewField.set(mTN, toast.getView()); |
|
||||||
|
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -1,38 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.view.View; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 17-11-14. |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
|
|
||||||
abstract class FloatView { |
|
||||||
|
|
||||||
abstract void setSize(int width, int height); |
|
||||||
|
|
||||||
abstract void setView(View view); |
|
||||||
|
|
||||||
abstract void setGravity(int gravity, int xOffset, int yOffset); |
|
||||||
|
|
||||||
abstract void init(); |
|
||||||
|
|
||||||
abstract void dismiss(); |
|
||||||
|
|
||||||
void updateXY(int x, int y) { |
|
||||||
} |
|
||||||
|
|
||||||
void updateX(int x) { |
|
||||||
} |
|
||||||
|
|
||||||
void updateY(int y) { |
|
||||||
} |
|
||||||
|
|
||||||
int getX() { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
int getY() { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
} |
|
@ -1,30 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.view.View; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 2017/12/22. |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
|
|
||||||
public abstract class IFloatWindow { |
|
||||||
public abstract void show(); |
|
||||||
|
|
||||||
public abstract void hide(); |
|
||||||
|
|
||||||
public abstract int getX(); |
|
||||||
|
|
||||||
public abstract int getY(); |
|
||||||
|
|
||||||
public abstract void updateX(int x); |
|
||||||
|
|
||||||
public abstract void updateX(@Screen.screenType int screenType,float ratio); |
|
||||||
|
|
||||||
public abstract void updateY(int y); |
|
||||||
|
|
||||||
public abstract void updateY(@Screen.screenType int screenType,float ratio); |
|
||||||
|
|
||||||
public abstract View getView(); |
|
||||||
|
|
||||||
abstract void dismiss(); |
|
||||||
} |
|
@ -1,248 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.animation.Animator; |
|
||||||
import android.animation.AnimatorListenerAdapter; |
|
||||||
import android.animation.ObjectAnimator; |
|
||||||
import android.animation.PropertyValuesHolder; |
|
||||||
import android.animation.TimeInterpolator; |
|
||||||
import android.animation.ValueAnimator; |
|
||||||
import android.os.Build; |
|
||||||
import android.view.MotionEvent; |
|
||||||
import android.view.View; |
|
||||||
import android.view.animation.DecelerateInterpolator; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 2017/12/22. |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
|
|
||||||
public class IFloatWindowImpl extends IFloatWindow { |
|
||||||
|
|
||||||
|
|
||||||
private FloatWindow.WindowBuilder mB; |
|
||||||
private FloatView mFloatView; |
|
||||||
private boolean isShow; |
|
||||||
private boolean once = true; |
|
||||||
private ValueAnimator mAnimator; |
|
||||||
private TimeInterpolator mDecelerateInterpolator; |
|
||||||
|
|
||||||
IFloatWindowImpl(FloatWindow.WindowBuilder b) { |
|
||||||
mB = b; |
|
||||||
if (mB.mMoveType == MoveType.fixed) { |
|
||||||
if (Build.VERSION.SDK_INT >=25) { |
|
||||||
mFloatView = new FloatPhone(b.mApplicationContext); |
|
||||||
} else { |
|
||||||
mFloatView = new FloatToast(b.mApplicationContext); |
|
||||||
} |
|
||||||
} else { |
|
||||||
mFloatView = new FloatPhone(b.mApplicationContext); |
|
||||||
initTouchEvent(); |
|
||||||
} |
|
||||||
mFloatView.setSize(mB.mWidth, mB.mHeight); |
|
||||||
mFloatView.setGravity(mB.gravity, mB.xOffset, mB.yOffset); |
|
||||||
mFloatView.setView(mB.mView); |
|
||||||
new FloatLifecycle(mB.mApplicationContext, mB.mShow, mB.mActivities, new LifecycleListener() { |
|
||||||
@Override |
|
||||||
public void onShow() { |
|
||||||
show(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onHide() { |
|
||||||
hide(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onPostHide() { |
|
||||||
postHide(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void show() { |
|
||||||
if (once) { |
|
||||||
mFloatView.init(); |
|
||||||
once = false; |
|
||||||
isShow = true; |
|
||||||
} else { |
|
||||||
if (isShow) return; |
|
||||||
getView().setVisibility(View.VISIBLE); |
|
||||||
isShow = true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void hide() { |
|
||||||
if (once || !isShow) return; |
|
||||||
getView().setVisibility(View.INVISIBLE); |
|
||||||
isShow = false; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
void dismiss() { |
|
||||||
mFloatView.dismiss(); |
|
||||||
isShow = false; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void updateX(int x) { |
|
||||||
checkMoveType(); |
|
||||||
mB.xOffset = x; |
|
||||||
mFloatView.updateX(x); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void updateY(int y) { |
|
||||||
checkMoveType(); |
|
||||||
mB.yOffset = y; |
|
||||||
mFloatView.updateY(y); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void updateX(int screenType, float ratio) { |
|
||||||
checkMoveType(); |
|
||||||
mB.xOffset = (int) ((screenType == Screen.width ? |
|
||||||
Util.getScreenWidth(mB.mApplicationContext) : |
|
||||||
Util.getScreenHeight(mB.mApplicationContext)) * ratio); |
|
||||||
mFloatView.updateX(mB.xOffset); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void updateY(int screenType, float ratio) { |
|
||||||
checkMoveType(); |
|
||||||
mB.yOffset = (int) ((screenType == Screen.width ? |
|
||||||
Util.getScreenWidth(mB.mApplicationContext) : |
|
||||||
Util.getScreenHeight(mB.mApplicationContext)) * ratio); |
|
||||||
mFloatView.updateY(mB.yOffset); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int getX() { |
|
||||||
return mFloatView.getX(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int getY() { |
|
||||||
return mFloatView.getY(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public View getView() { |
|
||||||
return mB.mView; |
|
||||||
} |
|
||||||
|
|
||||||
void postHide() { |
|
||||||
if (once || !isShow) return; |
|
||||||
getView().post(new Runnable() { |
|
||||||
@Override |
|
||||||
public void run() { |
|
||||||
getView().setVisibility(View.INVISIBLE); |
|
||||||
} |
|
||||||
}); |
|
||||||
isShow = false; |
|
||||||
} |
|
||||||
|
|
||||||
private void checkMoveType() { |
|
||||||
if (mB.mMoveType == MoveType.fixed) { |
|
||||||
throw new IllegalArgumentException("FloatWindow of this tag is not allowed to move!"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void initTouchEvent() { |
|
||||||
switch (mB.mMoveType) { |
|
||||||
case MoveType.free: |
|
||||||
break; |
|
||||||
default: |
|
||||||
getView().setOnTouchListener(new View.OnTouchListener() { |
|
||||||
float lastX, lastY, changeX, changeY; |
|
||||||
int newX, newY; |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean onTouch(View v, MotionEvent event) { |
|
||||||
|
|
||||||
switch (event.getAction()) { |
|
||||||
case MotionEvent.ACTION_DOWN: |
|
||||||
lastX = event.getRawX(); |
|
||||||
lastY = event.getRawY(); |
|
||||||
cancelAnimator(); |
|
||||||
break; |
|
||||||
case MotionEvent.ACTION_MOVE: |
|
||||||
changeX = event.getRawX() - lastX; |
|
||||||
changeY = event.getRawY() - lastY; |
|
||||||
newX = (int) (mFloatView.getX() + changeX); |
|
||||||
newY = (int) (mFloatView.getY() + changeY); |
|
||||||
mFloatView.updateXY(newX, newY); |
|
||||||
lastX = event.getRawX(); |
|
||||||
lastY = event.getRawY(); |
|
||||||
break; |
|
||||||
case MotionEvent.ACTION_UP: |
|
||||||
switch (mB.mMoveType) { |
|
||||||
case MoveType.slide: |
|
||||||
int startX = mFloatView.getX(); |
|
||||||
int endX = (startX * 2 + v.getWidth() > |
|
||||||
Util.getScreenWidth(mB.mApplicationContext)) ? |
|
||||||
Util.getScreenWidth(mB.mApplicationContext) - v.getWidth() : 0; |
|
||||||
mAnimator = ObjectAnimator.ofInt(startX, endX); |
|
||||||
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
|
||||||
@Override |
|
||||||
public void onAnimationUpdate(ValueAnimator animation) { |
|
||||||
int x = (int) animation.getAnimatedValue(); |
|
||||||
mFloatView.updateX(x); |
|
||||||
} |
|
||||||
}); |
|
||||||
startAnimator(); |
|
||||||
break; |
|
||||||
case MoveType.back: |
|
||||||
PropertyValuesHolder pvhX = PropertyValuesHolder.ofInt("x", mFloatView.getX(), mB.xOffset); |
|
||||||
PropertyValuesHolder pvhY = PropertyValuesHolder.ofInt("y", mFloatView.getY(), mB.yOffset); |
|
||||||
mAnimator = ObjectAnimator.ofPropertyValuesHolder(pvhX, pvhY); |
|
||||||
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
|
||||||
@Override |
|
||||||
public void onAnimationUpdate(ValueAnimator animation) { |
|
||||||
int x = (int) animation.getAnimatedValue("x"); |
|
||||||
int y = (int) animation.getAnimatedValue("y"); |
|
||||||
mFloatView.updateXY(x, y); |
|
||||||
} |
|
||||||
}); |
|
||||||
startAnimator(); |
|
||||||
break; |
|
||||||
} |
|
||||||
break; |
|
||||||
|
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void startAnimator() { |
|
||||||
if (mB.mInterpolator == null) { |
|
||||||
if (mDecelerateInterpolator == null) { |
|
||||||
mDecelerateInterpolator = new DecelerateInterpolator(); |
|
||||||
} |
|
||||||
mB.mInterpolator = mDecelerateInterpolator; |
|
||||||
} |
|
||||||
mAnimator.setInterpolator(mB.mInterpolator); |
|
||||||
mAnimator.addListener(new AnimatorListenerAdapter() { |
|
||||||
@Override |
|
||||||
public void onAnimationEnd(Animator animation) { |
|
||||||
mAnimator.removeAllUpdateListeners(); |
|
||||||
mAnimator.removeAllListeners(); |
|
||||||
mAnimator = null; |
|
||||||
} |
|
||||||
}); |
|
||||||
mAnimator.setDuration(mB.mDuration).start(); |
|
||||||
} |
|
||||||
|
|
||||||
private void cancelAnimator() { |
|
||||||
if (mAnimator != null && mAnimator.isRunning()) { |
|
||||||
mAnimator.cancel(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,15 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 2017/12/22. |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
|
|
||||||
interface LifecycleListener { |
|
||||||
|
|
||||||
void onShow(); |
|
||||||
|
|
||||||
void onHide(); |
|
||||||
|
|
||||||
void onPostHide(); |
|
||||||
} |
|
@ -1,24 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.support.annotation.IntDef; |
|
||||||
|
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 2017/12/22. |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
|
|
||||||
public class MoveType { |
|
||||||
static final int fixed = 0; |
|
||||||
public static final int free = 1; |
|
||||||
public static final int active = 2; |
|
||||||
public static final int slide = 3; |
|
||||||
public static final int back = 4; |
|
||||||
|
|
||||||
@IntDef({fixed, free, active, slide, back}) |
|
||||||
@Retention(RetentionPolicy.SOURCE) |
|
||||||
@interface MOVE_TYPE { |
|
||||||
} |
|
||||||
} |
|
@ -1,11 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 2017/11/14. |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
interface PermissionListener { |
|
||||||
void onSuccess(); |
|
||||||
|
|
||||||
void onFail(); |
|
||||||
} |
|
@ -1,21 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.support.annotation.IntDef; |
|
||||||
|
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 2017/12/23. |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
|
|
||||||
public class Screen { |
|
||||||
public static final int width = 0; |
|
||||||
public static final int height = 1; |
|
||||||
|
|
||||||
@IntDef({width, height}) |
|
||||||
@Retention(RetentionPolicy.SOURCE) |
|
||||||
@interface screenType { |
|
||||||
} |
|
||||||
} |
|
@ -1,50 +0,0 @@ |
|||||||
package com.frank.ffmpeg.floating; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.graphics.Point; |
|
||||||
import android.os.Build; |
|
||||||
import android.provider.Settings; |
|
||||||
import android.support.annotation.RequiresApi; |
|
||||||
import android.view.LayoutInflater; |
|
||||||
import android.view.View; |
|
||||||
import android.view.WindowManager; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by yhao on 2017/12/22. |
|
||||||
* https://github.com/yhaolpz
|
|
||||||
*/ |
|
||||||
|
|
||||||
public class Util { |
|
||||||
|
|
||||||
|
|
||||||
static View inflate(Context applicationContext, int layoutId) { |
|
||||||
LayoutInflater inflate = (LayoutInflater) applicationContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
|
||||||
return inflate.inflate(layoutId, null); |
|
||||||
} |
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M) |
|
||||||
public static boolean hasPermission(Context context) { |
|
||||||
return Settings.canDrawOverlays(context); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static Point sPoint; |
|
||||||
|
|
||||||
static int getScreenWidth(Context context) { |
|
||||||
if (sPoint == null) { |
|
||||||
sPoint = new Point(); |
|
||||||
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); |
|
||||||
wm.getDefaultDisplay().getSize(sPoint); |
|
||||||
} |
|
||||||
return sPoint.x; |
|
||||||
} |
|
||||||
|
|
||||||
static int getScreenHeight(Context context) { |
|
||||||
if (sPoint == null) { |
|
||||||
sPoint = new Point(); |
|
||||||
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); |
|
||||||
wm.getDefaultDisplay().getSize(sPoint); |
|
||||||
} |
|
||||||
return sPoint.y; |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue