src\MyApplication\.idea\codeStyleSettings.xml
src\MyApplication\.idea\compiler.xml src\MyApplication\.idea\encodings.xml src\MyApplication\.idea\gradle.xml src\MyApplication\.idea\misc.xml src\MyApplication\.idea\modules.xml src\MyApplication\.idea\runConfigurations.xml src\MyApplication\.idea\sonarlint\issuestore\index.pb src\MyApplication\app\build.gradle src\MyApplication\app\src\main\AndroidManifest.xml src\MyApplication\app\src\main\java\com\example\administrator\myapplication\adapter\BgPicGridAdapter.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\adapter\NotebookAdapter.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\app\BaseApplication.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\db\DatabaseHelper.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\db\NoteDatabase.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\entity\BgPicEntity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\entity\NotebookData.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\entity\OnResponseListener.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\entity\Response.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\entity\UpdataEvent.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\entity\User.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\AboutAppFragment.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\AlarmAlertActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\ChangeBgFragment.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\DateTimePicker.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\DateTimePickerDialog.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\LoginActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\MainActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\NoteBookFragment.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\NoteEditActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\NoteEditFragment.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\RegisterActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\SetLockActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\SettingFragment.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\UnLockActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\UserInfoActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\ui\WelcomeActivity.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\AccountUtils.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\BmobConstants.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\CommonUtils.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\Constants.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\DialogHelp.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\HTQAnimations.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\ImageLoadOptions.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\MD5Util.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\PhotoUtil.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\ResourceParser.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\SPUtils.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\StringUtils.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\SystemUtils.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\utils\TimeZoneUtil.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\widget\CircleImageView.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\widget\HTQDragGridView.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\widget\NoteItemCircleView.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\widget\ToggleButton.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\widget\patternlock\LockPatternView.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\widget\patternlock\Point.java src\MyApplication\app\src\main\java\com\example\administrator\myapplication\widget\patternlock\RotateDegrees.java src\MyApplication\app\src\main\res\anim\grow_from_bottom.xml src\MyApplication\app\src\main\res\anim\shrink_from_top.xml src\MyApplication\app\src\main\res\drawable-v21\btn_dark_blue_background.xml src\MyApplication\app\src\main\res\drawable-v21\btn_orange_background.xml src\MyApplication\app\src\main\res\drawable-v21\ic_menu_camera.xml src\MyApplication\app\src\main\res\drawable-v21\ic_menu_gallery.xml src\MyApplication\app\src\main\res\drawable-v21\ic_menu_manage.xml src\MyApplication\app\src\main\res\drawable-v21\ic_menu_send.xml src\MyApplication\app\src\main\res\drawable-v21\ic_menu_share.xml src\MyApplication\app\src\main\res\drawable-v21\ic_menu_slideshow.xml src\MyApplication\app\src\main\res\drawable-v21\login_divider_line.xml src\MyApplication\app\src\main\res\drawable-v21\login_et_background.xml src\MyApplication\app\src\main\res\drawable-v21\login_ll_background.xml src\MyApplication\app\src\main\res\drawable\btn_login_selector.xml src\MyApplication\app\src\main\res\drawable\ic_info_black_24dp.xml src\MyApplication\app\src\main\res\drawable\ic_notifications_black_24dp.xml src\MyApplication\app\src\main\res\drawable\ic_sync_black_24dp.xml src\MyApplication\app\src\main\res\drawable\side_nav_bar.xml src\MyApplication\app\src\main\res\drawable\skin_img_item_background.xml src\MyApplication\app\src\main\res\layout\about_me_fragment.xml src\MyApplication\app\src\main\res\layout\activity_login.xml src\MyApplication\app\src\main\res\layout\activity_main.xml src\MyApplication\app\src\main\res\layout\activity_note_edit.xml src\MyApplication\app\src\main\res\layout\activity_register.xml src\MyApplication\app\src\main\res\layout\activity_set_lock.xml src\MyApplication\app\src\main\res\layout\activity_unlock.xml src\MyApplication\app\src\main\res\layout\activity_user_info.xml src\MyApplication\app\src\main\res\layout\activity_welcome.xml src\MyApplication\app\src\main\res\layout\app_bar_main.xml src\MyApplication\app\src\main\res\layout\bg_pic_grid_item.xml src\MyApplication\app\src\main\res\layout\change_info_dialog_layout.xml src\MyApplication\app\src\main\res\layout\content_main.xml src\MyApplication\app\src\main\res\layout\datetime_picker.xml src\MyApplication\app\src\main\res\layout\fragment_change_background.xml src\MyApplication\app\src\main\res\layout\fragment_note.xml src\MyApplication\app\src\main\res\layout\fragment_setting.xml src\MyApplication\app\src\main\res\layout\item_notebook.xml src\MyApplication\app\src\main\res\layout\layout_note_detail_menu.xml src\MyApplication\app\src\main\res\layout\main_fragment.xml src\MyApplication\app\src\main\res\layout\nav_header_main.xml src\MyApplication\app\src\main\res\layout\note_edit_activity_fraglayout.xml src\MyApplication\app\src\main\res\layout\note_edit_fraglayout.xml src\MyApplication\app\src\main\res\layout\pop_showavator.xml src\MyApplication\app\src\main\res\layout\popupwindow_choose_layout.xml src\MyApplication\app\src\main\res\layout\widget_lock_view.xml src\MyApplication\app\src\main\res\menu\activity_main_drawer.xml src\MyApplication\app\src\main\res\menu\main.xml src\MyApplication\app\src\main\res\menu\notebook_edit_menu.xml src\MyApplication\app\src\main\res\values-v21\attrs.xml src\MyApplication\app\src\main\res\values-v21\styles.xml src\MyApplication\app\src\main\res\values-w820dp\dimens.xml src\MyApplication\app\src\main\res\values\attrs.xml src\MyApplication\app\src\main\res\values\colors.xml src\MyApplication\app\src\main\res\values\dimens.xml src\MyApplication\app\src\main\res\values\drawables.xml src\MyApplication\app\src\main\res\values\strings.xml src\MyApplication\app\src\main\res\values\styles.xml src\MyApplication\build.gradle src\MyApplication\gradlew src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\.idea\compiler.xml src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\.idea\encodings.xml src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\.idea\gradle.xml src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\.idea\misc.xml src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\.idea\modules.xml src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\.idea\runConfigurations.xml src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\app\src\main\java\cn\bmob\sdkdemo\BmobApplication.java src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\gradle\wrapper\gradle-wrapper.properties src\MyApplication\libs\BmobSDKDemo_v3.6.0\BmobDemo\gradlew src\MyApplication\libs\BmobSDKDemo_v3.6.0\更新日志.txt src\MyApplication\settings.gradle src\MyApplication\.idea\sonarlint\issuestore\0\5\05efc8b1657769a27696d478ded1e95f38737233 src\MyApplication\.idea\sonarlint\issuestore\0\7\0712df971a99ac4d2fccb8e0fb19f377f3374cca src\MyApplication\.idea\sonarlint\issuestore\2\a\2afbb999f001938c88fa43fc2ef52abf0f8213e4 src\MyApplication\.idea\sonarlint\issuestore\3\0\30a54a60f14d64645eed00c5f82475af0b8df642 src\MyApplication\.idea\sonarlint\issuestore\6\7\67dcf9378cf673b1d3b665701ca8ab112314a41a src\MyApplication\app\src\main\res\drawable\icon.png src\MyApplication\floatwindow\.gitignore src\MyApplication\floatwindow\build.gradle src\MyApplication\floatwindow\proguard-rules.pro src\MyApplication\floatwindow\src\androidTest\java\com\example\fixedfloatwindow\ExampleInstrumentedTest.java src\MyApplication\floatwindow\src\main\AndroidManifest.xml src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\FloatActivity.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\FloatLifecycle.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\FloatPhone.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\FloatToast.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\FloatView.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\FloatWindow.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\IFloatWindow.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\IFloatWindowImpl.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\LifecycleListener.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\LogUtil.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\Miui.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\MoveType.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\PermissionListener.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\PermissionUtil.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\ResumedListener.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\Rom.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\Screen.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\Util.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\ViewStateListener.java src\MyApplication\floatwindow\src\main\java\com\yhao\floatwindow\ViewStateListenerAdapter.java src\MyApplication\floatwindow\src\main\res\values\strings.xml src\MyApplication\floatwindow\src\main\res\values\style.xml src\MyApplication\floatwindow\src\test\java\com\example\fixedfloatwindow\ExampleUnitTest.java
This commit is contained in:
parent
6c240ad185
commit
1b78cc0904
|
@ -9,7 +9,7 @@
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
<option value="$PROJECT_DIR$/library" />
|
<option value="$PROJECT_DIR$/floatwindow" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="resolveModulePerSourceSet" value="false" />
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/MyApplication.iml" filepath="$PROJECT_DIR$/MyApplication.iml" />
|
<module fileurl="file://$PROJECT_DIR$/MyApplication.iml" filepath="$PROJECT_DIR$/MyApplication.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/library/my_library.iml" filepath="$PROJECT_DIR$/library/my_library.iml" />
|
<module fileurl="file://$PROJECT_DIR$/floatwindow/floatwindow.iml" filepath="$PROJECT_DIR$/floatwindow/floatwindow.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(éóÈàûÿÿÿÿ
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(¢ææòýÿÿÿÿ
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(™Õüþÿÿÿÿ
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(ñ¥—²ýÿÿÿÿ
|
||||||
|
Ksquid:S2696"6Make the enclosing method "static" or remove this set.(ƒÌï<C38C>
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(ù¤¾¤
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(Ù÷žñùÿÿÿÿ
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(¹ÿÁ<C3BF>ûÿÿÿÿ
|
||||||
|
@squid:S1172"+Remove this unused method parameter "view".(É‚£<E2809A>
|
||||||
|
Ssquid:S1155">Use isEmpty() to check whether the collection is empty or not.(ö‡Òí
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(¶¾õÕ
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(³¿á•
|
||||||
|
Psquid:S2696"6Make the enclosing method "static" or remove this set.(Ý…ÿÛüÿÿÿÿ
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(Œö܉
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(¼õØ€ùÿÿÿÿ
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(¾Äºú
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(û<>¤™ûÿÿÿÿ
|
||||||
|
@squid:S1444",Make this "public static mState" field final(½²»|
|
||||||
|
Lsquid:S2589"7Remove this expression which always evaluates to "true"(â¿ß“
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(Œö܉
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(›¢¼Äüÿÿÿÿ
|
||||||
|
–squid:S1186"€Add a nested comment explaining why this method is empty, throw an UnsupportedOperationException or complete the implementation.(ò‘<C3B2>‘
|
||||||
|
_squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(À<>ÎC
|
||||||
|
Bsquid:S2387"."mState" is the name of a field in "Fragment".(½²»|
|
||||||
|
Jsquid:S2696"6Make the enclosing method "static" or remove this set.(º’ë1
|
||||||
|
}"squid:ClassVariableVisibilityCheck"RMake mState a static final constant or non-public and provide accessors if needed.(½²»|
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(”“ɉúÿÿÿÿ
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(¡…•æùÿÿÿÿ
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(<28>ÀÆ’
|
||||||
|
ssquid:S1450"YRemove the "isFirstUse" field and declare it as a local variable in the relevant methods.(ÃÑ<C383><C391>ûÿÿÿÿ
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(<28>ÀÆ’
|
||||||
|
`squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(ô侄
|
||||||
|
bsquid:CallToDeprecatedMethod"=Remove this use of "setBackgroundDrawable"; it is deprecated.(”›õV
|
||||||
|
_squid:HiddenFieldCheck":Rename "drawer" which hides the field declared at line 41.(ÐÍè¨þÿÿÿÿ
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(Û¿’<C2BF>ýÿÿÿÿ
|
||||||
|
_squid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(üêÝ/
|
||||||
|
Asquid:S1905",Remove this unnecessary cast to "ImageView".(ÆïË”
|
||||||
|
_squid:HiddenFieldCheck":Rename "drawer" which hides the field declared at line 41.(ÐÍè¨þÿÿÿÿ
|
||||||
|
dsquid:CallToDeprecatedMethod"9Remove this use of "setDrawerListener"; it is deprecated.(ø¶Âßÿÿÿÿÿ
|
||||||
|
qsquid:S1450"WRemove the "baseView" field and declare it as a local variable in the relevant methods.(‘‚¼²þÿÿÿÿ
|
||||||
|
esquid:CommentedOutCodeLine"<This block of commented-out lines of code should be removed.(–“Å<E2809C>ýÿÿÿÿ
|
||||||
|
ysquid:S1450"_Remove the "noteBookFragment" field and declare it as a local variable in the relevant methods.(Óé«ùÿÿÿÿ
|
||||||
|
isquid:MaximumInheritanceDepth"=This class has 10 parents which is greater than 5 authorized.(ù ®Íúÿÿÿÿ
|
|
@ -1,3 +1,13 @@
|
||||||
|
|
||||||
<
|
<
|
||||||
build.gradle,f\0\f07866736216be0ee2aba49e392191aeae700a35
|
build.gradle,f\0\f07866736216be0ee2aba49e392191aeae700a35
|
||||||
|
?
|
||||||
|
settings.gradle,0\5\05efc8b1657769a27696d478ded1e95f38737233
|
||||||
|
A
|
||||||
|
gradle.properties,2\a\2afbb999f001938c88fa43fc2ef52abf0f8213e4
|
||||||
|
@
|
||||||
|
local.properties,0\7\0712df971a99ac4d2fccb8e0fb19f377f3374cca
|
||||||
|
‚
|
||||||
|
Rapp\src\main\java\com\example\administrator\myapplication\ui\NoteBookFragment.java,3\0\30a54a60f14d64645eed00c5f82475af0b8df642
|
||||||
|
~
|
||||||
|
Napp\src\main\java\com\example\administrator\myapplication\ui\MainActivity.java,6\7\67dcf9378cf673b1d3b665701ca8ab112314a41a
|
|
@ -7,10 +7,11 @@ android {
|
||||||
useLibrary 'org.apache.http.legacy'
|
useLibrary 'org.apache.http.legacy'
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.example.administrator.myapplication"
|
applicationId "com.example.administrator.myapplication"
|
||||||
minSdkVersion 17
|
minSdkVersion 19
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
|
multiDexEnabled true
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
@ -40,8 +41,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
compile project(':my_library')
|
|
||||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||||
exclude group: 'com.android.support', module: 'support-annotations'
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
})
|
})
|
||||||
|
@ -58,5 +58,7 @@ dependencies {
|
||||||
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.2'
|
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.2'
|
||||||
compile 'com.github.clans:fab:1.6.1'
|
compile 'com.github.clans:fab:1.6.1'
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
|
compile 'com.github.yhaolpz:FloatWindow:1.0.9'
|
||||||
apt 'com.jakewharton:butterknife-compiler:8.2.1'
|
apt 'com.jakewharton:butterknife-compiler:8.2.1'
|
||||||
|
compile project(':floatwindow')
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="2.1.0">
|
android:versionName="2.1.0">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
|
<!-- 获取悬浮窗的权限 -->
|
||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<!-- 获取GSM(2g)、WCDMA(联通3g)等网络状态的信息 -->
|
<!-- 获取GSM(2g)、WCDMA(联通3g)等网络状态的信息 -->
|
||||||
|
@ -28,7 +30,8 @@
|
||||||
android:icon="@mipmap/app_icon"
|
android:icon="@mipmap/app_icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme"
|
||||||
|
android:name="com.example.administrator.myapplication.app.BaseApplication">
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.WelcomeActivity"
|
android:name=".ui.WelcomeActivity"
|
||||||
android:theme="@style/AppTheme.NoActionBar">
|
android:theme="@style/AppTheme.NoActionBar">
|
||||||
|
|
|
@ -2,7 +2,14 @@ package com.example.administrator.myapplication.app;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.BounceInterpolator;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.example.administrator.myapplication.R;
|
||||||
|
import com.example.administrator.myapplication.ui.MainActivity;
|
||||||
import com.example.administrator.myapplication.utils.BmobConstants;
|
import com.example.administrator.myapplication.utils.BmobConstants;
|
||||||
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
|
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
|
||||||
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
|
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
|
||||||
|
@ -11,22 +18,52 @@ import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||||
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
|
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
|
||||||
import com.nostra13.universalimageloader.utils.StorageUtils;
|
import com.nostra13.universalimageloader.utils.StorageUtils;
|
||||||
|
import com.yhao.floatwindow.FloatWindow;
|
||||||
|
import com.yhao.floatwindow.MoveType;
|
||||||
|
import com.yhao.floatwindow.PermissionListener;
|
||||||
|
import com.yhao.floatwindow.Screen;
|
||||||
|
import com.yhao.floatwindow.ViewStateListener;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import cn.bmob.v3.Bmob;
|
import cn.bmob.v3.Bmob;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by htq on 2016/9/5.
|
|
||||||
*/
|
|
||||||
public class BaseApplication extends Application {
|
public class BaseApplication extends Application {
|
||||||
|
|
||||||
|
private static final String TAG = "FloatWindow";
|
||||||
private String ApplicationId="82cacaa4470ab6b8d61d3f0ce6d6201d";
|
private String ApplicationId="82cacaa4470ab6b8d61d3f0ce6d6201d";
|
||||||
static public String avatarPath= BmobConstants.MyAvatarDir+"avatarIcon.png";
|
static public String avatarPath= BmobConstants.MyAvatarDir+"avatarIcon.png";
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
|
ImageView imageView = new ImageView(getApplicationContext());
|
||||||
|
imageView.setImageResource(R.drawable.icon);
|
||||||
|
|
||||||
|
FloatWindow
|
||||||
|
.with(getApplicationContext())
|
||||||
|
.setView(imageView)
|
||||||
|
.setWidth(Screen.width, 0.2f) //设置悬浮控件宽高
|
||||||
|
.setHeight(Screen.width, 0.2f)
|
||||||
|
.setX(Screen.width, 0.8f)
|
||||||
|
.setY(Screen.height, 0.3f)
|
||||||
|
.setMoveType(MoveType.slide,100,-100)
|
||||||
|
.setMoveStyle(500, new BounceInterpolator())
|
||||||
|
.setFilter(true, MainActivity.class)
|
||||||
|
.setViewStateListener(mViewStateListener)
|
||||||
|
.setPermissionListener(mPermissionListener)
|
||||||
|
.setDesktopShow(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
imageView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Toast.makeText(BaseApplication.this, "嗖藏成功~", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//悬浮窗口部分
|
||||||
initImageLoader(this);
|
initImageLoader(this);
|
||||||
Bmob.initialize(this, ApplicationId);
|
Bmob.initialize(this, ApplicationId);
|
||||||
// android 7.0系统解决拍照的问题
|
// android 7.0系统解决拍照的问题
|
||||||
|
@ -55,4 +92,53 @@ public class BaseApplication extends Application {
|
||||||
ImageLoader.getInstance().init(config);// 全局初始化此配置
|
ImageLoader.getInstance().init(config);// 全局初始化此配置
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 悬浮窗日志 */
|
||||||
|
private PermissionListener mPermissionListener = new PermissionListener() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
Log.d(TAG, "onSuccess");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFail() {
|
||||||
|
Log.d(TAG, "onFail");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private ViewStateListener mViewStateListener = new ViewStateListener() {
|
||||||
|
@Override
|
||||||
|
public void onPositionUpdate(int x, int y) {
|
||||||
|
Log.d(TAG, "onPositionUpdate: x=" + x + " y=" + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShow() {
|
||||||
|
Log.d(TAG, "onShow");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHide() {
|
||||||
|
Log.d(TAG, "onHide");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDismiss() {
|
||||||
|
Log.d(TAG, "onDismiss");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoveAnimStart() {
|
||||||
|
Log.d(TAG, "onMoveAnimStart");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoveAnimEnd() {
|
||||||
|
Log.d(TAG, "onMoveAnimEnd");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackToDesktop() {
|
||||||
|
Log.d(TAG, "onBackToDesktop");
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v4.view.GravityCompat;
|
import android.support.v4.view.GravityCompat;
|
||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
import android.support.v7.app.ActionBarDrawerToggle;
|
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
@ -81,7 +81,9 @@ public class MainActivity extends AppCompatActivity
|
||||||
private void initUi()
|
private void initUi()
|
||||||
{
|
{
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
|
//toolbar.setTitle("hehehe");
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
//toolbar.setTitle("hehehe");
|
||||||
fab = (FloatingActionButton) findViewById(R.id.fab);
|
fab = (FloatingActionButton) findViewById(R.id.fab);
|
||||||
fab.setOnClickListener(new View.OnClickListener() {
|
fab.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -338,20 +338,20 @@ public void getServerData()
|
||||||
inflater.inflate(R.menu.main, menu);
|
inflater.inflate(R.menu.main, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
// public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
// Handle action bar item clicks here. The action bar will
|
// // Handle action bar item clicks here. The action bar will
|
||||||
// automatically handle clicks on the Home/Up button, so long
|
// // automatically handle clicks on the Home/Up button, so long
|
||||||
// as you specify a parent activity in AndroidManifest.xml.
|
// // as you specify a parent activity in AndroidManifest.xml.
|
||||||
int id = item.getItemId();
|
// int id = item.getItemId();
|
||||||
|
//
|
||||||
//noinspection SimplifiableIfStatement
|
// //noinspection SimplifiableIfStatement
|
||||||
if (id == R.id.action_settings) {
|
// if (id == R.id.action_settings) {
|
||||||
new SystemUtils(getActivity()).setBoolean("isTran",true);
|
// new SystemUtils(getActivity()).setBoolean("isTran",true);
|
||||||
mGrid.setAlpha(0.55f);
|
// mGrid.setAlpha(0.55f);
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return super.onOptionsItemSelected(item);
|
// return super.onOptionsItemSelected(item);
|
||||||
}
|
// }
|
||||||
}
|
}
|
Binary file not shown.
After Width: | Height: | Size: 171 KiB |
|
@ -7,6 +7,122 @@
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
tools:context="com.example.administrator.myapplication.ui.MainActivity">
|
tools:context="com.example.administrator.myapplication.ui.MainActivity">
|
||||||
|
|
||||||
|
<!--<android.support.design.widget.FloatingActionButton-->
|
||||||
|
<!--android:id="@+id/fab"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--android:layout_gravity="bottom|end"-->
|
||||||
|
<!--android:layout_margin="@dimen/fab_margin"-->
|
||||||
|
<!--app:borderWidth="0dp"-->
|
||||||
|
<!--app:elevation="4dp"-->
|
||||||
|
<!--app:rippleColor="@android:color/transparent"-->
|
||||||
|
<!--android:src="@drawable/actionbar_icon_add" />-->
|
||||||
|
|
||||||
|
<!--<android.support.design.widget.AppBarLayout-->
|
||||||
|
<!--android:layout_width="match_parent"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--android:theme="@style/AppTheme.AppBarOverlay">-->
|
||||||
|
|
||||||
|
<!--<!–<LinearLayout-->
|
||||||
|
<!--android:layout_width="match_parent"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--android:background="@color/black"-->
|
||||||
|
<!-->-->
|
||||||
|
|
||||||
|
<!--<ImageButton-->
|
||||||
|
<!--android:id="@+id/app_bar_menubt"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--android:src="@drawable/app_bar_menu"-->
|
||||||
|
<!--/>-->
|
||||||
|
|
||||||
|
<!--<android.support.design.widget.TabLayout-->
|
||||||
|
<!--android:id="@+id/app_bar_tablayout"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="30dp"-->
|
||||||
|
<!-->-->
|
||||||
|
<!--</android.support.design.widget.TabLayout>-->
|
||||||
|
|
||||||
|
<!--<ImageButton-->
|
||||||
|
<!--android:id="@+id/app_bar_menu"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--android:layout_marginEnd="1dp"-->
|
||||||
|
<!--android:src="@drawable/app_bar_search"/>-->
|
||||||
|
|
||||||
|
|
||||||
|
<!--</LinearLayout>–>-->
|
||||||
|
|
||||||
|
<!--<!–<android.support.v7.widget.Toolbar-->
|
||||||
|
<!--android:id="@+id/toolbar"-->
|
||||||
|
<!--android:layout_width="match_parent"-->
|
||||||
|
<!--android:layout_height="?attr/actionBarSize"-->
|
||||||
|
<!--android:background="?attr/colorPrimary"-->
|
||||||
|
<!--app:popupTheme="@style/AppTheme.PopupOverlay"/>-->
|
||||||
|
<!--–>-->
|
||||||
|
<!--<RelativeLayout-->
|
||||||
|
<!--android:layout_width="match_parent"-->
|
||||||
|
<!--android:layout_height="40dp"-->
|
||||||
|
<!-->-->
|
||||||
|
|
||||||
|
<!--<ImageButton-->
|
||||||
|
<!--android:id="@+id/app_bar_menu"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--app:srcCompat="@drawable/app_bar_menu"/>-->
|
||||||
|
|
||||||
|
<!--<android.support.design.widget.TabLayout-->
|
||||||
|
<!--android:id="@+id/app_bar_tablayout"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--app:tabGravity="center"-->
|
||||||
|
<!--app:tabSelectedTextColor="@color/black"-->
|
||||||
|
<!--android:layout_alignParentTop="true"-->
|
||||||
|
<!--android:layout_centerHorizontal="true">-->
|
||||||
|
|
||||||
|
<!--<android.support.design.widget.TabItem-->
|
||||||
|
<!--android:id="@+id/app_bar_item1"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--android:text="文章"/>-->
|
||||||
|
|
||||||
|
<!--<android.support.design.widget.TabItem-->
|
||||||
|
<!--android:id="@+id/app_bar_item2"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--android:text="图片"/>-->
|
||||||
|
|
||||||
|
<!--</android.support.design.widget.TabLayout>-->
|
||||||
|
|
||||||
|
<!--<ImageButton-->
|
||||||
|
<!--android:id="@+id/app_bar_search"-->
|
||||||
|
<!--android:layout_width="wrap_content"-->
|
||||||
|
<!--android:layout_height="wrap_content"-->
|
||||||
|
<!--app:srcCompat="?android:attr/actionModeWebSearchDrawable"-->
|
||||||
|
<!--android:layout_alignParentTop="true"-->
|
||||||
|
<!--android:layout_alignParentEnd="true"/>-->
|
||||||
|
<!--</RelativeLayout>-->
|
||||||
|
|
||||||
|
<!--</android.support.design.widget.AppBarLayout>-->
|
||||||
|
|
||||||
|
<!--<include layout="@layout/content_main"/>-->
|
||||||
|
|
||||||
|
<!--</android.support.design.widget.CoordinatorLayout>-->
|
||||||
|
|
||||||
|
<android.support.design.widget.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="@style/AppTheme.AppBarOverlay">
|
||||||
|
|
||||||
|
<android.support.v7.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||||
|
|
||||||
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
<include layout="@layout/content_main" />
|
<include layout="@layout/content_main" />
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
<android.support.design.widget.FloatingActionButton
|
||||||
|
@ -20,48 +136,4 @@
|
||||||
app:rippleColor="@android:color/transparent"
|
app:rippleColor="@android:color/transparent"
|
||||||
android:src="@drawable/actionbar_icon_add" />
|
android:src="@drawable/actionbar_icon_add" />
|
||||||
|
|
||||||
<android.support.design.widget.AppBarLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:theme="@style/AppTheme.AppBarOverlay">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/black"
|
|
||||||
>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/app_bar_menubt"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/app_bar_menu"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<android.support.design.widget.TabLayout
|
|
||||||
android:id="@+id/app_bar_tablayout"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="30dp"
|
|
||||||
>
|
|
||||||
</android.support.design.widget.TabLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/app_bar_menu"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="1dp"
|
|
||||||
android:src="@drawable/app_bar_search"/>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<android.support.v7.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
android:background="?attr/colorPrimary"
|
|
||||||
app:popupTheme="@style/AppTheme.PopupOverlay"/>
|
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
|
||||||
|
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
|
|
@ -2,8 +2,16 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
<item
|
<item
|
||||||
|
android:id="@+id/action_search"
|
||||||
|
android:icon="@drawable/ic_search_black_48dp"
|
||||||
|
android:orderInCategory="80"
|
||||||
|
android:title="search"
|
||||||
|
app:actionViewClass="android.support.v7.widget.SearchView"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
<!--分享菜单-->
|
||||||
|
<!--item
|
||||||
android:id="@+id/action_settings"
|
android:id="@+id/action_settings"
|
||||||
android:orderInCategory="100"
|
android:orderInCategory="100"
|
||||||
android:title="@string/action_settings"
|
android:title="@string/action_settings"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" /-->
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
<color name="orange">#FFA500</color><!--橙色 -->
|
<color name="orange">#FFA500</color><!--橙色 -->
|
||||||
<color name="lightsalmon">#FFA07A</color><!--亮肉色 -->
|
<color name="lightsalmon">#FFA07A</color><!--亮肉色 -->
|
||||||
<color name="darkorange">#FF8C00</color><!--暗桔黄色 -->
|
<color name="darkorange">#FF8C00</color><!--暗桔黄色 -->
|
||||||
<color name="coral">#FF7F50</color><!--珊瑚色 -->
|
<color name="coral">#ff7f50</color><!--珊瑚色 -->
|
||||||
<color name="hotpink">#FF69B4</color><!--热粉红色 -->
|
<color name="hotpink">#FF69B4</color><!--热粉红色 -->
|
||||||
<color name="tomato">#FF6347</color><!--西红柿色 -->
|
<color name="tomato">#FF6347</color><!--西红柿色 -->
|
||||||
<color name="orangered">#FF4500</color><!--红橙色 -->
|
<color name="orangered">#FF4500</color><!--红橙色 -->
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
<color name="oldlace">#FDF5E6</color><!--老花色 -->
|
<color name="oldlace">#FDF5E6</color><!--老花色 -->
|
||||||
<color name="lightgoldenrodyellow">#FAFAD2</color><!--亮金黄色 -->
|
<color name="lightgoldenrodyellow">#FAFAD2</color><!--亮金黄色 -->
|
||||||
<color name="linen">#FAF0E6</color><!--亚麻色 -->
|
<color name="linen">#FAF0E6</color><!--亚麻色 -->
|
||||||
<color name="antiquewhite">#FAEBD7</color><!--古董白 -->
|
<color name="antiquewhite">#faebd7</color><!--古董白 -->
|
||||||
<color name="salmon">#FA8072</color><!--鲜肉色 -->
|
<color name="salmon">#FA8072</color><!--鲜肉色 -->
|
||||||
<color name="ghostwhite">#F8F8FF</color><!--幽灵白 -->
|
<color name="ghostwhite">#F8F8FF</color><!--幽灵白 -->
|
||||||
<color name="mintcream">#F5FFFA</color><!--薄荷色 -->
|
<color name="mintcream">#F5FFFA</color><!--薄荷色 -->
|
||||||
|
|
|
@ -7,6 +7,8 @@ buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
classpath 'com.android.tools.build:gradle:2.3.3'
|
||||||
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
||||||
|
classpath 'com.android.tools.build:gradle:2.3.3'
|
||||||
|
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
}
|
}
|
||||||
|
@ -16,6 +18,7 @@ allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
|
maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -0,0 +1,38 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 26
|
||||||
|
buildToolsVersion "26.0.2"
|
||||||
|
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 19
|
||||||
|
targetSdkVersion 26
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||||
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
|
})
|
||||||
|
compile 'com.android.support:appcompat-v7:26.+'
|
||||||
|
testCompile 'junit:junit:4.12'
|
||||||
|
}
|
||||||
|
|
||||||
|
// JitPack Maven
|
||||||
|
apply plugin: 'com.github.dcendents.android-maven'
|
||||||
|
// Your Group
|
||||||
|
group='com.github.yhaolpz'
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.example.fixedfloatwindow;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.test.InstrumentationRegistry;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
public void useAppContext() throws Exception {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||||
|
|
||||||
|
assertEquals("com.example.fixedfloatwindow.test", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.fixedfloatwindow">
|
||||||
|
<application>
|
||||||
|
<activity
|
||||||
|
android:name="com.yhao.floatwindow.FloatActivity"
|
||||||
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
|
android:launchMode="standard"
|
||||||
|
android:theme="@style/permission_PermissionActivity"
|
||||||
|
android:windowSoftInputMode="stateHidden|stateAlwaysHidden"/>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
|
@ -0,0 +1,87 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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;
|
||||||
|
private static PermissionListener mPermissionListener;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
requestAlertWindowPermission();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
|
private void requestAlertWindowPermission() {
|
||||||
|
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
|
||||||
|
intent.setData(Uri.parse("package:" + getPackageName()));
|
||||||
|
startActivityForResult(intent, 756232212);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == 756232212) {
|
||||||
|
if (PermissionUtil.hasPermissionOnActivityResult(this)) {
|
||||||
|
mPermissionListener.onSuccess();
|
||||||
|
} else {
|
||||||
|
mPermissionListener.onFail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
static synchronized void request(Context context, PermissionListener permissionListener) {
|
||||||
|
if (PermissionUtil.hasPermission(context)) {
|
||||||
|
permissionListener.onSuccess();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mPermissionListenerList == null) {
|
||||||
|
mPermissionListenerList = new ArrayList<>();
|
||||||
|
mPermissionListener = new PermissionListener() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
for (PermissionListener listener : mPermissionListenerList) {
|
||||||
|
listener.onSuccess();
|
||||||
|
}
|
||||||
|
mPermissionListenerList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFail() {
|
||||||
|
for (PermissionListener listener : mPermissionListenerList) {
|
||||||
|
listener.onFail();
|
||||||
|
}
|
||||||
|
mPermissionListenerList.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Intent intent = new Intent(context, FloatActivity.class);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
mPermissionListenerList.add(permissionListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
private static ResumedListener sResumedListener;
|
||||||
|
private static int num = 0;
|
||||||
|
|
||||||
|
|
||||||
|
FloatLifecycle(Context applicationContext, boolean showFlag, Class[] activities, LifecycleListener lifecycleListener) {
|
||||||
|
this.showFlag = showFlag;
|
||||||
|
this.activities = activities;
|
||||||
|
num++;
|
||||||
|
mLifecycleListener = lifecycleListener;
|
||||||
|
mHandler = new Handler();
|
||||||
|
((Application) applicationContext).registerActivityLifecycleCallbacks(this);
|
||||||
|
applicationContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setResumedListener(ResumedListener resumedListener) {
|
||||||
|
sResumedListener = resumedListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (sResumedListener != null) {
|
||||||
|
num--;
|
||||||
|
if (num == 0) {
|
||||||
|
sResumedListener.onResumed();
|
||||||
|
sResumedListener = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resumeCount++;
|
||||||
|
if (needShow(activity)) {
|
||||||
|
mLifecycleListener.onShow();
|
||||||
|
} else {
|
||||||
|
mLifecycleListener.onHide();
|
||||||
|
}
|
||||||
|
if (appBackground) {
|
||||||
|
appBackground = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityPaused(final Activity activity) {
|
||||||
|
resumeCount--;
|
||||||
|
mHandler.postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (resumeCount == 0) {
|
||||||
|
appBackground = true;
|
||||||
|
mLifecycleListener.onBackToDesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, delay);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStarted(Activity activity) {
|
||||||
|
startCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStopped(Activity activity) {
|
||||||
|
startCount--;
|
||||||
|
if (startCount == 0) {
|
||||||
|
mLifecycleListener.onBackToDesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.onBackToDesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityDestroyed(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
|
||||||
|
class FloatPhone extends FloatView {
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
private final WindowManager mWindowManager;
|
||||||
|
private final WindowManager.LayoutParams mLayoutParams;
|
||||||
|
private View mView;
|
||||||
|
private int mX, mY;
|
||||||
|
private boolean isRemove = false;
|
||||||
|
private PermissionListener mPermissionListener;
|
||||||
|
|
||||||
|
FloatPhone(Context applicationContext, PermissionListener permissionListener) {
|
||||||
|
mContext = applicationContext;
|
||||||
|
mPermissionListener = permissionListener;
|
||||||
|
mWindowManager = (WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
mLayoutParams = new WindowManager.LayoutParams();
|
||||||
|
mLayoutParams.format = PixelFormat.RGBA_8888;
|
||||||
|
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||||
|
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||||
|
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
|
||||||
|
mLayoutParams.windowAnimations = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSize(int width, int height) {
|
||||||
|
mLayoutParams.width = width;
|
||||||
|
mLayoutParams.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setView(View view) {
|
||||||
|
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.N_MR1) {
|
||||||
|
req();
|
||||||
|
} else if (Miui.rom()) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
req();
|
||||||
|
} else {
|
||||||
|
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
|
||||||
|
Miui.req(mContext, new PermissionListener() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
mWindowManager.addView(mView, mLayoutParams);
|
||||||
|
if (mPermissionListener != null) {
|
||||||
|
mPermissionListener.onSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFail() {
|
||||||
|
if (mPermissionListener != null) {
|
||||||
|
mPermissionListener.onFail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
mLayoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;
|
||||||
|
mWindowManager.addView(mView, mLayoutParams);
|
||||||
|
} catch (Exception e) {
|
||||||
|
mWindowManager.removeView(mView);
|
||||||
|
LogUtil.e("TYPE_TOAST 失败");
|
||||||
|
req();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void req() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||||
|
} else {
|
||||||
|
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
|
||||||
|
}
|
||||||
|
FloatActivity.request(mContext, new PermissionListener() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
mWindowManager.addView(mView, mLayoutParams);
|
||||||
|
if (mPermissionListener != null) {
|
||||||
|
mPermissionListener.onSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFail() {
|
||||||
|
if (mPermissionListener != null) {
|
||||||
|
mPermissionListener.onFail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dismiss() {
|
||||||
|
isRemove = true;
|
||||||
|
mWindowManager.removeView(mView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateXY(int x, int y) {
|
||||||
|
if (isRemove) return;
|
||||||
|
mLayoutParams.x = mX = x;
|
||||||
|
mLayoutParams.y = mY = y;
|
||||||
|
mWindowManager.updateViewLayout(mView, mLayoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void updateX(int x) {
|
||||||
|
if (isRemove) return;
|
||||||
|
mLayoutParams.x = mX = x;
|
||||||
|
mWindowManager.updateViewLayout(mView, mLayoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void updateY(int y) {
|
||||||
|
if (isRemove) return;
|
||||||
|
mLayoutParams.y = mY = y;
|
||||||
|
mWindowManager.updateViewLayout(mView, mLayoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getX() {
|
||||||
|
return mX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getY() {
|
||||||
|
return mY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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 方式,无需申请权限
|
||||||
|
* 当前版本暂时用 TYPE_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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,222 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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.slide;
|
||||||
|
int mSlideLeftMargin;
|
||||||
|
int mSlideRightMargin;
|
||||||
|
long mDuration = 300;
|
||||||
|
TimeInterpolator mInterpolator;
|
||||||
|
private String mTag = mDefaultTag;
|
||||||
|
boolean mDesktopShow;
|
||||||
|
PermissionListener mPermissionListener;
|
||||||
|
ViewStateListener mViewStateListener;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return setMoveType(moveType, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置带边距的贴边动画,只有 moveType 为 MoveType.slide,设置边距才有意义,这个方法不标准,后面调整
|
||||||
|
*
|
||||||
|
* @param moveType 贴边动画 MoveType.slide
|
||||||
|
* @param slideLeftMargin 贴边动画左边距,默认为 0
|
||||||
|
* @param slideRightMargin 贴边动画右边距,默认为 0
|
||||||
|
*/
|
||||||
|
public B setMoveType(@MoveType.MOVE_TYPE int moveType, int slideLeftMargin, int slideRightMargin) {
|
||||||
|
mMoveType = moveType;
|
||||||
|
mSlideLeftMargin = slideLeftMargin;
|
||||||
|
mSlideRightMargin = slideRightMargin;
|
||||||
|
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 B setDesktopShow(boolean show) {
|
||||||
|
mDesktopShow = show;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setPermissionListener(PermissionListener listener) {
|
||||||
|
mPermissionListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setViewStateListener(ViewStateListener listener) {
|
||||||
|
mViewStateListener = listener;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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 boolean isShowing();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -0,0 +1,302 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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.annotation.SuppressLint;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
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 float downX;
|
||||||
|
private float downY;
|
||||||
|
private float upX;
|
||||||
|
private float upY;
|
||||||
|
private boolean mClick = false;
|
||||||
|
private int mSlop;
|
||||||
|
|
||||||
|
|
||||||
|
private IFloatWindowImpl() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IFloatWindowImpl(FloatWindow.B b) {
|
||||||
|
mB = b;
|
||||||
|
if (mB.mMoveType == MoveType.fixed) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||||
|
mFloatView = new FloatPhone(b.mApplicationContext, mB.mPermissionListener);
|
||||||
|
} else {
|
||||||
|
mFloatView = new FloatToast(b.mApplicationContext);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mFloatView = new FloatPhone(b.mApplicationContext, mB.mPermissionListener);
|
||||||
|
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 onBackToDesktop() {
|
||||||
|
if (!mB.mDesktopShow) {
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onBackToDesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void show() {
|
||||||
|
if (once) {
|
||||||
|
mFloatView.init();
|
||||||
|
once = false;
|
||||||
|
isShow = true;
|
||||||
|
} else {
|
||||||
|
if (isShow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getView().setVisibility(View.VISIBLE);
|
||||||
|
isShow = true;
|
||||||
|
}
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onShow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hide() {
|
||||||
|
if (once || !isShow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getView().setVisibility(View.INVISIBLE);
|
||||||
|
isShow = false;
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onHide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShowing() {
|
||||||
|
return isShow;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void dismiss() {
|
||||||
|
mFloatView.dismiss();
|
||||||
|
isShow = false;
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onDismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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() {
|
||||||
|
mSlop = ViewConfiguration.get(mB.mApplicationContext).getScaledTouchSlop();
|
||||||
|
return mB.mView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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.inactive:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
getView().setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
float lastX, lastY, changeX, changeY;
|
||||||
|
int newX, newY;
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
downX = event.getRawX();
|
||||||
|
downY = event.getRawY();
|
||||||
|
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);
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onPositionUpdate(newX, newY);
|
||||||
|
}
|
||||||
|
lastX = event.getRawX();
|
||||||
|
lastY = event.getRawY();
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
upX = event.getRawX();
|
||||||
|
upY = event.getRawY();
|
||||||
|
mClick = (Math.abs(upX - downX) > mSlop) || (Math.abs(upY - downY) > mSlop);
|
||||||
|
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() - mB.mSlideRightMargin :
|
||||||
|
mB.mSlideLeftMargin;
|
||||||
|
mAnimator = ObjectAnimator.ofInt(startX, endX);
|
||||||
|
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationUpdate(ValueAnimator animation) {
|
||||||
|
int x = (int) animation.getAnimatedValue();
|
||||||
|
mFloatView.updateX(x);
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onPositionUpdate(x, (int) upY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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);
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onPositionUpdate(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
startAnimator();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return mClick;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onMoveAnimEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mAnimator.setDuration(mB.mDuration).start();
|
||||||
|
if (mB.mViewStateListener != null) {
|
||||||
|
mB.mViewStateListener.onMoveAnimStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelAnimator() {
|
||||||
|
if (mAnimator != null && mAnimator.isRunning()) {
|
||||||
|
mAnimator.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2017/12/22.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface LifecycleListener {
|
||||||
|
|
||||||
|
void onShow();
|
||||||
|
|
||||||
|
void onHide();
|
||||||
|
|
||||||
|
void onBackToDesktop();
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2017/12/29.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
|
||||||
|
class LogUtil {
|
||||||
|
|
||||||
|
private static final String TAG = "FloatWindow";
|
||||||
|
|
||||||
|
|
||||||
|
static void e(String message) {
|
||||||
|
|
||||||
|
Log.e(TAG, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void d(String message) {
|
||||||
|
|
||||||
|
Log.d(TAG, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.yhao.floatwindow.Rom.isIntentAvailable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2017/12/30.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
* <p>
|
||||||
|
* 需要清楚:一个MIUI版本对应小米各种机型,基于不同的安卓版本,但是权限设置页跟MIUI版本有关
|
||||||
|
* 测试TYPE_TOAST类型:
|
||||||
|
* 7.0:
|
||||||
|
* 小米 5 MIUI8 -------------------- 失败
|
||||||
|
* 小米 Note2 MIUI9 -------------------- 失败
|
||||||
|
* 6.0.1
|
||||||
|
* 小米 5 -------------------- 失败
|
||||||
|
* 小米 红米note3 -------------------- 失败
|
||||||
|
* 6.0:
|
||||||
|
* 小米 5 -------------------- 成功
|
||||||
|
* 小米 红米4A MIUI8 -------------------- 成功
|
||||||
|
* 小米 红米Pro MIUI7 -------------------- 成功
|
||||||
|
* 小米 红米Note4 MIUI8 -------------------- 失败
|
||||||
|
* <p>
|
||||||
|
* 经过各种横向纵向测试对比,得出一个结论,就是小米对TYPE_TOAST的处理机制毫无规律可言!
|
||||||
|
* 跟Android版本无关,跟MIUI版本无关,addView方法也不报错
|
||||||
|
* 所以最后对小米6.0以上的适配方法是:不使用 TYPE_TOAST 类型,统一申请权限
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Miui {
|
||||||
|
|
||||||
|
private static final String miui = "ro.miui.ui.version.name";
|
||||||
|
private static final String miui5 = "V5";
|
||||||
|
private static final String miui6 = "V6";
|
||||||
|
private static final String miui7 = "V7";
|
||||||
|
private static final String miui8 = "V8";
|
||||||
|
private static final String miui9 = "V9";
|
||||||
|
private static List<PermissionListener> mPermissionListenerList;
|
||||||
|
private static PermissionListener mPermissionListener;
|
||||||
|
|
||||||
|
|
||||||
|
static boolean rom() {
|
||||||
|
LogUtil.d(" Miui : " + Miui.getProp());
|
||||||
|
return Build.MANUFACTURER.equals("Xiaomi");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getProp() {
|
||||||
|
return Rom.getProp(miui);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Android6.0以下申请权限
|
||||||
|
*/
|
||||||
|
static void req(final Context context, PermissionListener permissionListener) {
|
||||||
|
if (PermissionUtil.hasPermission(context)) {
|
||||||
|
permissionListener.onSuccess();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mPermissionListenerList == null) {
|
||||||
|
mPermissionListenerList = new ArrayList<>();
|
||||||
|
mPermissionListener = new PermissionListener() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
for (PermissionListener listener : mPermissionListenerList) {
|
||||||
|
listener.onSuccess();
|
||||||
|
}
|
||||||
|
mPermissionListenerList.clear();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onFail() {
|
||||||
|
for (PermissionListener listener : mPermissionListenerList) {
|
||||||
|
listener.onFail();
|
||||||
|
}
|
||||||
|
mPermissionListenerList.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req_(context);
|
||||||
|
}
|
||||||
|
mPermissionListenerList.add(permissionListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void req_(final Context context) {
|
||||||
|
switch (getProp()) {
|
||||||
|
case miui5:
|
||||||
|
reqForMiui5(context);
|
||||||
|
break;
|
||||||
|
case miui6:
|
||||||
|
case miui7:
|
||||||
|
reqForMiui67(context);
|
||||||
|
break;
|
||||||
|
case miui8:
|
||||||
|
case miui9:
|
||||||
|
reqForMiui89(context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FloatLifecycle.setResumedListener(new ResumedListener() {
|
||||||
|
@Override
|
||||||
|
public void onResumed() {
|
||||||
|
if (PermissionUtil.hasPermission(context)) {
|
||||||
|
mPermissionListener.onSuccess();
|
||||||
|
} else {
|
||||||
|
mPermissionListener.onFail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void reqForMiui5(Context context) {
|
||||||
|
String packageName = context.getPackageName();
|
||||||
|
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
Uri uri = Uri.fromParts("package", packageName, null);
|
||||||
|
intent.setData(uri);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
if (isIntentAvailable(intent, context)) {
|
||||||
|
context.startActivity(intent);
|
||||||
|
} else {
|
||||||
|
LogUtil.e("intent is not available!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void reqForMiui67(Context context) {
|
||||||
|
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
|
||||||
|
intent.setClassName("com.miui.securitycenter",
|
||||||
|
"com.miui.permcenter.permissions.AppPermissionsEditorActivity");
|
||||||
|
intent.putExtra("extra_pkgname", context.getPackageName());
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
if (isIntentAvailable(intent, context)) {
|
||||||
|
context.startActivity(intent);
|
||||||
|
} else {
|
||||||
|
LogUtil.e("intent is not available!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void reqForMiui89(Context context) {
|
||||||
|
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
|
||||||
|
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
|
||||||
|
intent.putExtra("extra_pkgname", context.getPackageName());
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
if (isIntentAvailable(intent, context)) {
|
||||||
|
context.startActivity(intent);
|
||||||
|
} else {
|
||||||
|
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
|
||||||
|
intent.setPackage("com.miui.securitycenter");
|
||||||
|
intent.putExtra("extra_pkgname", context.getPackageName());
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
if (isIntentAvailable(intent, context)) {
|
||||||
|
context.startActivity(intent);
|
||||||
|
} else {
|
||||||
|
LogUtil.e("intent is not available!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 有些机型在添加TYPE-TOAST类型时会自动改为TYPE_SYSTEM_ALERT,通过此方法可以屏蔽修改
|
||||||
|
* 但是...即使成功显示出悬浮窗,移动的话也会崩溃
|
||||||
|
*/
|
||||||
|
private static void addViewToWindow(WindowManager wm, View view, WindowManager.LayoutParams params) {
|
||||||
|
setMiUI_International(true);
|
||||||
|
wm.addView(view, params);
|
||||||
|
setMiUI_International(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void setMiUI_International(boolean flag) {
|
||||||
|
try {
|
||||||
|
Class BuildForMi = Class.forName("miui.os.Build");
|
||||||
|
Field isInternational = BuildForMi.getDeclaredField("IS_INTERNATIONAL_BUILD");
|
||||||
|
isInternational.setAccessible(true);
|
||||||
|
isInternational.setBoolean(null, flag);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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 inactive = 1;
|
||||||
|
public static final int active = 2;
|
||||||
|
public static final int slide = 3;
|
||||||
|
public static final int back = 4;
|
||||||
|
|
||||||
|
@IntDef({fixed, inactive, active, slide, back})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@interface MOVE_TYPE {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2017/11/14.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
public interface PermissionListener {
|
||||||
|
void onSuccess();
|
||||||
|
|
||||||
|
void onFail();
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
import android.app.AppOpsManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.support.annotation.RequiresApi;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2017/12/29.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PermissionUtil {
|
||||||
|
|
||||||
|
static boolean hasPermission(Context context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
return Settings.canDrawOverlays(context);
|
||||||
|
} else {
|
||||||
|
return hasPermissionBelowMarshmallow(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean hasPermissionOnActivityResult(Context context) {
|
||||||
|
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
|
||||||
|
return hasPermissionForO(context);
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
return Settings.canDrawOverlays(context);
|
||||||
|
} else {
|
||||||
|
return hasPermissionBelowMarshmallow(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 6.0以下判断是否有权限
|
||||||
|
* 理论上6.0以上才需处理权限,但有的国内rom在6.0以下就添加了权限
|
||||||
|
* 其实此方式也可以用于判断6.0以上版本,只不过有更简单的canDrawOverlays代替
|
||||||
|
*/
|
||||||
|
static boolean hasPermissionBelowMarshmallow(Context context) {
|
||||||
|
try {
|
||||||
|
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||||
|
Method dispatchMethod = AppOpsManager.class.getMethod("checkOp", int.class, int.class, String.class);
|
||||||
|
//AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
|
||||||
|
return AppOpsManager.MODE_ALLOWED == (Integer) dispatchMethod.invoke(
|
||||||
|
manager, 24, Binder.getCallingUid(), context.getApplicationContext().getPackageName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于判断8.0时是否有权限,仅用于OnActivityResult
|
||||||
|
* 针对8.0官方bug:在用户授予权限后Settings.canDrawOverlays或checkOp方法判断仍然返回false
|
||||||
|
*/
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
|
private static boolean hasPermissionForO(Context context) {
|
||||||
|
try {
|
||||||
|
WindowManager mgr = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
if (mgr == null) return false;
|
||||||
|
View viewToAdd = new View(context);
|
||||||
|
WindowManager.LayoutParams params = new WindowManager.LayoutParams(0, 0,
|
||||||
|
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ?
|
||||||
|
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
|
||||||
|
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||||
|
PixelFormat.TRANSPARENT);
|
||||||
|
viewToAdd.setLayoutParams(params);
|
||||||
|
mgr.addView(viewToAdd, params);
|
||||||
|
mgr.removeView(viewToAdd);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.e("hasPermissionForO e:" + e.toString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2017/12/30.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface ResumedListener {
|
||||||
|
void onResumed();
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2017/12/30.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Rom {
|
||||||
|
|
||||||
|
static boolean isIntentAvailable(Intent intent, Context context) {
|
||||||
|
return intent != null && context.getPackageManager().queryIntentActivities(
|
||||||
|
intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static String getProp(String name) {
|
||||||
|
BufferedReader input = null;
|
||||||
|
try {
|
||||||
|
Process p = Runtime.getRuntime().exec("getprop " + name);
|
||||||
|
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
|
||||||
|
String line = input.readLine();
|
||||||
|
input.close();
|
||||||
|
return line;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
if (input != null) {
|
||||||
|
try {
|
||||||
|
input.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2017/12/22.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Util {
|
||||||
|
|
||||||
|
|
||||||
|
static View inflate(Context applicationContext, int layoutId) {
|
||||||
|
LayoutInflater inflate = (LayoutInflater) applicationContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
return inflate.inflate(layoutId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isViewVisible(View view) {
|
||||||
|
return view.getGlobalVisibleRect(new Rect());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2018/5/5
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
public interface ViewStateListener {
|
||||||
|
void onPositionUpdate(int x, int y);
|
||||||
|
|
||||||
|
void onShow();
|
||||||
|
|
||||||
|
void onHide();
|
||||||
|
|
||||||
|
void onDismiss();
|
||||||
|
|
||||||
|
void onMoveAnimStart();
|
||||||
|
|
||||||
|
void onMoveAnimEnd();
|
||||||
|
|
||||||
|
void onBackToDesktop();
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.yhao.floatwindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by yhao on 2018/5/5.
|
||||||
|
* https://github.com/yhaolpz
|
||||||
|
*/
|
||||||
|
public class ViewStateListenerAdapter implements ViewStateListener{
|
||||||
|
@Override
|
||||||
|
public void onPositionUpdate(int x, int y) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShow() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHide() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDismiss() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoveAnimStart() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoveAnimEnd() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackToDesktop() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">FFWindow</string>
|
||||||
|
</resources>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<style name="permission_PermissionActivity" parent="@android:style/Theme.Translucent.NoTitleBar">
|
||||||
|
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.example.fixedfloatwindow;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() throws Exception {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1 @@
|
||||||
include ':app', ':my_library'
|
include ':app', ':floatwindow'
|
||||||
project(':my_library').projectDir = new File('library')
|
|
||||||
|
|
Loading…
Reference in New Issue