From bd8465b1fe3fa2883d9b233d458c3ba57aec0b70 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Tue, 3 Jul 2018 13:18:00 +0900 Subject: [PATCH 01/35] Update SDK(Android P) --- build.gradle | 8 ++++---- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 02b714d..245aaad 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.2' + classpath 'com.android.tools.build:gradle:3.3.0-alpha01' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -22,8 +22,8 @@ allprojects { } ext { - compileSdkVersion = 27 - buildToolsVersion = '27.0.3' - targetSdkVersion = 27 + compileSdkVersion = 28 + buildToolsVersion = '28.0.0 rc2' + targetSdkVersion = 28 minSdkVersion = 14 } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 77ad8d2..79407c7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon May 07 16:30:08 JST 2018 +#Tue Jul 03 12:45:55 JST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip From 96e1296d8632d60ea81cf58eecd9129ddd898569 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Tue, 3 Jul 2018 13:18:25 +0900 Subject: [PATCH 02/35] Add FOREGROUND_SERVICE permission --- sample/src/main/AndroidManifest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 3e1682c..2b4ed53 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -5,6 +5,8 @@ + + Date: Tue, 3 Jul 2018 13:43:54 +0900 Subject: [PATCH 03/35] Update README - FOREGROUND_PERMISSION - startForeground method (Forgot to write) --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 034c2fe..67ab2cc 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ To API Level 14 or later are supported [SimpleFloating](http://youtu.be/nb8M2p0agF4) ## Requirements -Target Sdk Version : 27 +Target Sdk Version : 28 Min Sdk Version : 14 ## How to use @@ -66,6 +66,7 @@ Describe the process (`onFinishFloatingView`) that is called when you exit the F 5) Add the permission to AndroidManifest ```xml + ``` 6) Define the Service to AndroidManifest @@ -83,11 +84,27 @@ example) ``` 7) Describe the process to start the Service (run on foreground) + + +example) + +- FloatingViewControlFragment.java + ```java final Intent intent = new Intent(activity, ChatHeadService.class); ContextCompat.startForegroundService(activity, intent); ``` +- ChatHeadService.java + +```java +public int onStartCommand(Intent intent, int flags, int startId) { + ... + startForeground(NOTIFICATION_ID, createNotification(this)); + ... +} +``` + 8) Create notification channel (targetSdkVersion >= 26) example) From 12b968172b84de70d792f7374ad286733e01b93b Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 2 Aug 2018 10:39:24 +0900 Subject: [PATCH 04/35] Update gradle version --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 245aaad..d7bd7a7 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0-alpha01' + classpath 'com.android.tools.build:gradle:3.3.0-alpha03' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 79407c7..d96358e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Jul 03 12:45:55 JST 2018 +#Thu Aug 02 10:32:15 JST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-rc-1-all.zip From d6eb8c19f7cc4f9139ed3a4163639738dcaf6252 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 2 Aug 2018 15:50:27 +0900 Subject: [PATCH 05/35] Add cutout's safe inset area - It passed SafeInsetArea from Fragment to FloatingView - If there is Cutout, touch position moves upward Fixed problem (portrait only) --- .../android/floatingview/FloatingView.java | 35 +++++++++- .../floatingview/FloatingViewManager.java | 21 ++++++ .../fragment/FloatingViewControlFragment.java | 66 ++++++++++--------- .../sample/service/ChatHeadService.java | 7 ++ .../service/CustomFloatingViewService.java | 7 ++ 5 files changed, 101 insertions(+), 35 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index 6b44ae5..98dd253 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -388,6 +388,11 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList */ private int mRotation; + /** + * Cutout safe inset rect(Same as FloatingViewManager's mSafeInsetRect) + */ + private final Rect mSafeInsetRect; + static { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) { OVERLAY_TYPE = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; @@ -427,6 +432,7 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList mMoveLimitRect = new Rect(); mPositionLimitRect = new Rect(); + mSafeInsetRect = new Rect(); // ステータスバーの高さを取得 mBaseStatusBarHeight = getSystemUiDimensionPixelSize(resources, "status_bar_height"); @@ -620,7 +626,7 @@ private void refreshLimitRect() { // 移動範囲の設定 mMoveLimitRect.set(-width, -height * 2, newScreenWidth + width + mNavigationBarHorizontalOffset, newScreenHeight + height + mNavigationBarVerticalOffset); - mPositionLimitRect.set(-mOverMargin, 0, newScreenWidth - width + mOverMargin + mNavigationBarHorizontalOffset, newScreenHeight - mStatusBarHeight - height + mNavigationBarVerticalOffset); + mPositionLimitRect.set(-mOverMargin, 0, newScreenWidth - width + mOverMargin + mNavigationBarHorizontalOffset, newScreenHeight - mStatusBarHeight + mSafeInsetRect.top - height + mNavigationBarVerticalOffset); // Initial animation stop when the device rotates final int newRotation = mWindowManager.getDefaultDisplay().getRotation(); @@ -1327,7 +1333,7 @@ private int getXByTouch() { * @return FloatingViewのY座標 */ private int getYByTouch() { - return (int) (mMetrics.heightPixels + mNavigationBarVerticalOffset - (mScreenTouchY - mLocalTouchY + getHeight())); + return (int) (mMetrics.heightPixels + mNavigationBarVerticalOffset + mSafeInsetRect.top - (mScreenTouchY - mLocalTouchY + getHeight())); } /** @@ -1362,6 +1368,29 @@ int getState() { return mAnimationHandler.getState(); } + /** + * Set the cutout's safe inset area + * + * @param safeInsetRect {@link FloatingViewManager#setSafeInsetRect(Rect)} + */ + void setSafeInsetRect(Rect safeInsetRect) { + mSafeInsetRect.set(safeInsetRect); + + // Check Cutout size + final int currentStatusBarHeight = mStatusBarHeight; + if (mStatusBarHeight > mSafeInsetRect.top) { + mStatusBarHeight = currentStatusBarHeight - mSafeInsetRect.top; + } else { + // mStatusBarHeight is not included in mMetrics.heightPixels + mStatusBarHeight = 0; + } + + // Refresh Limit Rect + if (currentStatusBarHeight != mStatusBarHeight) { + refreshLimitRect(); + } + } + /** * アニメーションの制御を行うハンドラです。 */ @@ -1520,7 +1549,7 @@ else if (mState == FloatingView.STATE_INTERSECTING) { * アニメーション時間から求められる位置を計算します。 * * @param timeRate 時間比率 - * @return ベースとなる係数(0.0から1.0+α) + * @return ベースとなる係数(0.0から1.0 + α) */ private static float calcAnimationPosition(float timeRate) { final float position; diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index ce1e094..0b9074c 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -174,6 +174,11 @@ public class FloatingViewManager implements ScreenChangedListener, View.OnTouchL @DisplayMode private int mDisplayMode; + /** + * Cutout safe inset rect + */ + private final Rect mSafeInsetRect; + /** * Windowに貼り付けられたFloatingViewのリスト * TODO:第2弾のFloatingViewの複数表示で意味を発揮する予定 @@ -196,6 +201,7 @@ public FloatingViewManager(Context context, FloatingViewListener listener) { mTrashViewRect = new Rect(); mIsMoveAccept = false; mDisplayMode = DISPLAY_MODE_HIDE_FULLSCREEN; + mSafeInsetRect = new Rect(); // FloatingViewと連携するViewの構築 mFloatingViewList = new ArrayList<>(); @@ -467,6 +473,20 @@ public boolean isTrashViewEnabled() { return mTrashView.isTrashEnabled(); } + /** + * Set the DisplayCutout's safe area + * + * @param safeInsetRect DisplayCutout#getSafeInsetXXX + */ + public void setSafeInsetRect(Rect safeInsetRect) { + if (safeInsetRect == null) { + mSafeInsetRect.setEmpty(); + } else { + mSafeInsetRect.set(safeInsetRect); + } + //TODO:update Layout + } + /** * ViewをWindowに貼り付けます。 * @@ -484,6 +504,7 @@ public void addViewToWindow(View view, Options options) { floatingView.setMoveDirection(options.moveDirection); floatingView.usePhysics(options.usePhysics); floatingView.setAnimateInitialMove(options.animateInitialMove); + floatingView.setSafeInsetRect(mSafeInsetRect); // set FloatingView size final FrameLayout.LayoutParams targetParams = new FrameLayout.LayoutParams(options.floatingViewWidth, options.floatingViewHeight); diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index 58677e7..a847eb3 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -2,15 +2,18 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; +import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; +import android.graphics.Rect; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.support.v4.content.ContextCompat; +import android.view.DisplayCutout; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -65,14 +68,14 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa rootView.findViewById(R.id.show_demo).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - showChatHead(getActivity(), true); + showFloatingView(getActivity(), true, false); } }); // カスタマイズデモの表示 rootView.findViewById(R.id.show_customized_demo).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - showCustomFloatingView(getActivity(), true); + showFloatingView(getActivity(), true, true); } }); // 設定画面の表示 @@ -96,31 +99,30 @@ public void onClick(View v) { @TargetApi(Build.VERSION_CODES.M) public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CHATHEAD_OVERLAY_PERMISSION_REQUEST_CODE) { - showChatHead(getActivity(), false); + showFloatingView(getActivity(), false, false); } else if (requestCode == CUSTOM_OVERLAY_PERMISSION_REQUEST_CODE) { - showCustomFloatingView(getActivity(), false); + showFloatingView(getActivity(), false, true); } } /** - * シンプルなFloatingViewの表示 + * FloatingViewの表示 * * @param context Context * @param isShowOverlayPermission 表示できなかった場合に表示許可の画面を表示するフラグ + * @param isCustomFloatingView If true, it launches CustomFloatingViewService. */ @SuppressLint("NewApi") - private void showChatHead(Context context, boolean isShowOverlayPermission) { + private void showFloatingView(Context context, boolean isShowOverlayPermission, boolean isCustomFloatingView) { // API22以下かチェック if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { - final Intent intent = new Intent(context, ChatHeadService.class); - ContextCompat.startForegroundService(context, intent); + startFloatingViewService(getActivity(), isCustomFloatingView); return; } // 他のアプリの上に表示できるかチェック if (Settings.canDrawOverlays(context)) { - final Intent intent = new Intent(context, ChatHeadService.class); - ContextCompat.startForegroundService(context, intent); + startFloatingViewService(getActivity(), isCustomFloatingView); return; } @@ -132,31 +134,31 @@ private void showChatHead(Context context, boolean isShowOverlayPermission) { } /** - * カスタマイズFloatingViewの表示 + * Start floating view service * - * @param context Context - * @param isShowOverlayPermission 表示できなかった場合に表示許可の画面を表示するフラグ + * @param activity {@link Activity} + * @param isCustomFloatingView If true, it launches CustomFloatingViewService. */ - @SuppressLint("NewApi") - private void showCustomFloatingView(Context context, boolean isShowOverlayPermission) { - // API22以下かチェック - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { - final Intent intent = new Intent(context, CustomFloatingViewService.class); - ContextCompat.startForegroundService(context, intent); - return; - } - - // 他のアプリの上に表示できるかチェック - if (Settings.canDrawOverlays(context)) { - final Intent intent = new Intent(context, CustomFloatingViewService.class); - ContextCompat.startForegroundService(context, intent); - return; + private static void startFloatingViewService(Activity activity, boolean isCustomFloatingView) { + // set safe inset area + final Rect safeInsetRect = new Rect(); + // TODO:Rewrite with android-x + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + final DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); + if (displayCutout != null) { + safeInsetRect.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom()); + } } - // オーバレイパーミッションの表示 - if (isShowOverlayPermission) { - final Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName())); - startActivityForResult(intent, CUSTOM_OVERLAY_PERMISSION_REQUEST_CODE); + // launch service + if (isCustomFloatingView) { + final Intent intent = new Intent(activity, CustomFloatingViewService.class); + intent.putExtra(CustomFloatingViewService.EXTRA_CUTOUT_SAFE_AREA, safeInsetRect); + ContextCompat.startForegroundService(activity, intent); + } else { + final Intent intent = new Intent(activity, ChatHeadService.class); + intent.putExtra(ChatHeadService.EXTRA_CUTOUT_SAFE_AREA, safeInsetRect); + ContextCompat.startForegroundService(activity, intent); } } -} +} \ No newline at end of file diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/service/ChatHeadService.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/service/ChatHeadService.java index d11cd2a..9f2feac 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/service/ChatHeadService.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/service/ChatHeadService.java @@ -4,6 +4,7 @@ import android.app.Service; import android.content.Context; import android.content.Intent; +import android.graphics.Rect; import android.os.IBinder; import android.support.v4.app.NotificationCompat; import android.util.DisplayMetrics; @@ -28,6 +29,11 @@ public class ChatHeadService extends Service implements FloatingViewListener { */ private static final String TAG = "ChatHeadService"; + /** + * Intent key (Cutout safe area) + */ + public static final String EXTRA_CUTOUT_SAFE_AREA = "cutout_safe_area"; + /** * 通知ID */ @@ -63,6 +69,7 @@ public void onClick(View v) { mFloatingViewManager = new FloatingViewManager(this, this); mFloatingViewManager.setFixedTrashIconImage(R.drawable.ic_trash_fixed); mFloatingViewManager.setActionTrashIconImage(R.drawable.ic_trash_action); + mFloatingViewManager.setSafeInsetRect((Rect) intent.getParcelableExtra(EXTRA_CUTOUT_SAFE_AREA)); final FloatingViewManager.Options options = new FloatingViewManager.Options(); options.overMargin = (int) (16 * metrics.density); mFloatingViewManager.addViewToWindow(iconView, options); diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/service/CustomFloatingViewService.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/service/CustomFloatingViewService.java index 4646241..aac0930 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/service/CustomFloatingViewService.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/service/CustomFloatingViewService.java @@ -6,6 +6,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.graphics.Rect; import android.net.Uri; import android.os.IBinder; import android.preference.PreferenceManager; @@ -29,6 +30,11 @@ */ public class CustomFloatingViewService extends Service implements FloatingViewListener { + /** + * Intent key (Cutout safe area) + */ + public static final String EXTRA_CUTOUT_SAFE_AREA = "cutout_safe_area"; + /** * 通知ID */ @@ -79,6 +85,7 @@ public void onClick(View v) { mFloatingViewManager = new FloatingViewManager(this, this); mFloatingViewManager.setFixedTrashIconImage(R.drawable.ic_trash_fixed); mFloatingViewManager.setActionTrashIconImage(R.drawable.ic_trash_action); + mFloatingViewManager.setSafeInsetRect((Rect) intent.getParcelableExtra(EXTRA_CUTOUT_SAFE_AREA)); // Setting Options(you can change options at any time) loadDynamicOptions(); // Initial Setting Options (you can't change options after created.) From d63e45c384d6d12c15355882bfaf6be9bed48734 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 2 Aug 2018 16:05:54 +0900 Subject: [PATCH 06/35] Update README.md --- README.md | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 67ab2cc..a103af3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # FloatingView The Android project is View to display information such as chat in front. -To API Level 14 or later are supported +To API Level 14 or higher are supported ## Screenshots ![](./screenshot/animation.gif) @@ -121,6 +121,35 @@ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ``` +9) Add DisplayCutout process(API Level >= 28) + +Note: `DisplayCutout` is obtained from `Fragment` or `Activity` (`Service` can not be acquired) + +example) + +- FloatingViewControlFragment.java + +```java +final Rect safeInsetRect = new Rect(); +if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + final DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); + if (displayCutout != null) { + safeInsetRect.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom()); + } +} + +final Intent intent = new Intent(activity, ChatHeadService.class); +intent.putExtra(ChatHeadService.EXTRA_CUTOUT_SAFE_AREA, safeInsetRect); +ContextCompat.startForegroundService(activity, intent); +``` + +- ChatHeadService.java + +```java +mFloatingViewManager.setSafeInsetRect((Rect) intent.getParcelableExtra(EXTRA_CUTOUT_SAFE_AREA)); +``` + + ## Static Options It can be set only when displaying for the first time From d6afbfd9fbda28cf54abb70c66910f7e4ef13469 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 3 Aug 2018 10:42:36 +0900 Subject: [PATCH 07/35] Remove If statement when the status bar and SafeInsetRect are different - "In portrait orientation, with no special flags set, the status bar must extend to at least the height of the cutout." --- .../android/floatingview/FloatingView.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index 98dd253..74d8644 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -1378,12 +1378,8 @@ void setSafeInsetRect(Rect safeInsetRect) { // Check Cutout size final int currentStatusBarHeight = mStatusBarHeight; - if (mStatusBarHeight > mSafeInsetRect.top) { - mStatusBarHeight = currentStatusBarHeight - mSafeInsetRect.top; - } else { - // mStatusBarHeight is not included in mMetrics.heightPixels - mStatusBarHeight = 0; - } + // mStatusBarHeight is not included in mMetrics.heightPixels + mStatusBarHeight = 0; // Refresh Limit Rect if (currentStatusBarHeight != mStatusBarHeight) { From f6a87c883640d663c6952dfe9ccc1b9912e691d3 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 3 Aug 2018 13:48:14 +0900 Subject: [PATCH 08/35] Cutout supports only portrait orientation. --- README.md | 1 + .../android/floatingview/FloatingViewManager.java | 1 + .../sample/fragment/FloatingViewControlFragment.java | 9 +++++++++ sample/src/main/res/values-ja/strings.xml | 1 + sample/src/main/res/values/strings.xml | 1 + 5 files changed, 13 insertions(+) diff --git a/README.md b/README.md index a103af3..fc2fd49 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 9) Add DisplayCutout process(API Level >= 28) Note: `DisplayCutout` is obtained from `Fragment` or `Activity` (`Service` can not be acquired) +Note: You must set the `DisplayCutout` obtained on portrait orientation. example) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index 0b9074c..16fff33 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -475,6 +475,7 @@ public boolean isTrashViewEnabled() { /** * Set the DisplayCutout's safe area + * Note:You must set the Cutout obtained on portrait orientation. * * @param safeInsetRect DisplayCutout#getSafeInsetXXX */ diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index a847eb3..d1bdbe5 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -7,12 +7,14 @@ import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.graphics.Rect; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.support.v4.content.ContextCompat; +import android.util.Log; import android.view.DisplayCutout; import android.view.LayoutInflater; import android.view.View; @@ -143,7 +145,14 @@ private static void startFloatingViewService(Activity activity, boolean isCustom // set safe inset area final Rect safeInsetRect = new Rect(); // TODO:Rewrite with android-x + // TODO:Consider alternatives if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + // FloatingView does not support the start of service on the landscape orientation (due to Cutout). + if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + Log.d(TAG, activity.getString(R.string.landscape_cutout_is_not_supported)); + return; + } + final DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); if (displayCutout != null) { safeInsetRect.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom()); diff --git a/sample/src/main/res/values-ja/strings.xml b/sample/src/main/res/values-ja/strings.xml index 330ea04..236ab46 100644 --- a/sample/src/main/res/values-ja/strings.xml +++ b/sample/src/main/res/values-ja/strings.xml @@ -15,4 +15,5 @@ 現在位置 (%d,%d) FloatingViewはまもなく消えます FloatingViewは消えました + 端末を縦向きにしてください diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index 937a0b1..6c1e129 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -16,6 +16,7 @@ Current position (%d,%d) FloatingView will be deleted soon. FloatingView has been deleted. + Please keep the device in portrait orientation default_floatingview_channel Default Channel From d7d059d18993957c11d29e844c848ceaf17054c7 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 3 Aug 2018 14:48:07 +0900 Subject: [PATCH 09/35] Add height of the status bar in landscape orientation --- .../android/floatingview/FloatingView.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index 74d8644..73d0efe 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -277,10 +277,15 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList private boolean mAnimateInitialMove; /** - * ステータスバーの高さ + * status bar's height */ private final int mBaseStatusBarHeight; + /** + * status bar's height(landscape) + */ + private int mBaseStatusBarRotatedHeight; + /** * Current status bar's height */ @@ -436,7 +441,13 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList // ステータスバーの高さを取得 mBaseStatusBarHeight = getSystemUiDimensionPixelSize(resources, "status_bar_height"); - mStatusBarHeight = mBaseStatusBarHeight; + // Check landscape resource id + final int statusBarLandscapeResId = resources.getIdentifier("status_bar_height_landscape", "dimen", "android"); + if (statusBarLandscapeResId > 0) { + mBaseStatusBarRotatedHeight = getSystemUiDimensionPixelSize(resources, "status_bar_height_landscape"); + } else { + mBaseStatusBarRotatedHeight = mBaseStatusBarHeight; + } // Init physics-based animation properties updateViewConfiguration(); @@ -556,7 +567,7 @@ public boolean onPreDraw() { */ void onUpdateSystemLayout(boolean isHideStatusBar, boolean isHideNavigationBar, boolean isPortrait, boolean hasTouchXOffset) { // status bar - mStatusBarHeight = isHideStatusBar ? 0 : mBaseStatusBarHeight; + updateStatusBarHeight(isHideStatusBar, isPortrait); // touch X offset(navigation bar is displayed and it is on the left side of the device) mTouchXOffset = !isHideNavigationBar && hasTouchXOffset ? mBaseNavigationBarRotatedHeight : 0; // navigation bar @@ -564,6 +575,21 @@ void onUpdateSystemLayout(boolean isHideStatusBar, boolean isHideNavigationBar, refreshLimitRect(); } + /** + * Update height of StatusBar. + * + * @param isHideStatusBar If true, the status bar is hidden + * @param isPortrait If true, the device orientation is portrait + */ + private void updateStatusBarHeight(boolean isHideStatusBar, boolean isPortrait) { + if (isHideStatusBar) { + mStatusBarHeight = 0; + return; + } + + mStatusBarHeight = isPortrait ? mBaseStatusBarHeight : mBaseStatusBarRotatedHeight; + } + /** * Update offset of NavigationBar. * From d77c7ee330dc389d6f7716cc23d2fd38b59bf382 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 3 Aug 2018 16:09:19 +0900 Subject: [PATCH 10/35] Update SDK (Android Studio 3.3 Canary4) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index d7bd7a7..91b5737 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0-alpha03' + classpath 'com.android.tools.build:gradle:3.3.0-alpha04' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d96358e..b601473 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Aug 02 10:32:15 JST 2018 +#Fri Aug 03 16:02:21 JST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-rc-1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip From d2713612e30beb2854ee2aa513383e6cae9b08ee Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 3 Aug 2018 17:15:55 +0900 Subject: [PATCH 11/35] Support Tall diaplay cutout - Recalculate size of status bar when device is rotated - Set the offset of the touch coordinates in the Y axis direction --- .../android/floatingview/FloatingView.java | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index 73d0efe..84a0873 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -318,6 +318,11 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList */ private int mTouchXOffset; + /** + * Offset of touch Y coordinate + */ + private int mTouchYOffset; + /** * 左・右端に寄せるアニメーション */ @@ -570,6 +575,8 @@ void onUpdateSystemLayout(boolean isHideStatusBar, boolean isHideNavigationBar, updateStatusBarHeight(isHideStatusBar, isPortrait); // touch X offset(navigation bar is displayed and it is on the left side of the device) mTouchXOffset = !isHideNavigationBar && hasTouchXOffset ? mBaseNavigationBarRotatedHeight : 0; + // touch Y offset(support Cutout) + mTouchYOffset = isPortrait ? mSafeInsetRect.top : 0; // navigation bar updateNavigationBarOffset(isHideNavigationBar, isPortrait); refreshLimitRect(); @@ -583,11 +590,29 @@ void onUpdateSystemLayout(boolean isHideStatusBar, boolean isHideNavigationBar, */ private void updateStatusBarHeight(boolean isHideStatusBar, boolean isPortrait) { if (isHideStatusBar) { + // 1.(No Cutout)No StatusBar(=0) + // 2.(Has Cutout)StatusBar is not included in mMetrics.heightPixels (=0) mStatusBarHeight = 0; return; } - mStatusBarHeight = isPortrait ? mBaseStatusBarHeight : mBaseStatusBarRotatedHeight; + // Has Cutout + final boolean hasTopCutout = mSafeInsetRect.top != 0; + if (hasTopCutout) { + if (isPortrait) { + mStatusBarHeight = 0; + } else { + mStatusBarHeight = mBaseStatusBarRotatedHeight; + } + return; + } + + // No cutout + if (isPortrait) { + mStatusBarHeight = mBaseStatusBarHeight; + } else { + mStatusBarHeight = mBaseStatusBarRotatedHeight; + } } /** @@ -652,7 +677,7 @@ private void refreshLimitRect() { // 移動範囲の設定 mMoveLimitRect.set(-width, -height * 2, newScreenWidth + width + mNavigationBarHorizontalOffset, newScreenHeight + height + mNavigationBarVerticalOffset); - mPositionLimitRect.set(-mOverMargin, 0, newScreenWidth - width + mOverMargin + mNavigationBarHorizontalOffset, newScreenHeight - mStatusBarHeight + mSafeInsetRect.top - height + mNavigationBarVerticalOffset); + mPositionLimitRect.set(-mOverMargin, 0, newScreenWidth - width + mOverMargin + mNavigationBarHorizontalOffset, newScreenHeight - mStatusBarHeight - height + mNavigationBarVerticalOffset); // Initial animation stop when the device rotates final int newRotation = mWindowManager.getDefaultDisplay().getRotation(); @@ -1359,7 +1384,7 @@ private int getXByTouch() { * @return FloatingViewのY座標 */ private int getYByTouch() { - return (int) (mMetrics.heightPixels + mNavigationBarVerticalOffset + mSafeInsetRect.top - (mScreenTouchY - mLocalTouchY + getHeight())); + return (int) (mMetrics.heightPixels + mNavigationBarVerticalOffset - (mScreenTouchY - mLocalTouchY + getHeight() - mTouchYOffset)); } /** From 10fd6f5ed00a998a22d18d50d3d68c6b122fade1 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 3 Aug 2018 18:09:02 +0900 Subject: [PATCH 12/35] Delete update process from FloatingView - Add TODO FloatingViewManager --- .../android/floatingview/FloatingView.java | 10 ---------- .../android/floatingview/FloatingViewManager.java | 1 + 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index 84a0873..d668dac 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -1426,16 +1426,6 @@ int getState() { */ void setSafeInsetRect(Rect safeInsetRect) { mSafeInsetRect.set(safeInsetRect); - - // Check Cutout size - final int currentStatusBarHeight = mStatusBarHeight; - // mStatusBarHeight is not included in mMetrics.heightPixels - mStatusBarHeight = 0; - - // Refresh Limit Rect - if (currentStatusBarHeight != mStatusBarHeight) { - refreshLimitRect(); - } } /** diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index 16fff33..c061892 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -486,6 +486,7 @@ public void setSafeInsetRect(Rect safeInsetRect) { mSafeInsetRect.set(safeInsetRect); } //TODO:update Layout + //TODO:update FloatingView } /** From b270a5c2fc3b3ea64b46d9a97f186ca61d6809a1 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Mon, 6 Aug 2018 13:36:47 +0900 Subject: [PATCH 13/35] Fix:Fixed a bug that the view shifted when touching after rotating the screen. - Add updateTouchXOffset method --- .../android/floatingview/FloatingView.java | 24 +++++++++++++++---- .../floatingview/FloatingViewManager.java | 9 +++---- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index d668dac..43671eb 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -568,13 +568,13 @@ public boolean onPreDraw() { * @param isHideStatusBar If true, the status bar is hidden * @param isHideNavigationBar If true, the navigation bar is hidden * @param isPortrait If true, the device orientation is portrait - * @param hasTouchXOffset If true, offset is required for touched X coordinate + * @param windowLeftOffset Left side offset of device display */ - void onUpdateSystemLayout(boolean isHideStatusBar, boolean isHideNavigationBar, boolean isPortrait, boolean hasTouchXOffset) { + void onUpdateSystemLayout(boolean isHideStatusBar, boolean isHideNavigationBar, boolean isPortrait, int windowLeftOffset) { // status bar updateStatusBarHeight(isHideStatusBar, isPortrait); - // touch X offset(navigation bar is displayed and it is on the left side of the device) - mTouchXOffset = !isHideNavigationBar && hasTouchXOffset ? mBaseNavigationBarRotatedHeight : 0; + // touch X offset(support Cutout) + updateTouchXOffset(isHideNavigationBar, windowLeftOffset); // touch Y offset(support Cutout) mTouchYOffset = isPortrait ? mSafeInsetRect.top : 0; // navigation bar @@ -615,6 +615,22 @@ private void updateStatusBarHeight(boolean isHideStatusBar, boolean isPortrait) } } + /** + * Update of touch X coordinate + * + * @param isHideNavigationBar If true, the navigation bar is hidden + * @param windowLeftOffset Left side offset of device display + */ + private void updateTouchXOffset(boolean isHideNavigationBar, int windowLeftOffset) { + final boolean noBottomCutout = mSafeInsetRect.bottom == 0; + if (noBottomCutout) { + // touch X offset(navigation bar is displayed and it is on the left side of the device) + mTouchXOffset = !isHideNavigationBar && windowLeftOffset > 0 ? mBaseNavigationBarRotatedHeight : 0; + } else { + mTouchXOffset = windowLeftOffset; + } + } + /** * Update offset of NavigationBar. * diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index c061892..58550e9 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -251,11 +251,8 @@ public void onScreenChanged(Rect windowRect, int visibility) { } final boolean isPortrait = mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; - // touch X offset(navigation bar is on the left side) - final boolean hasTouchXOffset = windowRect.left > 0; - // update FloatingView layout - mTargetFloatingView.onUpdateSystemLayout(isHideStatusBar, isHideNavigationBar, isPortrait, hasTouchXOffset); + mTargetFloatingView.onUpdateSystemLayout(isHideStatusBar, isHideNavigationBar, isPortrait, windowRect.left); // フルスクリーンでの非表示モードでない場合は何もしない if (mDisplayMode != DISPLAY_MODE_HIDE_FULLSCREEN) { @@ -442,13 +439,13 @@ public void setDisplayMode(@DisplayMode int displayMode) { mDisplayMode = displayMode; // 常に表示/フルスクリーン時に非表示にするモードの場合 if (mDisplayMode == DISPLAY_MODE_SHOW_ALWAYS || mDisplayMode == DISPLAY_MODE_HIDE_FULLSCREEN) { - for (FloatingView floatingView : mFloatingViewList) { + for (FloatingView floatingView: mFloatingViewList) { floatingView.setVisibility(View.VISIBLE); } } // 常に非表示にするモードの場合 else if (mDisplayMode == DISPLAY_MODE_HIDE_ALWAYS) { - for (FloatingView floatingView : mFloatingViewList) { + for (FloatingView floatingView: mFloatingViewList) { floatingView.setVisibility(View.GONE); } mTrashView.dismiss(); From c9c6386adab2552df5b2eec2174f78ca7a6caa8a Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Mon, 6 Aug 2018 13:55:46 +0900 Subject: [PATCH 14/35] Change : Set MainActivity to portrait - Launching FloatingView on landscape is not supported - Delete unused source and resources --- sample/src/main/AndroidManifest.xml | 22 +++++++++---------- .../fragment/FloatingViewControlFragment.java | 9 +------- sample/src/main/res/values-ja/strings.xml | 1 - sample/src/main/res/values/strings.xml | 1 - 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 2b4ed53..419a24b 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -1,10 +1,9 @@ - + - + @@ -13,13 +12,14 @@ android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> - + + android:label="@string/app_name" + android:screenOrientation="portrait"> - - + + @@ -27,15 +27,15 @@ android:name="jp.co.recruit_lifestyle.sample.DeleteActionActivity" android:excludeFromRecents="true" android:launchMode="singleInstance" - android:taskAffinity="jp.co.recruit.floatingview.ChatHeadActivity"/> + android:taskAffinity="jp.co.recruit.floatingview.ChatHeadActivity" /> + android:exported="false" /> + android:exported="false" /> diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index d1bdbe5..da468ed 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -7,14 +7,12 @@ import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; -import android.content.res.Configuration; import android.graphics.Rect; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.support.v4.content.ContextCompat; -import android.util.Log; import android.view.DisplayCutout; import android.view.LayoutInflater; import android.view.View; @@ -147,12 +145,7 @@ private static void startFloatingViewService(Activity activity, boolean isCustom // TODO:Rewrite with android-x // TODO:Consider alternatives if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - // FloatingView does not support the start of service on the landscape orientation (due to Cutout). - if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { - Log.d(TAG, activity.getString(R.string.landscape_cutout_is_not_supported)); - return; - } - + // Note:FloatingView does not support the start of service on the landscape orientation (due to Cutout). final DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); if (displayCutout != null) { safeInsetRect.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom()); diff --git a/sample/src/main/res/values-ja/strings.xml b/sample/src/main/res/values-ja/strings.xml index 236ab46..330ea04 100644 --- a/sample/src/main/res/values-ja/strings.xml +++ b/sample/src/main/res/values-ja/strings.xml @@ -15,5 +15,4 @@ 現在位置 (%d,%d) FloatingViewはまもなく消えます FloatingViewは消えました - 端末を縦向きにしてください diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index 6c1e129..937a0b1 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -16,7 +16,6 @@ Current position (%d,%d) FloatingView will be deleted soon. FloatingView has been deleted. - Please keep the device in portrait orientation default_floatingview_channel Default Channel From da71914574b00233688f2dcfe76e781f5df57a2a Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Mon, 6 Aug 2018 14:57:37 +0900 Subject: [PATCH 15/35] Add: Update FloatingView when updating setSafeInsetRect --- .../android/floatingview/FloatingViewManager.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index 58550e9..67c1e6d 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -482,8 +482,19 @@ public void setSafeInsetRect(Rect safeInsetRect) { } else { mSafeInsetRect.set(safeInsetRect); } - //TODO:update Layout - //TODO:update FloatingView + + final int size = mFloatingViewList.size(); + if (size == 0) { + return; + } + + // update floating view + for (int i = 0; i < size; i++) { + final FloatingView floatingView = mFloatingViewList.get(i); + floatingView.setSafeInsetRect(mSafeInsetRect); + } + // dirty hack + mFullscreenObserverView.onGlobalLayout(); } /** From b323ad9e3790159a230156aa4375874b6486c36c Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Tue, 7 Aug 2018 13:32:52 +0900 Subject: [PATCH 16/35] Update SDK - Delete "ext" in build.gradle --- build.gradle | 9 +-------- library/build.gradle | 14 +++++++------- sample/build.gradle | 10 +++++----- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/build.gradle b/build.gradle index 91b5737..b5fd412 100644 --- a/build.gradle +++ b/build.gradle @@ -19,11 +19,4 @@ allprojects { jcenter() google() } -} - -ext { - compileSdkVersion = 28 - buildToolsVersion = '28.0.0 rc2' - targetSdkVersion = 28 - minSdkVersion = 14 -} +} \ No newline at end of file diff --git a/library/build.gradle b/library/build.gradle index 0e258ed..9f5d722 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,21 +1,21 @@ apply plugin: 'com.android.library' android { - compileSdkVersion rootProject.ext.compileSdkVersion as Integer - buildToolsVersion rootProject.ext.buildToolsVersion as String + compileSdkVersion 28 + buildToolsVersion '28.0.2' defaultConfig { - minSdkVersion rootProject.ext.minSdkVersion as Integer - targetSdkVersion rootProject.ext.targetSdkVersion as Integer + minSdkVersion 14 + targetSdkVersion 28 versionCode 1 versionName "1.0" } } dependencies { - implementation 'com.android.support:support-annotations:27.1.1' - implementation 'com.android.support:support-compat:27.1.1' - implementation 'com.android.support:support-dynamic-animation:27.1.1' + implementation 'com.android.support:support-annotations:28.0.0-rc01' + implementation 'com.android.support:support-compat:28.0.0-rc01' + implementation 'com.android.support:support-dynamic-animation:28.0.0-rc01' } // build a jar with source files diff --git a/sample/build.gradle b/sample/build.gradle index b79f443..b1c5e21 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion rootProject.ext.compileSdkVersion as Integer - buildToolsVersion rootProject.ext.buildToolsVersion as String + compileSdkVersion 28 + buildToolsVersion '28.0.2' defaultConfig { applicationId "jp.co.recruit.floatingview" - minSdkVersion rootProject.ext.minSdkVersion as Integer - targetSdkVersion rootProject.ext.targetSdkVersion as Integer + minSdkVersion 14 + targetSdkVersion 28 versionCode 1 versionName "1.0" } @@ -21,6 +21,6 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:preference-v14:27.1.1' + implementation 'com.android.support:preference-v14:28.0.0-rc01' implementation project(':library') } From f895e5f2f4fe220133c46b148a67764097e9eb7d Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 14 Sep 2018 15:28:38 +0900 Subject: [PATCH 17/35] Added caution to demo app when obtain the Cutout. --- .../fragment/FloatingViewControlFragment.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index da468ed..53ae903 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -7,6 +7,7 @@ import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.graphics.Rect; import android.net.Uri; import android.os.Build; @@ -17,6 +18,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManager; import jp.co.recruit.floatingview.R; import jp.co.recruit_lifestyle.sample.service.ChatHeadService; @@ -145,10 +147,19 @@ private static void startFloatingViewService(Activity activity, boolean isCustom // TODO:Rewrite with android-x // TODO:Consider alternatives if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - // Note:FloatingView does not support the start of service on the landscape orientation (due to Cutout). final DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); if (displayCutout != null) { safeInsetRect.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom()); + + // *** You must follow these rules when obtain the cutout *** + // 1. 'windowLayoutInDisplayCutoutMode' do not be set to 'never' + if (activity.getWindow().getAttributes().layoutInDisplayCutoutMode == WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER) { + throw new RuntimeException("'windowLayoutInDisplayCutoutMode' do not be set to 'never'"); + } + // 2. Do not set Activity to landscape + if(activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){ + throw new RuntimeException("Do not set Activity to landscape"); + } } } From aed61c6fdfd0d313b2df335491231b085ca3ec4b Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 14 Sep 2018 15:49:18 +0900 Subject: [PATCH 18/35] Update tools version --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- library/build.gradle | 6 +++--- sample/build.gradle | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index b5fd412..be593da 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0-alpha04' + classpath 'com.android.tools.build:gradle:3.3.0-alpha10' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b601473..de2c9cd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Aug 03 16:02:21 JST 2018 +#Fri Sep 14 15:32:46 JST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip diff --git a/library/build.gradle b/library/build.gradle index 9f5d722..4360def 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -13,9 +13,9 @@ android { } dependencies { - implementation 'com.android.support:support-annotations:28.0.0-rc01' - implementation 'com.android.support:support-compat:28.0.0-rc01' - implementation 'com.android.support:support-dynamic-animation:28.0.0-rc01' + implementation 'com.android.support:support-annotations:28.0.0-rc02' + implementation 'com.android.support:support-compat:28.0.0-rc02' + implementation 'com.android.support:support-dynamic-animation:28.0.0-rc02' } // build a jar with source files diff --git a/sample/build.gradle b/sample/build.gradle index b1c5e21..6720294 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -21,6 +21,6 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:preference-v14:28.0.0-rc01' + implementation 'com.android.support:preference-v14:28.0.0-rc02' implementation project(':library') } From 909a531a0160fc9f71ab06a85b7a6a4ca8934b69 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 14 Sep 2018 15:56:56 +0900 Subject: [PATCH 19/35] Update README --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fc2fd49..3a52f10 100644 --- a/README.md +++ b/README.md @@ -123,8 +123,9 @@ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 9) Add DisplayCutout process(API Level >= 28) -Note: `DisplayCutout` is obtained from `Fragment` or `Activity` (`Service` can not be acquired) -Note: You must set the `DisplayCutout` obtained on portrait orientation. +Note: `DisplayCutout` is obtained from `Fragment` or `Activity` (You can not get `DisplayCutout` from `Service`) +Note: You must set the `DisplayCutout` obtained on portrait orientation. +Note: You must not set `windowLayoutInDisplayCutoutMode` to `never` when getting a `DisplayCutout`. example) From efd90a926ca26d5cf9f29a2022fd9340040f9d44 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 20 Sep 2018 13:36:17 +0900 Subject: [PATCH 20/35] Avoid use deprecated class --- .../co/recruit_lifestyle/sample/DeleteActionActivity.java | 8 ++++---- .../java/jp/co/recruit_lifestyle/sample/MainActivity.java | 8 ++++---- .../sample/fragment/DeleteActionFragment.java | 2 +- .../sample/fragment/FloatingViewControlFragment.java | 4 ++-- .../sample/fragment/FloatingViewSettingsFragment.java | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/DeleteActionActivity.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/DeleteActionActivity.java index c77caa0..21f2363 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/DeleteActionActivity.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/DeleteActionActivity.java @@ -1,8 +1,8 @@ package jp.co.recruit_lifestyle.sample; -import android.app.Activity; -import android.app.FragmentTransaction; import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AppCompatActivity; import jp.co.recruit.floatingview.R; import jp.co.recruit_lifestyle.sample.fragment.DeleteActionFragment; @@ -10,7 +10,7 @@ /** * 通知から起動後に削除アクションを行う画面です。 */ -public class DeleteActionActivity extends Activity { +public class DeleteActionActivity extends AppCompatActivity { /** * 設定フラグメントのタグ @@ -26,7 +26,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_delete_action); if (savedInstanceState == null) { - final FragmentTransaction ft = getFragmentManager().beginTransaction(); + final FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(R.id.container, DeleteActionFragment.newInstance(), FRAGMENT_TAG_DELETE_ACTION); ft.commit(); } diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/MainActivity.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/MainActivity.java index 659dec9..29a1b8d 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/MainActivity.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/MainActivity.java @@ -1,17 +1,17 @@ package jp.co.recruit_lifestyle.sample; -import android.app.Activity; -import android.app.FragmentTransaction; import android.app.NotificationChannel; import android.app.NotificationManager; import android.os.Build; import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AppCompatActivity; import jp.co.recruit.floatingview.R; import jp.co.recruit_lifestyle.sample.fragment.FloatingViewControlFragment; -public class MainActivity extends Activity { +public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { @@ -30,7 +30,7 @@ protected void onCreate(Bundle savedInstanceState) { } if (savedInstanceState == null) { - FragmentTransaction ft = getFragmentManager().beginTransaction(); + final FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(R.id.container, FloatingViewControlFragment.newInstance()); ft.commit(); } diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/DeleteActionFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/DeleteActionFragment.java index db8166b..93966d2 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/DeleteActionFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/DeleteActionFragment.java @@ -1,9 +1,9 @@ package jp.co.recruit_lifestyle.sample.fragment; import android.app.Activity; -import android.app.Fragment; import android.content.Intent; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index 53ae903..d4574e9 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -3,8 +3,6 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; -import android.app.Fragment; -import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; @@ -13,6 +11,8 @@ import android.os.Build; import android.os.Bundle; import android.provider.Settings; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; import android.support.v4.content.ContextCompat; import android.view.DisplayCutout; import android.view.LayoutInflater; diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewSettingsFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewSettingsFragment.java index 9861227..51864a6 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewSettingsFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewSettingsFragment.java @@ -2,14 +2,14 @@ import android.os.Bundle; -import android.support.v14.preference.PreferenceFragment; +import android.support.v7.preference.PreferenceFragmentCompat; import jp.co.recruit.floatingview.R; /** * FloatingViewの設定を行います。 */ -public class FloatingViewSettingsFragment extends PreferenceFragment { +public class FloatingViewSettingsFragment extends PreferenceFragmentCompat { /** * FloatingViewSettingsFragmentを生成します。 From d388c74271c52d5ec607c3ffd1c47bc5c989ce4a Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 20 Sep 2018 13:36:39 +0900 Subject: [PATCH 21/35] Update gradle tools --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index be593da..1c4196e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0-alpha10' + classpath 'com.android.tools.build:gradle:3.3.0-alpha11' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From 3fcb929ea4bb1a8cfb4e9b7f0867a2093cf2e129 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 20 Sep 2018 14:14:45 +0900 Subject: [PATCH 22/35] Fix lint warning --- .../sample/fragment/DeleteActionFragment.java | 3 ++- .../sample/fragment/FloatingViewControlFragment.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/DeleteActionFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/DeleteActionFragment.java index 93966d2..b4d8706 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/DeleteActionFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/DeleteActionFragment.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; @@ -38,7 +39,7 @@ public DeleteActionFragment() { * {@inheritDoc} */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View rootView = inflater.inflate(R.layout.fragment_delete_action, container, false); // 削除ボタン final View clearFloatingButton = rootView.findViewById(R.id.clearDemo); diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index d4574e9..d3461e5 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -11,6 +11,7 @@ import android.os.Build; import android.os.Bundle; import android.provider.Settings; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.content.ContextCompat; @@ -64,7 +65,7 @@ public FloatingViewControlFragment() { * {@inheritDoc} */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View rootView = inflater.inflate(R.layout.fragment_floating_view_control, container, false); // デモの表示 rootView.findViewById(R.id.show_demo).setOnClickListener(new View.OnClickListener() { From d09d3d153dbf08e8f177d246cd8927b1edb69bd1 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Tue, 25 Sep 2018 11:13:35 +0900 Subject: [PATCH 23/35] Update SDK - use support library 28.0.0 --- build.gradle | 2 +- library/build.gradle | 10 ++++------ sample/build.gradle | 4 +--- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 1c4196e..11f6a11 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0-alpha11' + classpath 'com.android.tools.build:gradle:3.2.0' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/library/build.gradle b/library/build.gradle index 4360def..1a38089 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -2,8 +2,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion 28 - buildToolsVersion '28.0.2' - defaultConfig { minSdkVersion 14 targetSdkVersion 28 @@ -13,9 +11,9 @@ android { } dependencies { - implementation 'com.android.support:support-annotations:28.0.0-rc02' - implementation 'com.android.support:support-compat:28.0.0-rc02' - implementation 'com.android.support:support-dynamic-animation:28.0.0-rc02' + implementation 'com.android.support:support-annotations:28.0.0' + implementation 'com.android.support:support-compat:28.0.0' + implementation 'com.android.support:support-dynamic-animation:28.0.0' } // build a jar with source files @@ -25,7 +23,7 @@ task sourcesJar(type: Jar) { } task javadoc(type: Javadoc) { - failOnError false + failOnError false source = android.sourceSets.main.java.sourceFiles classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) } diff --git a/sample/build.gradle b/sample/build.gradle index 6720294..5b141aa 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -2,8 +2,6 @@ apply plugin: 'com.android.application' android { compileSdkVersion 28 - buildToolsVersion '28.0.2' - defaultConfig { applicationId "jp.co.recruit.floatingview" minSdkVersion 14 @@ -21,6 +19,6 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:preference-v14:28.0.0-rc02' + implementation 'com.android.support:preference-v14:28.0.0' implementation project(':library') } From 88a6d481aabc56356fbb49bc08ea9cf3200fbae1 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Tue, 25 Sep 2018 15:26:35 +0900 Subject: [PATCH 24/35] Created a convenient method in FloatingViewManager. --- README.md | 16 +++------- .../floatingview/FloatingViewManager.java | 30 +++++++++++++++-- .../fragment/FloatingViewControlFragment.java | 32 +++++++------------ 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 3a52f10..a1073f8 100644 --- a/README.md +++ b/README.md @@ -123,25 +123,17 @@ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 9) Add DisplayCutout process(API Level >= 28) -Note: `DisplayCutout` is obtained from `Fragment` or `Activity` (You can not get `DisplayCutout` from `Service`) -Note: You must set the `DisplayCutout` obtained on portrait orientation. -Note: You must not set `windowLayoutInDisplayCutoutMode` to `never` when getting a `DisplayCutout`. +Call `FloatingViewManager.findCutoutSafeArea(activity)`. +Note: Activity must be portrait oriented. +Note: You must not set `windowLayoutInDisplayCutoutMode` to `never`. example) - FloatingViewControlFragment.java ```java -final Rect safeInsetRect = new Rect(); -if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - final DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); - if (displayCutout != null) { - safeInsetRect.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom()); - } -} - final Intent intent = new Intent(activity, ChatHeadService.class); -intent.putExtra(ChatHeadService.EXTRA_CUTOUT_SAFE_AREA, safeInsetRect); +intent.putExtra(ChatHeadService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(activity)); ContextCompat.startForegroundService(activity, intent); ``` diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index 67c1e6d..bedeacc 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -16,6 +16,7 @@ package jp.co.recruit_lifestyle.android.floatingview; +import android.app.Activity; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; @@ -24,7 +25,9 @@ import android.os.Build; import android.support.annotation.DrawableRes; import android.support.annotation.IntDef; +import android.support.annotation.NonNull; import android.util.DisplayMetrics; +import android.view.DisplayCutout; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; @@ -439,13 +442,13 @@ public void setDisplayMode(@DisplayMode int displayMode) { mDisplayMode = displayMode; // 常に表示/フルスクリーン時に非表示にするモードの場合 if (mDisplayMode == DISPLAY_MODE_SHOW_ALWAYS || mDisplayMode == DISPLAY_MODE_HIDE_FULLSCREEN) { - for (FloatingView floatingView: mFloatingViewList) { + for (FloatingView floatingView : mFloatingViewList) { floatingView.setVisibility(View.VISIBLE); } } // 常に非表示にするモードの場合 else if (mDisplayMode == DISPLAY_MODE_HIDE_ALWAYS) { - for (FloatingView floatingView: mFloatingViewList) { + for (FloatingView floatingView : mFloatingViewList) { floatingView.setVisibility(View.GONE); } mTrashView.dismiss(); @@ -579,6 +582,29 @@ public void removeAllViewToWindow() { mFloatingViewList.clear(); } + /** + * Find the safe area of DisplayCutout. + * + * @param activity {@link Activity} (Portrait and `windowLayoutInDisplayCutoutMode` != never) + * @return Safe cutout insets. + */ + public static Rect findCutoutSafeArea(@NonNull Activity activity) { + final Rect safeInsetRect = new Rect(); + // TODO:Rewrite with android-x + // TODO:Consider alternatives + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + return safeInsetRect; + } + + // set safeInsetRect + final DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); + if (displayCutout != null) { + safeInsetRect.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom()); + } + + return safeInsetRect; + } + /** * FloatingViewを貼り付ける際のオプションを表すクラスです。 */ diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index d3461e5..c02d5fc 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -6,7 +6,6 @@ import android.content.Context; import android.content.Intent; import android.content.res.Configuration; -import android.graphics.Rect; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -15,13 +14,13 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.content.ContextCompat; -import android.view.DisplayCutout; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import jp.co.recruit.floatingview.R; +import jp.co.recruit_lifestyle.android.floatingview.FloatingViewManager; import jp.co.recruit_lifestyle.sample.service.ChatHeadService; import jp.co.recruit_lifestyle.sample.service.CustomFloatingViewService; @@ -143,35 +142,26 @@ private void showFloatingView(Context context, boolean isShowOverlayPermission, * @param isCustomFloatingView If true, it launches CustomFloatingViewService. */ private static void startFloatingViewService(Activity activity, boolean isCustomFloatingView) { - // set safe inset area - final Rect safeInsetRect = new Rect(); - // TODO:Rewrite with android-x - // TODO:Consider alternatives + // *** You must follow these rules when obtain the cutout(FloatingViewManager.findCutoutSafeArea) *** if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - final DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); - if (displayCutout != null) { - safeInsetRect.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom()); - - // *** You must follow these rules when obtain the cutout *** - // 1. 'windowLayoutInDisplayCutoutMode' do not be set to 'never' - if (activity.getWindow().getAttributes().layoutInDisplayCutoutMode == WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER) { - throw new RuntimeException("'windowLayoutInDisplayCutoutMode' do not be set to 'never'"); - } - // 2. Do not set Activity to landscape - if(activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){ - throw new RuntimeException("Do not set Activity to landscape"); - } + // 1. 'windowLayoutInDisplayCutoutMode' do not be set to 'never' + if (activity.getWindow().getAttributes().layoutInDisplayCutoutMode == WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER) { + throw new RuntimeException("'windowLayoutInDisplayCutoutMode' do not be set to 'never'"); + } + // 2. Do not set Activity to landscape + if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + throw new RuntimeException("Do not set Activity to landscape"); } } // launch service if (isCustomFloatingView) { final Intent intent = new Intent(activity, CustomFloatingViewService.class); - intent.putExtra(CustomFloatingViewService.EXTRA_CUTOUT_SAFE_AREA, safeInsetRect); + intent.putExtra(CustomFloatingViewService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(activity)); ContextCompat.startForegroundService(activity, intent); } else { final Intent intent = new Intent(activity, ChatHeadService.class); - intent.putExtra(ChatHeadService.EXTRA_CUTOUT_SAFE_AREA, safeInsetRect); + intent.putExtra(ChatHeadService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(activity)); ContextCompat.startForegroundService(activity, intent); } } From 90243bc10f6d2e85669bfa83e3c8e749c9137eb9 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Tue, 25 Sep 2018 16:19:29 +0900 Subject: [PATCH 25/35] Fix typo and space --- .../co/recruit_lifestyle/android/floatingview/FloatingView.java | 2 +- .../android/floatingview/FloatingViewManager.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index 43671eb..e7e0117 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -292,7 +292,7 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList private int mStatusBarHeight; /** - * Navigation bar's height(portlait) + * Navigation bar's height(portrait) */ private final int mBaseNavigationBarHeight; diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index bedeacc..a57fefc 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -604,7 +604,7 @@ public static Rect findCutoutSafeArea(@NonNull Activity activity) { return safeInsetRect; } - + /** * FloatingViewを貼り付ける際のオプションを表すクラスです。 */ From 8608cde6cbb4652b3f44a0f2ad4e9ecae99bad8b Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 27 Sep 2018 13:03:15 +0900 Subject: [PATCH 26/35] Fix find navigation bar --- .../android/floatingview/FloatingViewManager.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index 67c1e6d..494f844 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -241,7 +241,7 @@ public void onScreenChanged(Rect windowRect, int visibility) { } // detect navigation bar - final boolean isHideNavigationBar; + boolean isHideNavigationBar; if (visibility == FullscreenObserverView.NO_LAST_VISIBILITY) { // At the first it can not get the correct value, so do special processing mWindowManager.getDefaultDisplay().getMetrics(mDisplayMetrics); @@ -249,8 +249,14 @@ public void onScreenChanged(Rect windowRect, int visibility) { } else { isHideNavigationBar = (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; } - final boolean isPortrait = mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; + // auto dismiss navigation bar mode(Galaxy S8, S9 and so on.) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + final DisplayMetrics realMetrics = new DisplayMetrics(); + mWindowManager.getDefaultDisplay().getRealMetrics(realMetrics); + isHideNavigationBar = isHideNavigationBar || windowRect.bottom - realMetrics.heightPixels == 0; + } + final boolean isPortrait = mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; // update FloatingView layout mTargetFloatingView.onUpdateSystemLayout(isHideStatusBar, isHideNavigationBar, isPortrait, windowRect.left); From bb358d042ea7ad449213bb6642ee8d83c7a62510 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 27 Sep 2018 13:20:25 +0900 Subject: [PATCH 27/35] Refactor various name --- .../android/floatingview/FloatingViewManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index 494f844..c452fde 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -251,9 +251,9 @@ public void onScreenChanged(Rect windowRect, int visibility) { } // auto dismiss navigation bar mode(Galaxy S8, S9 and so on.) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - final DisplayMetrics realMetrics = new DisplayMetrics(); - mWindowManager.getDefaultDisplay().getRealMetrics(realMetrics); - isHideNavigationBar = isHideNavigationBar || windowRect.bottom - realMetrics.heightPixels == 0; + final DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + mWindowManager.getDefaultDisplay().getRealMetrics(realDisplayMetrics); + isHideNavigationBar = isHideNavigationBar || windowRect.bottom - realDisplayMetrics.heightPixels == 0; } final boolean isPortrait = mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; From 5a22d9345dee7b6d2d5ed730ee0a4937c63b6067 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 27 Sep 2018 16:25:15 +0900 Subject: [PATCH 28/35] Add final --- .../co/recruit_lifestyle/android/floatingview/FloatingView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index 43671eb..e0c92fb 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -284,7 +284,7 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList /** * status bar's height(landscape) */ - private int mBaseStatusBarRotatedHeight; + private final int mBaseStatusBarRotatedHeight; /** * Current status bar's height From 78528f24646c59706cdd3c705002825fd7cd83ea Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 28 Sep 2018 15:17:26 +0900 Subject: [PATCH 29/35] Fix find navigation bar - a bug when rotating the device to landscape mode on home screen --- .../floatingview/FloatingViewManager.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index c452fde..2bd9636 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -241,20 +241,19 @@ public void onScreenChanged(Rect windowRect, int visibility) { } // detect navigation bar - boolean isHideNavigationBar; + final boolean isHideNavigationBar; if (visibility == FullscreenObserverView.NO_LAST_VISIBILITY) { // At the first it can not get the correct value, so do special processing - mWindowManager.getDefaultDisplay().getMetrics(mDisplayMetrics); - isHideNavigationBar = windowRect.width() - mDisplayMetrics.widthPixels > 0 || windowRect.height() - mDisplayMetrics.heightPixels > 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + mWindowManager.getDefaultDisplay().getRealMetrics(mDisplayMetrics); + isHideNavigationBar = windowRect.width() - mDisplayMetrics.widthPixels == 0 && windowRect.bottom - mDisplayMetrics.heightPixels == 0; + } else { + mWindowManager.getDefaultDisplay().getMetrics(mDisplayMetrics); + isHideNavigationBar = windowRect.width() - mDisplayMetrics.widthPixels > 0 || windowRect.height() - mDisplayMetrics.heightPixels > 0; + } } else { isHideNavigationBar = (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; } - // auto dismiss navigation bar mode(Galaxy S8, S9 and so on.) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - final DisplayMetrics realDisplayMetrics = new DisplayMetrics(); - mWindowManager.getDefaultDisplay().getRealMetrics(realDisplayMetrics); - isHideNavigationBar = isHideNavigationBar || windowRect.bottom - realDisplayMetrics.heightPixels == 0; - } final boolean isPortrait = mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; // update FloatingView layout @@ -445,13 +444,13 @@ public void setDisplayMode(@DisplayMode int displayMode) { mDisplayMode = displayMode; // 常に表示/フルスクリーン時に非表示にするモードの場合 if (mDisplayMode == DISPLAY_MODE_SHOW_ALWAYS || mDisplayMode == DISPLAY_MODE_HIDE_FULLSCREEN) { - for (FloatingView floatingView: mFloatingViewList) { + for (FloatingView floatingView : mFloatingViewList) { floatingView.setVisibility(View.VISIBLE); } } // 常に非表示にするモードの場合 else if (mDisplayMode == DISPLAY_MODE_HIDE_ALWAYS) { - for (FloatingView floatingView: mFloatingViewList) { + for (FloatingView floatingView : mFloatingViewList) { floatingView.setVisibility(View.GONE); } mTrashView.dismiss(); From 123c5106004b6a646a9032f3a3b7c44c13330475 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 28 Sep 2018 18:36:13 +0900 Subject: [PATCH 30/35] Fix navigation bar auto hide mode - test only portrait --- .../android/floatingview/FloatingView.java | 49 ++++++++++++++++--- .../floatingview/FloatingViewManager.java | 2 +- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index e0c92fb..d435e33 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -568,17 +568,17 @@ public boolean onPreDraw() { * @param isHideStatusBar If true, the status bar is hidden * @param isHideNavigationBar If true, the navigation bar is hidden * @param isPortrait If true, the device orientation is portrait - * @param windowLeftOffset Left side offset of device display + * @param windowRect {@link Rect} of system window */ - void onUpdateSystemLayout(boolean isHideStatusBar, boolean isHideNavigationBar, boolean isPortrait, int windowLeftOffset) { + void onUpdateSystemLayout(boolean isHideStatusBar, boolean isHideNavigationBar, boolean isPortrait, Rect windowRect) { // status bar updateStatusBarHeight(isHideStatusBar, isPortrait); // touch X offset(support Cutout) - updateTouchXOffset(isHideNavigationBar, windowLeftOffset); + updateTouchXOffset(isHideNavigationBar, windowRect.left); // touch Y offset(support Cutout) mTouchYOffset = isPortrait ? mSafeInsetRect.top : 0; // navigation bar - updateNavigationBarOffset(isHideNavigationBar, isPortrait); + updateNavigationBarOffset(isHideNavigationBar, isPortrait, windowRect); refreshLimitRect(); } @@ -636,17 +636,52 @@ private void updateTouchXOffset(boolean isHideNavigationBar, int windowLeftOffse * * @param isHideNavigationBar If true, the navigation bar is hidden * @param isPortrait If true, the device orientation is portrait + * @param windowRect {@link Rect} of system window */ - private void updateNavigationBarOffset(boolean isHideNavigationBar, boolean isPortrait) { + private void updateNavigationBarOffset(boolean isHideNavigationBar, boolean isPortrait, Rect windowRect) { + int currentNavigationBarVerticalHeight = 0; + int navigationBarVerticalDiff = 0; + final boolean hasSoftNavigationBar = hasSoftNavigationBar(); + // auto hide navigation bar(Galaxy S8, S9 and so on.) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + final DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + mWindowManager.getDefaultDisplay().getRealMetrics(realDisplayMetrics); + currentNavigationBarVerticalHeight = realDisplayMetrics.heightPixels - windowRect.bottom; + navigationBarVerticalDiff = mBaseNavigationBarHeight - currentNavigationBarVerticalHeight; + } + if (!isHideNavigationBar) { - mNavigationBarVerticalOffset = 0; + // auto hide navigation bar + // 他デバイスとの矛盾をもとに推測する + // 1.デバイスに組み込まれたナビゲーションバー(mBaseNavigationBarHeight == 0)はシステムの状態によって高さに差が発生しない + // 2.デバイスに組み込まれたナビゲーションバー(!hasSoftNavigationBar)は意図的にBaseを0にしているので、矛盾している + if (navigationBarVerticalDiff != 0 && mBaseNavigationBarHeight == 0 || + !hasSoftNavigationBar && mBaseNavigationBarHeight != 0) { + if (hasSoftNavigationBar) { + // 1.auto hide mode -> show mode + // 2.show mode -> auto hide mode -> home + mNavigationBarVerticalOffset = 0; + } else { + // show mode -> home + mNavigationBarVerticalOffset = -currentNavigationBarVerticalHeight; + } + } else { + // normal device + mNavigationBarVerticalOffset = 0; + } + mNavigationBarHorizontalOffset = 0; return; } // If the portrait, is displayed at the bottom of the screen if (isPortrait) { - mNavigationBarVerticalOffset = mBaseNavigationBarHeight; + // auto hide navigation bar + if (!hasSoftNavigationBar && mBaseNavigationBarHeight != 0) { + mNavigationBarVerticalOffset = 0; + } else { + mNavigationBarVerticalOffset = mBaseNavigationBarHeight; + } mNavigationBarHorizontalOffset = 0; return; } diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index 2bd9636..cf5698e 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -257,7 +257,7 @@ public void onScreenChanged(Rect windowRect, int visibility) { final boolean isPortrait = mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; // update FloatingView layout - mTargetFloatingView.onUpdateSystemLayout(isHideStatusBar, isHideNavigationBar, isPortrait, windowRect.left); + mTargetFloatingView.onUpdateSystemLayout(isHideStatusBar, isHideNavigationBar, isPortrait, windowRect); // フルスクリーンでの非表示モードでない場合は何もしない if (mDisplayMode != DISPLAY_MODE_HIDE_FULLSCREEN) { From c6a466bdc9b6415af4109949ff5f0e96540abfe7 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Fri, 28 Sep 2018 20:28:01 +0900 Subject: [PATCH 31/35] Fix navigation bar auto hide mode - landscape mode --- .../android/floatingview/FloatingView.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index d435e33..95b1353 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -639,15 +639,17 @@ private void updateTouchXOffset(boolean isHideNavigationBar, int windowLeftOffse * @param windowRect {@link Rect} of system window */ private void updateNavigationBarOffset(boolean isHideNavigationBar, boolean isPortrait, Rect windowRect) { - int currentNavigationBarVerticalHeight = 0; + int currentNavigationBarHeight = 0; + int currentNavigationBarWidth = 0; int navigationBarVerticalDiff = 0; final boolean hasSoftNavigationBar = hasSoftNavigationBar(); // auto hide navigation bar(Galaxy S8, S9 and so on.) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { final DisplayMetrics realDisplayMetrics = new DisplayMetrics(); mWindowManager.getDefaultDisplay().getRealMetrics(realDisplayMetrics); - currentNavigationBarVerticalHeight = realDisplayMetrics.heightPixels - windowRect.bottom; - navigationBarVerticalDiff = mBaseNavigationBarHeight - currentNavigationBarVerticalHeight; + currentNavigationBarHeight = realDisplayMetrics.heightPixels - windowRect.bottom; + currentNavigationBarWidth = realDisplayMetrics.widthPixels - mMetrics.widthPixels; + navigationBarVerticalDiff = mBaseNavigationBarHeight - currentNavigationBarHeight; } if (!isHideNavigationBar) { @@ -663,7 +665,7 @@ private void updateNavigationBarOffset(boolean isHideNavigationBar, boolean isPo mNavigationBarVerticalOffset = 0; } else { // show mode -> home - mNavigationBarVerticalOffset = -currentNavigationBarVerticalHeight; + mNavigationBarVerticalOffset = -currentNavigationBarHeight; } } else { // normal device @@ -693,7 +695,17 @@ private void updateNavigationBarOffset(boolean isHideNavigationBar, boolean isPo mNavigationBarHorizontalOffset = 0; } else { mNavigationBarVerticalOffset = 0; - mNavigationBarHorizontalOffset = mBaseNavigationBarRotatedHeight; + // auto hide navigation bar + // 他デバイスとの矛盾をもとに推測する + // 1.デバイスに組み込まれたナビゲーションバー(!hasSoftNavigationBar)は、意図的にBaseを0にしているので、矛盾している + if (!hasSoftNavigationBar && mBaseNavigationBarRotatedHeight != 0) { + mNavigationBarHorizontalOffset = 0; + } else if (hasSoftNavigationBar && mBaseNavigationBarRotatedHeight == 0) { + // 2.ソフトナビゲーションバーの場合、Baseが設定されるため矛盾している + mNavigationBarHorizontalOffset = currentNavigationBarWidth; + } else { + mNavigationBarHorizontalOffset = mBaseNavigationBarRotatedHeight; + } } } From efca8e901aae2096ddedc1c0037a968d1a2c9979 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Tue, 2 Oct 2018 17:14:02 +0900 Subject: [PATCH 32/35] Fix IllegalArgumentException - it only happens with Android 8. --- .../floatingview/FloatingViewManager.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java index d7d995c..d70a898 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingViewManager.java @@ -26,6 +26,7 @@ import android.support.annotation.DrawableRes; import android.support.annotation.IntDef; import android.support.annotation.NonNull; +import android.support.v4.view.ViewCompat; import android.util.DisplayMetrics; import android.view.DisplayCutout; import android.view.HapticFeedbackConstants; @@ -544,7 +545,7 @@ public void addViewToWindow(View view, Options options) { mWindowManager.addView(mFullscreenObserverView, mFullscreenObserverView.getWindowLayoutParams()); mTargetFloatingView = floatingView; } else { - mWindowManager.removeViewImmediate(mTrashView); + removeViewImmediate(mTrashView); } // 必ずトップに来て欲しいので毎回貼り付け mWindowManager.addView(mTrashView, mTrashView.getWindowLayoutParams()); @@ -559,7 +560,7 @@ private void removeViewToWindow(FloatingView floatingView) { final int matchIndex = mFloatingViewList.indexOf(floatingView); // 見つかった場合は表示とリストから削除 if (matchIndex != -1) { - mWindowManager.removeViewImmediate(floatingView); + removeViewImmediate(floatingView); mFloatingViewList.remove(matchIndex); } @@ -576,17 +577,29 @@ private void removeViewToWindow(FloatingView floatingView) { * ViewをWindowから全て取り外します。 */ public void removeAllViewToWindow() { - mWindowManager.removeViewImmediate(mFullscreenObserverView); - mWindowManager.removeViewImmediate(mTrashView); + removeViewImmediate(mFullscreenObserverView); + removeViewImmediate(mTrashView); // FloatingViewの削除 final int size = mFloatingViewList.size(); for (int i = 0; i < size; i++) { final FloatingView floatingView = mFloatingViewList.get(i); - mWindowManager.removeViewImmediate(floatingView); + removeViewImmediate(floatingView); } mFloatingViewList.clear(); } + /** + * Safely remove the View (issue #89) + * + * @param view {@link View} + */ + private void removeViewImmediate(View view) { + if (!ViewCompat.isAttachedToWindow(view)) { + return; + } + mWindowManager.removeViewImmediate(view); + } + /** * Find the safe area of DisplayCutout. * From 9fee8018bd7fc8440cbfb81baa8349e32d4168ff Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 4 Oct 2018 14:14:10 +0900 Subject: [PATCH 33/35] Refactor startFloatingViewService method --- .../fragment/FloatingViewControlFragment.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index c02d5fc..10d25bd 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -3,6 +3,7 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; +import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; @@ -155,14 +156,9 @@ private static void startFloatingViewService(Activity activity, boolean isCustom } // launch service - if (isCustomFloatingView) { - final Intent intent = new Intent(activity, CustomFloatingViewService.class); - intent.putExtra(CustomFloatingViewService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(activity)); - ContextCompat.startForegroundService(activity, intent); - } else { - final Intent intent = new Intent(activity, ChatHeadService.class); - intent.putExtra(ChatHeadService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(activity)); - ContextCompat.startForegroundService(activity, intent); - } + final Class service = isCustomFloatingView ? CustomFloatingViewService.class : ChatHeadService.class; + final Intent intent = new Intent(activity, service); + intent.putExtra(CustomFloatingViewService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(activity)); + ContextCompat.startForegroundService(activity, intent); } } \ No newline at end of file From 13c05202f34652f3d5d56c0b6933c736da48db43 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 4 Oct 2018 14:34:19 +0900 Subject: [PATCH 34/35] Refactor updateTouchXOffset --- .../android/floatingview/FloatingView.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java index 90a3112..a18062a 100644 --- a/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java +++ b/library/src/main/java/jp/co/recruit_lifestyle/android/floatingview/FloatingView.java @@ -622,13 +622,15 @@ private void updateStatusBarHeight(boolean isHideStatusBar, boolean isPortrait) * @param windowLeftOffset Left side offset of device display */ private void updateTouchXOffset(boolean isHideNavigationBar, int windowLeftOffset) { - final boolean noBottomCutout = mSafeInsetRect.bottom == 0; - if (noBottomCutout) { - // touch X offset(navigation bar is displayed and it is on the left side of the device) - mTouchXOffset = !isHideNavigationBar && windowLeftOffset > 0 ? mBaseNavigationBarRotatedHeight : 0; - } else { + final boolean hasBottomCutout = mSafeInsetRect.bottom != 0; + if (hasBottomCutout) { mTouchXOffset = windowLeftOffset; + return; } + + // No cutout + // touch X offset(navigation bar is displayed and it is on the left side of the device) + mTouchXOffset = !isHideNavigationBar && windowLeftOffset > 0 ? mBaseNavigationBarRotatedHeight : 0; } /** From 0c7b987a246c71c9b9aa11c873b98ce75bfc7a18 Mon Sep 17 00:00:00 2001 From: Yoshihide Sogawa <12043975+YoshihideSogawa@users.noreply.github.com> Date: Thu, 4 Oct 2018 17:38:32 +0900 Subject: [PATCH 35/35] Fix sample - use ChatHeadService.EXTRA_CUTOUT_SAFE_AREA --- .../sample/fragment/FloatingViewControlFragment.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java index 10d25bd..b0a6d68 100644 --- a/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java +++ b/sample/src/main/java/jp/co/recruit_lifestyle/sample/fragment/FloatingViewControlFragment.java @@ -156,9 +156,17 @@ private static void startFloatingViewService(Activity activity, boolean isCustom } // launch service - final Class service = isCustomFloatingView ? CustomFloatingViewService.class : ChatHeadService.class; + final Class service; + final String key; + if (isCustomFloatingView) { + service = CustomFloatingViewService.class; + key = CustomFloatingViewService.EXTRA_CUTOUT_SAFE_AREA; + } else { + service = ChatHeadService.class; + key = ChatHeadService.EXTRA_CUTOUT_SAFE_AREA; + } final Intent intent = new Intent(activity, service); - intent.putExtra(CustomFloatingViewService.EXTRA_CUTOUT_SAFE_AREA, FloatingViewManager.findCutoutSafeArea(activity)); + intent.putExtra(key, FloatingViewManager.findCutoutSafeArea(activity)); ContextCompat.startForegroundService(activity, intent); } } \ No newline at end of file