Allow the root layout to be overriden. (#22887)
a
diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
index f5ef171..16763a2 100644
--- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
+++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
@@ -358,7 +358,7 @@
*/
@NonNull
private View createFragmentContainer() {
- FrameLayout container = new FrameLayout(this);
+ FrameLayout container = provideRootLayout(this);
container.setId(FRAGMENT_CONTAINER_ID);
container.setLayoutParams(
new ViewGroup.LayoutParams(
@@ -741,4 +741,10 @@
private boolean isDebuggable() {
return (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}
+
+ /** Returns a {@link FrameLayout} that is used as the content view of this activity. */
+ @NonNull
+ protected FrameLayout provideRootLayout(Context context) {
+ return new FrameLayout(context);
+ }
}
diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java
index 448646d..dc4b601 100644
--- a/shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java
+++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java
@@ -12,6 +12,8 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.embedding.android.FlutterActivityLaunchConfigs.BackgroundMode;
@@ -127,6 +129,24 @@
assertFalse(spyFlutterActivity.shouldHandleDeeplinking());
}
+ @Test
+ public void itAllowsRootLayoutOverride() {
+ FlutterFragmentActivityWithRootLayout activity =
+ Robolectric.buildActivity(FlutterFragmentActivityWithRootLayout.class).get();
+
+ activity.onCreate(null);
+ ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
+ boolean foundCustomView = false;
+ for (int i = 0; i < contentView.getChildCount(); i++) {
+ foundCustomView =
+ contentView.getChildAt(i) instanceof FlutterFragmentActivityWithRootLayout.CustomLayout;
+ if (foundCustomView) {
+ break;
+ }
+ }
+ assertTrue(foundCustomView);
+ }
+
static class FlutterFragmentActivityWithProvidedEngine extends FlutterFragmentActivity {
@Override
protected FlutterFragment createFlutterFragment() {
@@ -171,6 +191,20 @@
}
}
+ private static class FlutterFragmentActivityWithRootLayout
+ extends FlutterFragmentActivityWithProvidedEngine {
+ public static class CustomLayout extends FrameLayout {
+ public CustomLayout(Context context) {
+ super(context);
+ }
+ }
+
+ @Override
+ protected FrameLayout provideRootLayout(Context context) {
+ return new CustomLayout(context);
+ }
+ }
+
// This is just a compile time check to ensure that it's possible for FlutterFragmentActivity
// subclasses
// to provide their own intent builders which builds their own runtime types.