Skip to content
This repository has been archived by the owner on Feb 3, 2020. It is now read-only.

Commit

Permalink
Merge pull request #90 from recruit-lifestyle/feature/support_p
Browse files Browse the repository at this point in the history
Support Android P
  • Loading branch information
YoshihideSogawa authored Sep 14, 2018
2 parents 4b0e352 + 909a531 commit f5ad373
Show file tree
Hide file tree
Showing 11 changed files with 268 additions and 83 deletions.
52 changes: 50 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -66,6 +66,7 @@ Describe the process (`onFinishFloatingView`) that is called when you exit the F
5) Add the permission to AndroidManifest
```xml
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
```

6) Define the Service to AndroidManifest
Expand All @@ -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)
Expand All @@ -104,6 +121,37 @@ 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`.

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

Expand Down
11 changes: 2 additions & 9 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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-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
Expand All @@ -19,11 +19,4 @@ allprojects {
jcenter()
google()
}
}

ext {
compileSdkVersion = 27
buildToolsVersion = '27.0.3'
targetSdkVersion = 27
minSdkVersion = 14
}
}
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Mon May 07 16:30:08 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.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
14 changes: 7 additions & 7 deletions library/build.gradle
Original file line number Diff line number Diff line change
@@ -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-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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -313,6 +318,11 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList
*/
private int mTouchXOffset;

/**
* Offset of touch Y coordinate
*/
private int mTouchYOffset;

/**
* 左・右端に寄せるアニメーション
*/
Expand Down Expand Up @@ -388,6 +398,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;
Expand Down Expand Up @@ -427,10 +442,17 @@ class FloatingView extends FrameLayout implements ViewTreeObserver.OnPreDrawList

mMoveLimitRect = new Rect();
mPositionLimitRect = new Rect();
mSafeInsetRect = new Rect();

// ステータスバーの高さを取得
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();
Expand Down Expand Up @@ -546,18 +568,69 @@ 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
mStatusBarHeight = isHideStatusBar ? 0 : mBaseStatusBarHeight;
// touch X offset(navigation bar is displayed and it is on the left side of the device)
mTouchXOffset = !isHideNavigationBar && hasTouchXOffset ? mBaseNavigationBarRotatedHeight : 0;
updateStatusBarHeight(isHideStatusBar, isPortrait);
// touch X offset(support Cutout)
updateTouchXOffset(isHideNavigationBar, windowLeftOffset);
// touch Y offset(support Cutout)
mTouchYOffset = isPortrait ? mSafeInsetRect.top : 0;
// navigation bar
updateNavigationBarOffset(isHideNavigationBar, isPortrait);
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) {
// 1.(No Cutout)No StatusBar(=0)
// 2.(Has Cutout)StatusBar is not included in mMetrics.heightPixels (=0)
mStatusBarHeight = 0;
return;
}

// 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;
}
}

/**
* 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.
*
Expand Down Expand Up @@ -1327,7 +1400,7 @@ private int getXByTouch() {
* @return FloatingViewのY座標
*/
private int getYByTouch() {
return (int) (mMetrics.heightPixels + mNavigationBarVerticalOffset - (mScreenTouchY - mLocalTouchY + getHeight()));
return (int) (mMetrics.heightPixels + mNavigationBarVerticalOffset - (mScreenTouchY - mLocalTouchY + getHeight() - mTouchYOffset));
}

/**
Expand Down Expand Up @@ -1362,6 +1435,15 @@ 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);
}

/**
* アニメーションの制御を行うハンドラです。
*/
Expand Down Expand Up @@ -1520,7 +1602,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;
Expand Down
Loading

0 comments on commit f5ad373

Please sign in to comment.