diff --git a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java index 27e1cc643..4d2d7b745 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java @@ -59,6 +59,7 @@ import com.hippo.ehviewer.gallery.DirGalleryProvider; import com.hippo.ehviewer.gallery.EhGalleryProvider; import com.hippo.ehviewer.gallery.GalleryProvider2; import com.hippo.ehviewer.widget.GalleryGuideView; +import com.hippo.ehviewer.widget.GalleryHeader; import com.hippo.ehviewer.widget.ReversibleSeekBar; import com.hippo.glgallery.GalleryPageView; import com.hippo.glgallery.GalleryProvider; @@ -378,6 +379,12 @@ public class GalleryActivity extends EhActivity implements SeekBar.OnSeekBarChan // Cutout if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + + GalleryHeader galleryHeader = findViewById(R.id.gallery_header); + galleryHeader.setOnApplyWindowInsetsListener((v, insets) -> { + galleryHeader.setDisplayCutout(insets.getDisplayCutout()); + return insets; + }); } if (Settings.getGuideGallery()) { diff --git a/app/src/main/java/com/hippo/ehviewer/widget/GalleryHeader.java b/app/src/main/java/com/hippo/ehviewer/widget/GalleryHeader.java new file mode 100644 index 000000000..16906ffbe --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/widget/GalleryHeader.java @@ -0,0 +1,108 @@ +/* + * Copyright 2019 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.ehviewer.widget; + +import android.content.Context; +import android.graphics.Rect; +import android.os.Build; +import android.util.AttributeSet; +import android.util.SparseIntArray; +import android.view.DisplayCutout; +import android.view.View; +import android.widget.FrameLayout; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; + +// Offset widgets to avoid notch +public class GalleryHeader extends FrameLayout { + + private SparseIntArray originalTopMargins = new SparseIntArray(); + private DisplayCutout displayCutout = null; + private int[] location = new int[2]; + private Rect rect = new Rect(); + + public GalleryHeader(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @RequiresApi(api = Build.VERSION_CODES.P) + public void setDisplayCutout(@Nullable DisplayCutout displayCutout) { + // Backup top margins + if (originalTopMargins.size() == 0) { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + originalTopMargins.append(child.getId(), ((MarginLayoutParams) child.getLayoutParams()).topMargin); + } + } + + if (displayCutout != null) { + // Update top margins + if (getWidth() == 0 && getHeight() == 0) { + this.displayCutout = displayCutout; + } else { + updateTopMargins(displayCutout); + } + } else if (originalTopMargins.size() != 0) { + // Reset + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + ((MarginLayoutParams) child.getLayoutParams()).topMargin = originalTopMargins.get(child.getId()); + } + // Layout + requestLayout(); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (displayCutout != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + updateTopMargins(displayCutout); + displayCutout = null; + } + } + + @RequiresApi(api = Build.VERSION_CODES.P) + private void updateTopMargins(@NonNull DisplayCutout displayCutout) { + getLocationOnScreen(location); + int y = location[1]; + + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + child.getLocationOnScreen(location); + + // Fix top margin + boolean intersected = false; + for (Rect notch : displayCutout.getBoundingRects()) { + rect.set(location[0], location[1], location[0] + child.getWidth(), location[1] + child.getHeight()); + if (Rect.intersects(notch, rect)) { + intersected = true; + ((MarginLayoutParams) child.getLayoutParams()).topMargin = originalTopMargins.get(child.getId()) + (notch.bottom - y); + break; + } + } + if (!intersected) { + ((MarginLayoutParams) child.getLayoutParams()).topMargin = originalTopMargins.get(child.getId()); + } + + // Layout + requestLayout(); + } + } +} diff --git a/app/src/main/res/layout/activity_gallery.xml b/app/src/main/res/layout/activity_gallery.xml index a4211f372..bd179bc96 100644 --- a/app/src/main/res/layout/activity_gallery.xml +++ b/app/src/main/res/layout/activity_gallery.xml @@ -26,34 +26,42 @@ android:layout_width="match_parent" android:layout_height="match_parent"/> - + android:layout_gravity="top"> - + - + + + + +