Skip to content

Commit

Permalink
Margin mode (AppAndFlow#85)
Browse files Browse the repository at this point in the history
* WIP: margin mode

* Reset props when mode changes

* Add android margin support

* Android status bar style

Co-authored-by: Jacob Parker <[email protected]>
  • Loading branch information
jacobp100 and Jacob Parker authored May 28, 2020
1 parent 53ade8f commit 778e3eb
Show file tree
Hide file tree
Showing 23 changed files with 617 additions and 209 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ or npm:
npm install --save react-native-safe-area-context
```

You then need to link the native parts of the library for the platforms you are using.
You then need to link the native parts of the library for the platforms you are using.

#### Linking in React Native >= 0.60

Expand Down Expand Up @@ -95,9 +95,11 @@ protected List<ReactPackage> getPackages() {

## Usage

`SafeAreaView` is a regular `View` component with the safe area edges applied as padding.
`SafeAreaView` is a regular `View` component with the safe area edges applied as padding - or margins if you prefer.

If you set your own padding on the view, it will be added to the padding from the safe area.
If you set your own padding or margin on the view, it will be added to the padding or margin from the safe area.

For the moment, you can't put paddings or margins as percent values - regardless of where your safe areas are being applied.

**If you are targeting web, you must set up `SafeAreaProvider` in as described in the hooks section**. You do not need to for native platforms.

Expand All @@ -123,6 +125,12 @@ All props are optional.

On iOS 10, emulate the safe area using the status bar height and home indicator sizes.

#### `mode`

`padding` (default) or `margin`

Apply the safe area to either the padding or the margin.

#### `edges`

Array of `top`, `right`, `bottom`, and `left`. Defaults to all.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public SafeAreaProvider(Context context) {
}

private void maybeUpdateInsets() {
EdgeInsets edgeInsets = SafeAreaUtils.getSafeAreaInsets(getRootView(), this);
EdgeInsets edgeInsets = SafeAreaUtils.getSafeAreaInsets(getRootView());
Rect frame = SafeAreaUtils.getFrame((ViewGroup) getRootView(), this);
if (edgeInsets != null && frame != null &&
(mLastInsets == null ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
}

View contentView = decorView.findViewById(android.R.id.content);
EdgeInsets insets = SafeAreaUtils.getSafeAreaInsets(decorView, contentView);
EdgeInsets insets = SafeAreaUtils.getSafeAreaInsets(decorView);
Rect frame = SafeAreaUtils.getFrame(decorView, contentView);
if (insets == null || frame == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
}
}

static @Nullable EdgeInsets getSafeAreaInsets(View rootView, View view) {
static @Nullable EdgeInsets getSafeAreaInsets(View rootView) {
EdgeInsets windowInsets = getRootWindowInsetsCompat(rootView);
if (windowInsets == null) {
return null;
Expand All @@ -45,13 +45,11 @@
// Calculate the part of the view that overlaps with window insets.
float windowWidth = rootView.getWidth();
float windowHeight = rootView.getHeight();
Rect visibleRect = new Rect();
view.getGlobalVisibleRect(visibleRect);

windowInsets.top = Math.max(windowInsets.top - visibleRect.top, 0);
windowInsets.left = Math.max(windowInsets.left - visibleRect.left, 0);
windowInsets.bottom = Math.max(visibleRect.top + view.getHeight() + windowInsets.bottom - windowHeight, 0);
windowInsets.right = Math.max(visibleRect.left + view.getWidth() + windowInsets.right - windowWidth, 0);
windowInsets.top = Math.max(windowInsets.top, 0);
windowInsets.left = Math.max(windowInsets.left, 0);
windowInsets.bottom = Math.max(rootView.getHeight() + windowInsets.bottom - windowHeight, 0);
windowInsets.right = Math.max(rootView.getWidth() + windowInsets.right - windowWidth, 0);
return windowInsets;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.ContextWrapper;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;

Expand All @@ -16,6 +17,7 @@

@SuppressLint("ViewConstructor")
public class SafeAreaView extends ReactViewGroup implements ViewTreeObserver.OnGlobalLayoutListener {
private SafeAreaViewMode mMode = SafeAreaViewMode.PADDING;
private @Nullable EdgeInsets mInsets;
private @Nullable EnumSet<SafeAreaViewEdges> mEdges;

Expand All @@ -40,7 +42,7 @@ private void updateInsets() {
? mEdges
: EnumSet.allOf(SafeAreaViewEdges.class);

SafeAreaViewLocalData localData = new SafeAreaViewLocalData(mInsets, edges);
SafeAreaViewLocalData localData = new SafeAreaViewLocalData(mInsets, mMode, edges);

ReactContext reactContext = getReactContext(this);
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
Expand All @@ -50,13 +52,18 @@ private void updateInsets() {
}
}

public void setMode(SafeAreaViewMode mode) {
mMode = mode;
updateInsets();
}

public void setEdges(EnumSet<SafeAreaViewEdges> edges) {
mEdges = edges;
updateInsets();
}

private void maybeUpdateInsets() {
EdgeInsets edgeInsets = SafeAreaUtils.getSafeAreaInsets(getRootView(), this);
EdgeInsets edgeInsets = SafeAreaUtils.getSafeAreaInsets(getRootView());
if (edgeInsets != null && (mInsets == null || !mInsets.equalsToEdgeInsets(edgeInsets))) {
mInsets = edgeInsets;
updateInsets();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@

public class SafeAreaViewLocalData {
private EdgeInsets mInsets;
private SafeAreaViewMode mMode;
private EnumSet<SafeAreaViewEdges> mEdges;

public SafeAreaViewLocalData(EdgeInsets insets, EnumSet<SafeAreaViewEdges> edges) {
public SafeAreaViewLocalData(EdgeInsets insets, SafeAreaViewMode mode, EnumSet<SafeAreaViewEdges> edges) {
mInsets = insets;
mMode = mode;
mEdges = edges;
}

public EdgeInsets getInsets() {
return mInsets;
}

public SafeAreaViewMode getMode() {
return mMode;
}

public EnumSet<SafeAreaViewEdges> getEdges() {
return mEdges;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ public Class<? extends LayoutShadowNode> getShadowNodeClass() {
return SafeAreaViewShadowNode.class;
}

@ReactProp(name = "mode")
public void setMode(SafeAreaView view, String mode) {
if ("padding".equals(mode)) {
view.setMode(SafeAreaViewMode.PADDING);
} else if ("margin".equals(mode)) {
view.setMode(SafeAreaViewMode.MARGIN);
}
}

@ReactProp(name = "edges")
public void setEdges(SafeAreaView view, @Nullable ReadableArray propList) {
EnumSet<SafeAreaViewEdges> edges = EnumSet.noneOf(SafeAreaViewEdges.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.th3rdwave.safeareacontext;

public enum SafeAreaViewMode {
PADDING,
MARGIN
}
Loading

0 comments on commit 778e3eb

Please sign in to comment.