Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_26386469
GSYVideoPlayer
提交
f82d7d73
G
GSYVideoPlayer
项目概览
qq_26386469
/
GSYVideoPlayer
与 Fork 源项目一致
从无法访问的项目Fork
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
GSYVideoPlayer
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
f82d7d73
编写于
12月 25, 2017
作者:
G
guoshuyu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
增加桌面悬浮窗的demo适配
上级
0ffa7eba
变更
27
隐藏空白更改
内联
并排
Showing
27 changed file
with
1567 addition
and
7 deletion
+1567
-7
app/build.gradle
app/build.gradle
+2
-2
app/src/main/AndroidManifest.xml
app/src/main/AndroidManifest.xml
+16
-2
app/src/main/java/com/example/gsyvideoplayer/EmptyActivity.java
...c/main/java/com/example/gsyvideoplayer/EmptyActivity.java
+28
-0
app/src/main/java/com/example/gsyvideoplayer/MainActivity.java
...rc/main/java/com/example/gsyvideoplayer/MainActivity.java
+5
-2
app/src/main/java/com/example/gsyvideoplayer/WindowActivity.java
.../main/java/com/example/gsyvideoplayer/WindowActivity.java
+105
-0
app/src/main/java/com/example/gsyvideoplayer/utils/JumpUtils.java
...main/java/com/example/gsyvideoplayer/utils/JumpUtils.java
+11
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatActivity.java
...example/gsyvideoplayer/utils/floatUtil/FloatActivity.java
+82
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatLifecycle.java
...xample/gsyvideoplayer/utils/floatUtil/FloatLifecycle.java
+129
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatPhone.java
...om/example/gsyvideoplayer/utils/floatUtil/FloatPhone.java
+106
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatToast.java
...om/example/gsyvideoplayer/utils/floatUtil/FloatToast.java
+95
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatView.java
...com/example/gsyvideoplayer/utils/floatUtil/FloatView.java
+38
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatWindow.java
...m/example/gsyvideoplayer/utils/floatUtil/FloatWindow.java
+189
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/IFloatWindow.java
.../example/gsyvideoplayer/utils/floatUtil/IFloatWindow.java
+30
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/IFloatWindowImpl.java
...mple/gsyvideoplayer/utils/floatUtil/IFloatWindowImpl.java
+253
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/LifecycleListener.java
...ple/gsyvideoplayer/utils/floatUtil/LifecycleListener.java
+15
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/MoveType.java
.../com/example/gsyvideoplayer/utils/floatUtil/MoveType.java
+24
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/PermissionListener.java
...le/gsyvideoplayer/utils/floatUtil/PermissionListener.java
+11
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/Screen.java
...va/com/example/gsyvideoplayer/utils/floatUtil/Screen.java
+21
-0
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/Util.java
...java/com/example/gsyvideoplayer/utils/floatUtil/Util.java
+57
-0
app/src/main/java/com/example/gsyvideoplayer/video/FloatingVideo.java
.../java/com/example/gsyvideoplayer/video/FloatingVideo.java
+188
-0
app/src/main/java/com/example/gsyvideoplayer/view/FloatPlayerView.java
...java/com/example/gsyvideoplayer/view/FloatPlayerView.java
+74
-0
app/src/main/res/layout/activity_empty.xml
app/src/main/res/layout/activity_empty.xml
+12
-0
app/src/main/res/layout/activity_main.xml
app/src/main/res/layout/activity_main.xml
+7
-0
app/src/main/res/layout/activity_window.xml
app/src/main/res/layout/activity_window.xml
+28
-0
app/src/main/res/layout/layout_floating_play.xml
app/src/main/res/layout/layout_floating_play.xml
+14
-0
app/src/main/res/layout/layout_floating_video.xml
app/src/main/res/layout/layout_floating_video.xml
+24
-0
dependencies.gradle
dependencies.gradle
+3
-1
未找到文件。
app/build.gradle
浏览文件 @
f82d7d73
...
...
@@ -52,6 +52,7 @@ dependencies {
def
androidDependencies
=
rootProject
.
ext
.
androidDependencies
def
dataDependencies
=
rootProject
.
ext
.
dataDependencies
annotationProcessor
viewDependencies
.
apt_butterKnife
//debugCompile dataDependencies.leakcanary
compile
viewDependencies
.
butterKnife
compile
androidDependencies
.
recyclerView
compile
viewDependencies
.
DanmakuFlameMaster
...
...
@@ -62,9 +63,8 @@ dependencies {
compile
viewDependencies
.
glideProcessor
compile
androidDependencies
.
support_v4
compile
androidDependencies
.
design
//debugCompile dataDependencies.leakcanary
compile
project
(
':gsyVideoPlayer'
)
compile
project
(
':gsyVideoPlayer'
)
//jcenter
//compile "com.shuyu:GSYVideoPlayer:$gsyVideoVersion"
...
...
app/src/main/AndroidManifest.xml
浏览文件 @
f82d7d73
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
package=
"com.example.gsyvideoplayer"
>
<!-- 请求访问网络状态 -->
...
...
@@ -8,7 +9,7 @@
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.SYSTEM_ALERT_WINDOW"
/>
<uses-permission
android:name=
"android.permission.WRITE_SETTINGS"
/>
<application
...
...
@@ -103,8 +104,21 @@
android:name=
".ScrollingActivity"
android:configChanges=
"orientation|keyboardHidden|screenSize"
android:label=
"@string/title_activity_scrolling"
android:theme=
"@style/AppTheme.NoActionBar"
android:screenOrientation=
"portrait"
android:theme=
"@style/AppTheme.NoActionBar"
/>
<activity
android:name=
".WindowActivity"
android:configChanges=
"orientation|keyboardHidden|screenSize"
android:screenOrientation=
"portrait"
/>
<activity
android:name=
".EmptyActivity"
android:configChanges=
"orientation|keyboardHidden|screenSize"
android:screenOrientation=
"portrait"
/>
<activity
android:name=
".utils.floatUtil.FloatActivity"
android:configChanges=
"orientation|keyboardHidden|screenSize"
android:screenOrientation=
"portrait"
/>
</application>
</manifest>
\ No newline at end of file
app/src/main/java/com/example/gsyvideoplayer/EmptyActivity.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer
;
import
android.content.Intent
;
import
android.os.Bundle
;
import
android.support.v7.app.AppCompatActivity
;
import
android.widget.Button
;
import
butterknife.BindView
;
import
butterknife.ButterKnife
;
import
butterknife.OnClick
;
public
class
EmptyActivity
extends
AppCompatActivity
{
@BindView
(
R
.
id
.
jump_other
)
Button
jumpOther
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
activity_empty
);
ButterKnife
.
bind
(
this
);
}
@OnClick
(
R
.
id
.
jump_other
)
public
void
onViewClicked
()
{
startActivity
(
new
Intent
(
this
,
EmptyActivity
.
class
));
}
}
app/src/main/java/com/example/gsyvideoplayer/MainActivity.java
浏览文件 @
f82d7d73
...
...
@@ -30,7 +30,7 @@ public class MainActivity extends AppCompatActivity {
}
@OnClick
({
R
.
id
.
open_btn
,
R
.
id
.
list_btn
,
R
.
id
.
list_btn_2
,
R
.
id
.
list_detail
,
R
.
id
.
clear_cache
,
R
.
id
.
recycler
,
R
.
id
.
recycler_2
,
R
.
id
.
list_detail_list
,
R
.
id
.
web_detail
,
R
.
id
.
danmaku_video
,
R
.
id
.
fragment_video
,
R
.
id
.
more_type
,
R
.
id
.
input_type
,
R
.
id
.
open_btn_empty
,
R
.
id
.
open_control
,
R
.
id
.
open_filter
,
R
.
id
.
open_btn_pick
,
R
.
id
.
open_btn_auto
,
R
.
id
.
open_scroll
})
R
.
id
.
more_type
,
R
.
id
.
input_type
,
R
.
id
.
open_btn_empty
,
R
.
id
.
open_control
,
R
.
id
.
open_filter
,
R
.
id
.
open_btn_pick
,
R
.
id
.
open_btn_auto
,
R
.
id
.
open_scroll
,
R
.
id
.
open_window
})
public
void
onClick
(
View
view
)
{
switch
(
view
.
getId
())
{
case
R
.
id
.
open_btn
:
...
...
@@ -101,7 +101,10 @@ public class MainActivity extends AppCompatActivity {
//列表自动播放
JumpUtils
.
goToScrollDetailPlayer
(
this
);
break
;
case
R
.
id
.
open_window
:
//多窗体下的悬浮窗
JumpUtils
.
goToScrollWindow
(
this
);
break
;
case
R
.
id
.
clear_cache
:
//清理缓存
GSYVideoManager
.
clearAllDefaultCache
(
MainActivity
.
this
);
...
...
app/src/main/java/com/example/gsyvideoplayer/WindowActivity.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.support.annotation.RequiresApi
;
import
android.support.v7.app.AppCompatActivity
;
import
android.view.View
;
import
android.view.animation.BounceInterpolator
;
import
android.widget.Button
;
import
com.example.gsyvideoplayer.utils.floatUtil.FloatWindow
;
import
com.example.gsyvideoplayer.utils.floatUtil.MoveType
;
import
com.example.gsyvideoplayer.utils.floatUtil.Screen
;
import
com.example.gsyvideoplayer.utils.floatUtil.Util
;
import
com.example.gsyvideoplayer.view.FloatPlayerView
;
import
com.shuyu.gsyvideoplayer.GSYVideoManager
;
import
butterknife.BindView
;
import
butterknife.ButterKnife
;
import
butterknife.OnClick
;
/**
* 多窗体下的悬浮窗页面
*/
public
class
WindowActivity
extends
AppCompatActivity
{
@BindView
(
R
.
id
.
start_window
)
Button
startWindow
;
@BindView
(
R
.
id
.
jump_other
)
Button
jumpOther
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
activity_window
);
ButterKnife
.
bind
(
this
);
if
(
Build
.
VERSION
.
SDK_INT
>=
23
)
{
if
(!
Util
.
hasPermission
(
this
))
{
requestAlertWindowPermission
();
}
}
}
@Override
protected
void
onDestroy
()
{
super
.
onDestroy
();
GSYVideoManager
.
instance
().
releaseMediaPlayer
();
/**
* 这里在返回主页的时候销毁了,因为不想和DEMO中其他页面冲突
*/
FloatWindow
.
destroy
();
}
@RequiresApi
(
api
=
23
)
private
void
requestAlertWindowPermission
()
{
Intent
intent
=
new
Intent
(
"android.settings.action.MANAGE_OVERLAY_PERMISSION"
);
intent
.
setData
(
Uri
.
parse
(
"package:"
+
getPackageName
()));
startActivityForResult
(
intent
,
1
);
}
@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
))
{
}
else
{
this
.
finish
();
}
}
}
@OnClick
({
R
.
id
.
start_window
,
R
.
id
.
jump_other
})
public
void
onViewClicked
(
View
view
)
{
switch
(
view
.
getId
())
{
case
R
.
id
.
start_window
:
if
(
FloatWindow
.
get
()
!=
null
)
{
return
;
}
FloatPlayerView
floatPlayerView
=
new
FloatPlayerView
(
getApplicationContext
());
FloatWindow
.
with
(
getApplicationContext
())
.
setView
(
floatPlayerView
)
.
setWidth
(
Screen
.
width
,
0.4f
)
.
setHeight
(
Screen
.
width
,
0.4f
)
.
setX
(
Screen
.
width
,
0.8f
)
.
setY
(
Screen
.
height
,
0.3f
)
.
setMoveType
(
MoveType
.
slide
)
.
setFilter
(
false
)
.
setMoveStyle
(
500
,
new
BounceInterpolator
())
.
build
();
FloatWindow
.
get
().
show
();
break
;
case
R
.
id
.
jump_other
:
startActivity
(
new
Intent
(
this
,
EmptyActivity
.
class
));
break
;
}
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/JumpUtils.java
浏览文件 @
f82d7d73
...
...
@@ -26,6 +26,7 @@ import com.example.gsyvideoplayer.RecyclerView2Activity;
import
com.example.gsyvideoplayer.RecyclerViewActivity
;
import
com.example.gsyvideoplayer.ScrollingActivity
;
import
com.example.gsyvideoplayer.WebDetailActivity
;
import
com.example.gsyvideoplayer.WindowActivity
;
/**
* Created by shuyu on 2016/11/11.
...
...
@@ -168,6 +169,16 @@ public class JumpUtils {
activity
.
startActivity
(
intent
);
}
/**
* 跳转到详情播放
*
* @param activity
*/
public
static
void
goToScrollWindow
(
Activity
activity
)
{
Intent
intent
=
new
Intent
(
activity
,
WindowActivity
.
class
);
activity
.
startActivity
(
intent
);
}
/**
* 跳转到详情播放
*
...
...
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatActivity.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
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.provider.Settings
;
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
,
1
);
}
@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
;
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatLifecycle.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
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
String
SYSTEM_DIALOG_REASON_KEY
=
"reason"
;
private
static
final
String
SYSTEM_DIALOG_REASON_HOME_KEY
=
"homekey"
;
private
static
final
long
delay
=
300
;
private
Handler
mHandler
;
private
Class
[]
activities
;
private
boolean
showFlag
;
private
int
startCount
;
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
();
}
else
{
//mLifecycleListener.onHide();
}
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
)
{
startCount
++;
}
@Override
public
void
onActivityStopped
(
Activity
activity
)
{
startCount
--;
if
(
startCount
==
0
)
{
//mLifecycleListener.onHide();
}
}
@Override
public
void
onReceive
(
Context
context
,
Intent
intent
)
{
String
action
=
intent
.
getAction
();
if
(
action
!=
null
&&
action
.
equals
(
Intent
.
ACTION_CLOSE_SYSTEM_DIALOGS
))
{
String
reason
=
intent
.
getStringExtra
(
SYSTEM_DIALOG_REASON_KEY
);
if
(
SYSTEM_DIALOG_REASON_HOME_KEY
.
equals
(
reason
))
{
//mLifecycleListener.onHide();
}
}
}
@Override
public
void
onActivityCreated
(
Activity
activity
,
Bundle
savedInstanceState
)
{
}
@Override
public
void
onActivitySaveInstanceState
(
Activity
activity
,
Bundle
outState
)
{
}
@Override
public
void
onActivityDestroyed
(
Activity
activity
)
{
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatPhone.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
import
android.content.Context
;
import
android.graphics.PixelFormat
;
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
)
{
mLayoutParams
.
flags
=
WindowManager
.
LayoutParams
.
FLAG_NOT_TOUCH_MODAL
|
WindowManager
.
LayoutParams
.
FLAG_NOT_FOCUSABLE
;
mLayoutParams
.
type
=
WindowManager
.
LayoutParams
.
TYPE_PHONE
;
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
(
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
;
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatToast.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
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
{
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
();
}
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatView.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
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
;
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/FloatWindow.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
import
android.animation.TimeInterpolator
;
import
android.content.Context
;
import
android.support.annotation.LayoutRes
;
import
android.support.annotation.MainThread
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.view.Gravity
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* Created by yhao on 2017/12/22.
* https://github.com/yhaolpz
*/
public
class
FloatWindow
{
private
FloatWindow
()
{
}
private
static
final
String
mDefaultTag
=
"default_float_window_tag"
;
private
static
Map
<
String
,
IFloatWindow
>
mFloatWindowMap
;
public
static
IFloatWindow
get
()
{
return
get
(
mDefaultTag
);
}
public
static
IFloatWindow
get
(
@NonNull
String
tag
)
{
return
mFloatWindowMap
==
null
?
null
:
mFloatWindowMap
.
get
(
tag
);
}
private
static
B
mBuilder
=
null
;
@MainThread
public
static
B
with
(
@NonNull
Context
applicationContext
)
{
return
mBuilder
=
new
B
(
applicationContext
);
}
public
static
void
destroy
()
{
destroy
(
mDefaultTag
);
}
public
static
void
destroy
(
String
tag
)
{
if
(
mFloatWindowMap
==
null
||
!
mFloatWindowMap
.
containsKey
(
tag
))
{
return
;
}
mFloatWindowMap
.
get
(
tag
).
dismiss
();
mFloatWindowMap
.
remove
(
tag
);
}
public
static
class
B
{
Context
mApplicationContext
;
View
mView
;
private
int
mLayoutId
;
int
mWidth
=
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
;
int
mHeight
=
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
;
int
gravity
=
Gravity
.
TOP
|
Gravity
.
START
;
int
xOffset
;
int
yOffset
;
boolean
mShow
=
true
;
Class
[]
mActivities
;
int
mMoveType
=
MoveType
.
fixed
;
long
mDuration
=
300
;
TimeInterpolator
mInterpolator
;
private
String
mTag
=
mDefaultTag
;
private
B
()
{
}
B
(
Context
applicationContext
)
{
mApplicationContext
=
applicationContext
;
}
public
B
setView
(
@NonNull
View
view
)
{
mView
=
view
;
return
this
;
}
public
B
setView
(
@LayoutRes
int
layoutId
)
{
mLayoutId
=
layoutId
;
return
this
;
}
public
B
setWidth
(
int
width
)
{
mWidth
=
width
;
return
this
;
}
public
B
setHeight
(
int
height
)
{
mHeight
=
height
;
return
this
;
}
public
B
setWidth
(
@Screen
.
screenType
int
screenType
,
float
ratio
)
{
mWidth
=
(
int
)
((
screenType
==
Screen
.
width
?
Util
.
getScreenWidth
(
mApplicationContext
)
:
Util
.
getScreenHeight
(
mApplicationContext
))
*
ratio
);
return
this
;
}
public
B
setHeight
(
@Screen
.
screenType
int
screenType
,
float
ratio
)
{
mHeight
=
(
int
)
((
screenType
==
Screen
.
width
?
Util
.
getScreenWidth
(
mApplicationContext
)
:
Util
.
getScreenHeight
(
mApplicationContext
))
*
ratio
);
return
this
;
}
public
B
setX
(
int
x
)
{
xOffset
=
x
;
return
this
;
}
public
B
setY
(
int
y
)
{
yOffset
=
y
;
return
this
;
}
public
B
setX
(
@Screen
.
screenType
int
screenType
,
float
ratio
)
{
xOffset
=
(
int
)
((
screenType
==
Screen
.
width
?
Util
.
getScreenWidth
(
mApplicationContext
)
:
Util
.
getScreenHeight
(
mApplicationContext
))
*
ratio
);
return
this
;
}
public
B
setY
(
@Screen
.
screenType
int
screenType
,
float
ratio
)
{
yOffset
=
(
int
)
((
screenType
==
Screen
.
width
?
Util
.
getScreenWidth
(
mApplicationContext
)
:
Util
.
getScreenHeight
(
mApplicationContext
))
*
ratio
);
return
this
;
}
/**
* 设置 Activity 过滤器,用于指定在哪些界面显示悬浮窗,默认全部界面都显示
*
* @param show 过滤类型,子类类型也会生效
* @param activities 过滤界面
*/
public
B
setFilter
(
boolean
show
,
@NonNull
Class
...
activities
)
{
mShow
=
show
;
mActivities
=
activities
;
return
this
;
}
public
B
setMoveType
(
@MoveType
.
MOVE_TYPE
int
moveType
)
{
mMoveType
=
moveType
;
return
this
;
}
public
B
setMoveStyle
(
long
duration
,
@Nullable
TimeInterpolator
interpolator
)
{
mDuration
=
duration
;
mInterpolator
=
interpolator
;
return
this
;
}
public
B
setTag
(
@NonNull
String
tag
)
{
mTag
=
tag
;
return
this
;
}
public
void
build
()
{
if
(
mFloatWindowMap
==
null
)
{
mFloatWindowMap
=
new
HashMap
<>();
}
if
(
mFloatWindowMap
.
containsKey
(
mTag
))
{
throw
new
IllegalArgumentException
(
"FloatWindow of this tag has been added, Please set a new tag for the new FloatWindow"
);
}
if
(
mView
==
null
&&
mLayoutId
==
0
)
{
throw
new
IllegalArgumentException
(
"View has not been set!"
);
}
if
(
mView
==
null
)
{
mView
=
Util
.
inflate
(
mApplicationContext
,
mLayoutId
);
}
IFloatWindow
floatWindowImpl
=
new
IFloatWindowImpl
(
this
);
mFloatWindowMap
.
put
(
mTag
,
floatWindowImpl
);
}
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/IFloatWindow.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
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
();
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/IFloatWindowImpl.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
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
.
B
mB
;
private
FloatView
mFloatView
;
private
FloatLifecycle
mFloatLifecycle
;
private
boolean
isShow
;
private
boolean
once
=
true
;
private
ValueAnimator
mAnimator
;
private
TimeInterpolator
mDecelerateInterpolator
;
private
IFloatWindowImpl
()
{
}
IFloatWindowImpl
(
FloatWindow
.
B
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
);
mFloatLifecycle
=
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
();
}
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/LifecycleListener.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
/**
* Created by yhao on 2017/12/22.
* https://github.com/yhaolpz
*/
interface
LifecycleListener
{
void
onShow
();
void
onHide
();
void
onPostHide
();
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/MoveType.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
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
{
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/PermissionListener.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
/**
* Created by yhao on 2017/11/14.
* https://github.com/yhaolpz
*/
interface
PermissionListener
{
void
onSuccess
();
void
onFail
();
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/Screen.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
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
{
}
}
app/src/main/java/com/example/gsyvideoplayer/utils/floatUtil/Util.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.utils.floatUtil
;
import
android.content.Context
;
import
android.graphics.Point
;
import
android.provider.Settings
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.WindowManager
;
import
java.lang.reflect.Method
;
/**
* 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
);
}
public
static
boolean
hasPermission
(
Context
context
)
{
Boolean
result
;
try
{
Class
clazz
=
Settings
.
class
;
Method
canDrawOverlays
=
clazz
.
getDeclaredMethod
(
"canDrawOverlays"
,
Context
.
class
);
result
=
(
Boolean
)
canDrawOverlays
.
invoke
(
null
,
context
);
}
catch
(
Exception
e
)
{
result
=
false
;
}
return
result
;
}
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
;
}
}
app/src/main/java/com/example/gsyvideoplayer/video/FloatingVideo.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.video
;
import
android.content.Context
;
import
android.media.AudioManager
;
import
android.util.AttributeSet
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
com.example.gsyvideoplayer.R
;
import
com.shuyu.gsyvideoplayer.GSYVideoManager
;
import
com.shuyu.gsyvideoplayer.utils.Debuger
;
import
com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
;
import
java.util.Timer
;
import
java.util.TimerTask
;
import
static
com
.
shuyu
.
gsyvideoplayer
.
utils
.
CommonUtil
.
hideNavKey
;
/**
* 多窗体下的悬浮窗页面支持Video
* Created by shuyu on 2017/12/25.
*/
public
class
FloatingVideo
extends
StandardGSYVideoPlayer
{
protected
DismissControlViewTimerTask
mDismissControlViewTimerTask
;
/**
* 1.5.0开始加入,如果需要不同布局区分功能,需要重载
*/
public
FloatingVideo
(
Context
context
,
Boolean
fullFlag
)
{
super
(
context
,
fullFlag
);
}
public
FloatingVideo
(
Context
context
)
{
super
(
context
);
}
public
FloatingVideo
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
}
@Override
protected
void
init
(
Context
context
)
{
if
(
getActivityContext
()
!=
null
)
{
this
.
mContext
=
getActivityContext
();
}
else
{
this
.
mContext
=
context
;
}
initInflate
(
mContext
);
mTextureViewContainer
=
(
ViewGroup
)
findViewById
(
R
.
id
.
surface_container
);
mStartButton
=
findViewById
(
R
.
id
.
start
);
if
(
isInEditMode
())
return
;
mScreenWidth
=
getActivityContext
().
getResources
().
getDisplayMetrics
().
widthPixels
;
mScreenHeight
=
getActivityContext
().
getResources
().
getDisplayMetrics
().
heightPixels
;
mAudioManager
=
(
AudioManager
)
getActivityContext
().
getApplicationContext
().
getSystemService
(
Context
.
AUDIO_SERVICE
);
mStartButton
=
findViewById
(
com
.
shuyu
.
gsyvideoplayer
.
R
.
id
.
start
);
mStartButton
.
setOnClickListener
(
new
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
clickStartIcon
();
}
});
}
@Override
public
int
getLayoutId
()
{
return
R
.
layout
.
layout_floating_video
;
}
@Override
protected
void
startPrepare
()
{
if
(
GSYVideoManager
.
instance
().
listener
()
!=
null
)
{
GSYVideoManager
.
instance
().
listener
().
onCompletion
();
}
GSYVideoManager
.
instance
().
setListener
(
this
);
GSYVideoManager
.
instance
().
setPlayTag
(
mPlayTag
);
GSYVideoManager
.
instance
().
setPlayPosition
(
mPlayPosition
);
mAudioManager
.
requestAudioFocus
(
onAudioFocusChangeListener
,
AudioManager
.
STREAM_MUSIC
,
AudioManager
.
AUDIOFOCUS_GAIN_TRANSIENT
);
//((Activity) getActivityContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mBackUpPlayingBufferState
=
-
1
;
GSYVideoManager
.
instance
().
prepare
(
mUrl
,
mMapHeadData
,
mLooping
,
mSpeed
);
setStateAndUi
(
CURRENT_STATE_PREPAREING
);
}
@Override
public
void
onAutoCompletion
()
{
setStateAndUi
(
CURRENT_STATE_AUTO_COMPLETE
);
mSaveChangeViewTIme
=
0
;
if
(
mTextureViewContainer
.
getChildCount
()
>
0
)
{
mTextureViewContainer
.
removeAllViews
();
}
if
(!
mIfCurrentIsFullscreen
)
GSYVideoManager
.
instance
().
setLastListener
(
null
);
mAudioManager
.
abandonAudioFocus
(
onAudioFocusChangeListener
);
//((Activity) getActivityContext()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
releaseNetWorkState
();
if
(
mVideoAllCallBack
!=
null
&&
isCurrentMediaListener
())
{
Debuger
.
printfLog
(
"onAutoComplete"
);
mVideoAllCallBack
.
onAutoComplete
(
mOriginUrl
,
mTitle
,
this
);
}
}
@Override
public
void
onCompletion
()
{
//make me normal first
setStateAndUi
(
CURRENT_STATE_NORMAL
);
mSaveChangeViewTIme
=
0
;
if
(
mTextureViewContainer
.
getChildCount
()
>
0
)
{
mTextureViewContainer
.
removeAllViews
();
}
if
(!
mIfCurrentIsFullscreen
)
{
GSYVideoManager
.
instance
().
setListener
(
null
);
GSYVideoManager
.
instance
().
setLastListener
(
null
);
}
GSYVideoManager
.
instance
().
setCurrentVideoHeight
(
0
);
GSYVideoManager
.
instance
().
setCurrentVideoWidth
(
0
);
mAudioManager
.
abandonAudioFocus
(
onAudioFocusChangeListener
);
//((Activity) getActivityContext()).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
releaseNetWorkState
();
}
@Override
protected
Context
getActivityContext
()
{
return
getContext
();
}
@Override
protected
void
startDismissControlViewTimer
()
{
cancelDismissControlViewTimer
();
mDismissControlViewTimer
=
new
Timer
();
mDismissControlViewTimerTask
=
new
DismissControlViewTimerTask
();
mDismissControlViewTimer
.
schedule
(
mDismissControlViewTimerTask
,
mDismissControlTime
);
}
@Override
protected
void
cancelDismissControlViewTimer
()
{
if
(
mDismissControlViewTimer
!=
null
)
{
mDismissControlViewTimer
.
cancel
();
mDismissControlViewTimer
=
null
;
}
if
(
mDismissControlViewTimerTask
!=
null
)
{
mDismissControlViewTimerTask
.
cancel
();
mDismissControlViewTimerTask
=
null
;
}
}
private
class
DismissControlViewTimerTask
extends
TimerTask
{
@Override
public
void
run
()
{
if
(
mCurrentState
!=
CURRENT_STATE_NORMAL
&&
mCurrentState
!=
CURRENT_STATE_ERROR
&&
mCurrentState
!=
CURRENT_STATE_AUTO_COMPLETE
)
{
if
(
getActivityContext
()
!=
null
)
{
FloatingVideo
.
this
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
hideAllWidget
();
setViewShowState
(
mLockScreen
,
GONE
);
if
(
mHideKey
&&
mIfCurrentIsFullscreen
&&
mShowVKey
)
{
hideNavKey
(
mContext
);
}
}
});
}
}
}
}
}
app/src/main/java/com/example/gsyvideoplayer/view/FloatPlayerView.java
0 → 100644
浏览文件 @
f82d7d73
package
com.example.gsyvideoplayer.view
;
import
android.content.Context
;
import
android.graphics.Color
;
import
android.util.AttributeSet
;
import
android.view.Gravity
;
import
android.view.ViewGroup
;
import
android.widget.FrameLayout
;
import
com.example.gsyvideoplayer.video.FloatingVideo
;
import
com.shuyu.gsyvideoplayer.video.base.GSYVideoPlayer
;
/**
* Created by guoshuyu on 2017/12/25.
*/
public
class
FloatPlayerView
extends
FrameLayout
{
FloatingVideo
videoPlayer
;
public
FloatPlayerView
(
Context
context
)
{
super
(
context
);
init
();
}
public
FloatPlayerView
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
init
();
}
public
FloatPlayerView
(
Context
context
,
AttributeSet
attrs
,
int
defStyleAttr
)
{
super
(
context
,
attrs
,
defStyleAttr
);
init
();
}
private
void
init
()
{
videoPlayer
=
new
FloatingVideo
(
getContext
());
LayoutParams
layoutParams
=
new
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
);
layoutParams
.
gravity
=
Gravity
.
CENTER
;
addView
(
videoPlayer
,
layoutParams
);
String
source1
=
"http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f20.mp4"
;
videoPlayer
.
setUp
(
source1
,
true
,
"测试视频"
);
//增加封面
/*ImageView imageView = new ImageView(getContext());
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(R.mipmap.xxx1);
videoPlayer.setThumbImageView(imageView);*/
//是否可以滑动调整
videoPlayer
.
setIsTouchWiget
(
false
);
}
public
void
onPause
()
{
videoPlayer
.
onVideoPause
();
}
public
void
onResume
()
{
videoPlayer
.
onVideoResume
();
}
public
void
onBackPressed
()
{
//释放所有
videoPlayer
.
setStandardVideoAllCallBack
(
null
);
GSYVideoPlayer
.
releaseAllVideos
();
}
}
app/src/main/res/layout/activity_empty.xml
0 → 100644
浏览文件 @
f82d7d73
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<Button
android:id=
"@+id/jump_other"
android:layout_width=
"120dp"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"20dp"
android:text=
"跳转其他页面"
/>
</LinearLayout>
app/src/main/res/layout/activity_main.xml
浏览文件 @
f82d7d73
...
...
@@ -143,6 +143,13 @@
android:layout_marginTop=
"20dp"
android:text=
"联动detail"
/>
<Button
android:id=
"@+id/open_window"
android:layout_width=
"120dp"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"20dp"
android:text=
"悬浮窗口"
/>
<Button
android:id=
"@+id/clear_cache"
android:layout_width=
"120dp"
...
...
app/src/main/res/layout/activity_window.xml
0 → 100644
浏览文件 @
f82d7d73
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<Button
android:id=
"@+id/start_window"
android:layout_width=
"120dp"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"20dp"
android:text=
"启动悬浮窗口"
/>
<Button
android:id=
"@+id/jump_other"
android:layout_width=
"120dp"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"20dp"
android:text=
"跳转其他页面"
/>
<TextView
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_margin=
"10dp"
android:textSize=
"15sp"
android:text=
"返回到桌面,或者点击跳转其他页面均可以存在,demo这里在返回主页Main的时候销毁,因为不想和DEMO中其他页面冲突"
/>
</LinearLayout>
app/src/main/res/layout/layout_floating_play.xml
0 → 100644
浏览文件 @
f82d7d73
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id=
"@+id/activity_play"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"#000000"
>
<com.example.gsyvideoplayer.video.FloatingVideo
android:id=
"@+id/video_player"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_centerInParent=
"true"
/>
</RelativeLayout>
app/src/main/res/layout/layout_floating_video.xml
0 → 100644
浏览文件 @
f82d7d73
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/black"
>
<FrameLayout
android:id=
"@+id/surface_container"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:gravity=
"center"
>
</FrameLayout>
<moe.codeest.enviews.ENPlayView
android:id=
"@+id/start"
android:layout_width=
"35dp"
android:layout_height=
"35dp"
android:layout_centerHorizontal=
"true"
android:layout_centerVertical=
"true"
android:layout_gravity=
"center_vertical"
/>
</RelativeLayout>
dependencies.gradle
浏览文件 @
f82d7d73
...
...
@@ -20,6 +20,7 @@ ext {
DanmakuFlameMaster
=
'0.6.4'
transitionseverywhere
=
'1.7.0'
floatWindow
=
'1.0.6'
//DataLibraries
videocache
=
'2.1.1'
...
...
@@ -53,7 +54,8 @@ ext {
ndkbitmap_armv5
:
"com.github.ctiao:ndkbitmap-armv5:${DanmakuFlameMaster}"
,
ndkbitmap_x86
:
"com.github.ctiao:ndkbitmap-x86:${DanmakuFlameMaster}"
,
glide
:
"com.github.bumptech.glide:glide:${imageLoader}"
,
glideProcessor
:
"com.github.bumptech.glide:compiler:${imageLoader}"
glideProcessor
:
"com.github.bumptech.glide:compiler:${imageLoader}"
,
floatWindow
:
"com.github.yhaolpz:FloatWindow:${floatWindow}"
,
]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录