Merge pull request #11314 from t895/menu-cutout-padding
Android: Pad menu fragment when expanding to cutout area
This commit is contained in:
commit
6abcaadd5a
|
@ -16,6 +16,7 @@ import android.view.Menu;
|
|||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
@ -25,6 +26,9 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
@ -342,6 +346,8 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
|
|||
ActivityEmulationBinding binding = ActivityEmulationBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
setInsets(binding.frameMenu);
|
||||
|
||||
// Find or create the EmulationFragment
|
||||
mEmulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentById(R.id.frame_emulation_fragment);
|
||||
|
@ -538,6 +544,28 @@ public final class EmulationActivity extends AppCompatActivity implements ThemeP
|
|||
}
|
||||
}
|
||||
|
||||
private void setInsets(View view)
|
||||
{
|
||||
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) ->
|
||||
{
|
||||
Insets cutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout());
|
||||
ViewGroup.MarginLayoutParams mlpMenu =
|
||||
(ViewGroup.MarginLayoutParams) v.getLayoutParams();
|
||||
int menuWidth = getResources().getDimensionPixelSize(R.dimen.menu_width);
|
||||
if (ViewCompat.getLayoutDirection(v) == ViewCompat.LAYOUT_DIRECTION_LTR)
|
||||
{
|
||||
mlpMenu.width = cutInsets.left + menuWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
mlpMenu.width = cutInsets.right + menuWidth;
|
||||
}
|
||||
NativeLibrary.SetObscuredPixelsTop(cutInsets.top);
|
||||
NativeLibrary.SetObscuredPixelsLeft(cutInsets.left);
|
||||
return windowInsets;
|
||||
});
|
||||
}
|
||||
|
||||
public void showOverlayControlsMenu(@NonNull View anchor)
|
||||
{
|
||||
PopupMenu popup = new PopupMenu(this, anchor);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package org.dolphinemu.dolphinemu.fragments;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -14,6 +13,9 @@ import android.widget.LinearLayout;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
|
@ -21,6 +23,7 @@ import org.dolphinemu.dolphinemu.R;
|
|||
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||
import org.dolphinemu.dolphinemu.databinding.FragmentIngameMenuBinding;
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
|
||||
import org.dolphinemu.dolphinemu.utils.InsetsHelper;
|
||||
|
||||
public final class MenuFragment extends Fragment implements View.OnClickListener
|
||||
{
|
||||
|
@ -28,6 +31,8 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
|
|||
private static final String KEY_WII = "wii";
|
||||
private static SparseIntArray buttonsActionsMap = new SparseIntArray();
|
||||
|
||||
private int mCutInset = 0;
|
||||
|
||||
static
|
||||
{
|
||||
buttonsActionsMap
|
||||
|
@ -68,14 +73,6 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
|
|||
return fragment;
|
||||
}
|
||||
|
||||
// This is primarily intended to account for any navigation bar at the bottom of the screen
|
||||
private int getBottomPaddingRequired()
|
||||
{
|
||||
Rect visibleFrame = new Rect();
|
||||
requireActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame);
|
||||
return visibleFrame.bottom - visibleFrame.top - getResources().getDisplayMetrics().heightPixels;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
|
@ -88,6 +85,7 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
|
|||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
setInsets();
|
||||
updatePauseUnpauseVisibility();
|
||||
|
||||
if (!requireActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN))
|
||||
|
@ -100,21 +98,6 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
|
|||
mBinding.menuRefreshWiimotes.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
int bottomPaddingRequired = getBottomPaddingRequired();
|
||||
|
||||
// Provide a safe zone between the navigation bar and Exit Emulation to avoid accidental touches
|
||||
float density = getResources().getDisplayMetrics().density;
|
||||
if (bottomPaddingRequired >= 32 * density)
|
||||
{
|
||||
bottomPaddingRequired += 32 * density;
|
||||
}
|
||||
|
||||
if (bottomPaddingRequired > view.getPaddingBottom())
|
||||
{
|
||||
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(),
|
||||
view.getPaddingRight(), bottomPaddingRequired);
|
||||
}
|
||||
|
||||
LinearLayout options = mBinding.layoutOptions;
|
||||
for (int childIndex = 0; childIndex < options.getChildCount(); childIndex++)
|
||||
{
|
||||
|
@ -130,11 +113,41 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
|
|||
{
|
||||
mBinding.textGameTitle.setText(title);
|
||||
}
|
||||
}
|
||||
|
||||
if (getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR)
|
||||
private void setInsets()
|
||||
{
|
||||
ViewCompat.setOnApplyWindowInsetsListener(mBinding.getRoot(), (v, windowInsets) ->
|
||||
{
|
||||
view.post(() -> NativeLibrary.SetObscuredPixelsLeft(view.getWidth()));
|
||||
}
|
||||
Insets cutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout());
|
||||
mCutInset = cutInsets.left;
|
||||
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
if (ViewCompat.getLayoutDirection(v) == ViewCompat.LAYOUT_DIRECTION_LTR)
|
||||
{
|
||||
left = cutInsets.left;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = cutInsets.right;
|
||||
}
|
||||
|
||||
v.post(() -> NativeLibrary.SetObscuredPixelsLeft(v.getWidth()));
|
||||
|
||||
// Don't use padding if the navigation bar isn't in the way
|
||||
if (InsetsHelper.getBottomPaddingRequired(requireActivity()) > 0)
|
||||
{
|
||||
v.setPadding(left, cutInsets.top, right,
|
||||
cutInsets.bottom + InsetsHelper.getNavigationBarHeight(requireContext()));
|
||||
}
|
||||
else
|
||||
{
|
||||
v.setPadding(left, cutInsets.top, right,
|
||||
cutInsets.bottom + getResources().getDimensionPixelSize(R.dimen.spacing_large));
|
||||
}
|
||||
return windowInsets;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -155,7 +168,7 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
|
|||
{
|
||||
super.onDestroyView();
|
||||
|
||||
NativeLibrary.SetObscuredPixelsLeft(0);
|
||||
NativeLibrary.SetObscuredPixelsLeft(mCutInset);
|
||||
mBinding = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package org.dolphinemu.dolphinemu.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -222,4 +224,24 @@ public class InsetsHelper
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int getNavigationBarHeight(Context context)
|
||||
{
|
||||
Resources resources = context.getResources();
|
||||
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
if (resourceId > 0)
|
||||
{
|
||||
return resources.getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is primarily intended to account for any navigation bar at the bottom of the screen
|
||||
public static int getBottomPaddingRequired(Activity activity)
|
||||
{
|
||||
Rect visibleFrame = new Rect();
|
||||
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame);
|
||||
return visibleFrame.bottom - visibleFrame.top -
|
||||
activity.getResources().getDisplayMetrics().heightPixels;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<FrameLayout
|
||||
android:id="@+id/frame_menu"
|
||||
android:layout_width="260dp"
|
||||
android:layout_width="@dimen/menu_width"
|
||||
android:layout_height="match_parent"
|
||||
tools:layout="@layout/fragment_ingame_menu"/>
|
||||
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="16dp"
|
||||
android:background="?attr/colorSurface"
|
||||
tools:layout_width="250dp">
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
tools:layout_width="250dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_game_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginHorizontal="32dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginVertical="24dp"
|
||||
android:ellipsize="end"
|
||||
android:letterSpacing="0"
|
||||
android:maxLines="@integer/game_title_lines"
|
||||
|
@ -22,11 +21,16 @@
|
|||
android:textColor="?attr/colorOnSurface"
|
||||
tools:text="The Legend of Zelda: The Wind Waker" />
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:scrollbarSize="8dp"
|
||||
android:scrollbarSize="4dp"
|
||||
android:fadeScrollbars="false">
|
||||
|
||||
<LinearLayout
|
||||
|
@ -38,73 +42,62 @@
|
|||
<Button
|
||||
android:id="@+id/menu_pause_emulation"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/pause_emulation" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_unpause_emulation"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/unpause_emulation"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_take_screenshot"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/emulation_screenshot" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_quicksave"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/emulation_quicksave"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_quickload"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/emulation_quickload"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_emulation_save_root"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/emulation_savestate"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_emulation_load_root"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/emulation_loadstate"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_settings"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/grid_menu_settings" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_overlay_controls"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:text="@string/emulation_overlay_controls" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_refresh_wiimotes"
|
||||
android:text="@string/emulation_refresh_wiimotes"
|
||||
android:letterSpacing="0"
|
||||
style="@style/InGameMenuOption"/>
|
||||
style="@style/InGameMenuOption" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_change_disc"
|
||||
android:text="@string/emulation_change_disc"
|
||||
android:letterSpacing="0"
|
||||
style="@style/InGameMenuOption"/>
|
||||
style="@style/InGameMenuOption" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -113,14 +106,12 @@
|
|||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider_2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_exit"
|
||||
style="@style/InGameMenuOption"
|
||||
android:letterSpacing="0"
|
||||
android:layout_marginTop="@dimen/spacing_large"
|
||||
android:text="@string/emulation_exit" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
<dimen name="spacing_small">4dp</dimen>
|
||||
<dimen name="spacing_medlarge">12dp</dimen>
|
||||
<dimen name="spacing_large">16dp</dimen>
|
||||
<dimen name="menu_width">256dp</dimen>
|
||||
<dimen name="card_width">135dp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -2,16 +2,14 @@
|
|||
<resources>
|
||||
<!-- Custom button styles -->
|
||||
<style name="InGameMenuOption" parent="Widget.Material3.Button.TextButton">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">48dp</item>
|
||||
<item name="android:textColor">?attr/colorOnSurface</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:fontFamily">sans-serif-condensed</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">48dp</item>
|
||||
<item name="android:gravity">center_vertical|left</item>
|
||||
<item name="android:paddingLeft">32dp</item>
|
||||
<item name="android:paddingRight">32dp</item>
|
||||
<item name="android:layout_margin">0dp</item>
|
||||
</style>
|
||||
|
||||
<style name="OverlayInGameMenuOption" parent="InGameMenuOption">
|
||||
|
|
Loading…
Reference in New Issue