Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
flutter_boost_1.22.4
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
谢冠章
flutter_boost_1.22.4
Commits
368ae69d
Commit
368ae69d
authored
Oct 14, 2019
by
yangwu.jia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Boost 1.9升级,TextField键盘呼出问题解决
parent
c7fe899c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
422 additions
and
147 deletions
+422
-147
android/src/main/java/com/idlefish/flutterboost/XFlutterView.java
...src/main/java/com/idlefish/flutterboost/XFlutterView.java
+271
-118
android/src/main/java/com/idlefish/flutterboost/XTextInputPlugin.java
...main/java/com/idlefish/flutterboost/XTextInputPlugin.java
+144
-22
android/src/main/java/com/idlefish/flutterboost/containers/FlutterActivityAndFragmentDelegate.java
...rboost/containers/FlutterActivityAndFragmentDelegate.java
+4
-4
android/src/main/java/com/idlefish/flutterboost/containers/FlutterSplashView.java
...m/idlefish/flutterboost/containers/FlutterSplashView.java
+2
-2
example/lib/main.dart
example/lib/main.dart
+1
-1
No files found.
android/src/main/java/com/idlefish/flutterboost/XFlutterView.java
View file @
368ae69d
package
com.idlefish.flutterboost
;
import
android.annotation.TargetApi
;
import
android.a
pp.Activity
;
import
android.a
nnotation.SuppressLint
;
import
android.content.Context
;
import
android.content.res.Configuration
;
//import android.graphics.Insets;
import
android.graphics.Rect
;
import
android.os.Build
;
import
android.os.LocaleList
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.RequiresApi
;
import
android.support.annotation.VisibleForTesting
;
import
android.support.v4.view.ViewCompat
;
import
android.text.format.DateFormat
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.KeyEvent
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.view.WindowInsets
;
import
android.view.accessibility.AccessibilityManager
;
import
android.view.accessibility.AccessibilityNodeProvider
;
...
...
@@ -23,23 +26,43 @@ import android.view.inputmethod.InputConnection;
import
android.widget.FrameLayout
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Set
;
import
io.flutter.embedding.android.AndroidKeyProcessor
;
import
io.flutter.embedding.android.AndroidTouchProcessor
;
import
io.flutter.embedding.android.FlutterSurfaceView
;
import
io.flutter.embedding.android.FlutterTextureView
;
import
io.flutter.embedding.android.FlutterView
;
import
io.flutter.Log
;
import
io.flutter.embedding.android.*
;
import
io.flutter.embedding.engine.FlutterEngine
;
import
io.flutter.embedding.engine.renderer.FlutterRenderer
;
import
io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener
;
import
io.flutter.plugin.editing.TextInputPlugin
;
import
io.flutter.plugin.platform.Platform
Plugin
;
import
io.flutter.plugin.platform.Platform
ViewsController
;
import
io.flutter.view.AccessibilityBridge
;
/**
* Displays a Flutter UI on an Android device.
* <p>
* A {@code FlutterView}'s UI is painted by a corresponding {@link FlutterEngine}.
* <p>
* A {@code FlutterView} can operate in 2 different {@link RenderMode}s:
* <ol>
* <li>{@link RenderMode#surface}, which paints a Flutter UI to a {@link android.view.SurfaceView}.
* This mode has the best performance, but a {@code FlutterView} in this mode cannot be positioned
* between 2 other Android {@code View}s in the z-index, nor can it be animated/transformed.
* Unless the special capabilities of a {@link android.graphics.SurfaceTexture} are required,
* developers should strongly prefer this render mode.</li>
* <li>{@link RenderMode#texture}, which paints a Flutter UI to a {@link android.graphics.SurfaceTexture}.
* This mode is not as performant as {@link RenderMode#surface}, but a {@code FlutterView} in this
* mode can be animated and transformed, as well as positioned in the z-index between 2+ other
* Android {@code Views}. Unless the special capabilities of a {@link android.graphics.SurfaceTexture}
* are required, developers should strongly prefer the {@link RenderMode#surface} render mode.</li>
* </ol>
* See <a>https://source.android.com/devices/graphics/arch-tv#surface_or_texture</a> for more
* information comparing {@link android.view.SurfaceView} and {@link android.view.TextureView}.
*/
public
class
XFlutterView
extends
FrameLayout
{
private
static
final
String
TAG
=
"
X
FlutterView"
;
private
static
final
String
TAG
=
"FlutterView"
;
// Behavior configuration of this FlutterView.
@NonNull
...
...
@@ -50,10 +73,14 @@ public class XFlutterView extends FrameLayout {
// Internal view hierarchy references.
@Nullable
private
FlutterRenderer
.
RenderSurface
renderSurface
;
private
final
Set
<
OnFirstFrameRenderedListener
>
onFirstFrameRenderedListeners
=
new
HashSet
<>();
private
boolean
didRenderFirstFrame
;
// Connections to a Flutter execution context.
@Nullable
private
FlutterEngine
flutterEngine
;
@NonNull
private
final
Set
<
FlutterView
.
FlutterEngineAttachmentListener
>
flutterEngineAttachmentListeners
=
new
HashSet
<>();
// Components that process various types of Android View input and events,
// possibly storing intermediate state, and communicating those events to Flutter.
...
...
@@ -61,9 +88,9 @@ public class XFlutterView extends FrameLayout {
// These components essentially add some additional behavioral logic on top of
// existing, stateless system channels, e.g., KeyEventChannel, TextInputChannel, etc.
@Nullable
private
X
TextInputPlugin
textInputPlugin
;
private
TextInputPlugin
textInputPlugin
;
@Nullable
private
X
AndroidKeyProcessor
androidKeyProcessor
;
private
AndroidKeyProcessor
androidKeyProcessor
;
@Nullable
private
AndroidTouchProcessor
androidTouchProcessor
;
@Nullable
...
...
@@ -79,17 +106,51 @@ public class XFlutterView extends FrameLayout {
}
};
private
final
OnFirstFrameRenderedListener
onFirstFrameRenderedListener
=
new
OnFirstFrameRenderedListener
()
{
@Override
public
void
onFirstFrameRendered
()
{
didRenderFirstFrame
=
true
;
for
(
OnFirstFrameRenderedListener
listener
:
onFirstFrameRenderedListeners
)
{
listener
.
onFirstFrameRendered
();
}
}
};
/**
* Constructs a {@code FlutterView} programmatically, without any XML attributes.
* <p>
* <ul>
* <li>{@link #renderMode} defaults to {@link RenderMode#surface}.</li>
* <li>{@link #transparencyMode} defaults to {@link TransparencyMode#opaque}.</li>
* </ul>
* {@code FlutterView} requires an {@code Activity} instead of a generic {@code Context}
* to be compatible with {@link PlatformViewsController}.
*/
public
XFlutterView
(
@NonNull
Context
context
)
{
this
(
context
,
null
,
null
,
null
);
}
/**
* Constructs a {@code FlutterView} programmatically, without any XML attributes,
* and allows selection of a {@link #renderMode}.
* <p>
* {@link #transparencyMode} defaults to {@link TransparencyMode#opaque}.
* <p>
* {@code FlutterView} requires an {@code Activity} instead of a generic {@code Context}
* to be compatible with {@link PlatformViewsController}.
*/
public
XFlutterView
(
@NonNull
Context
context
,
@NonNull
FlutterView
.
RenderMode
renderMode
)
{
this
(
context
,
null
,
renderMode
,
null
);
}
/**
* Constructs a {@code FlutterView} programmatically, without any XML attributes,
* assumes the use of {@link RenderMode#surface}, and allows selection of a {@link #transparencyMode}.
* <p>
* {@code FlutterView} requires an {@code Activity} instead of a generic {@code Context}
* to be compatible with {@link PlatformViewsController}.
*/
public
XFlutterView
(
@NonNull
Context
context
,
@NonNull
FlutterView
.
TransparencyMode
transparencyMode
)
{
this
(
context
,
null
,
FlutterView
.
RenderMode
.
surface
,
transparencyMode
);
}
...
...
@@ -97,6 +158,9 @@ public class XFlutterView extends FrameLayout {
/**
* Constructs a {@code FlutterView} programmatically, without any XML attributes, and allows
* a selection of {@link #renderMode} and {@link #transparencyMode}.
* <p>
* {@code FlutterView} requires an {@code Activity} instead of a generic {@code Context}
* to be compatible with {@link PlatformViewsController}.
*/
public
XFlutterView
(
@NonNull
Context
context
,
@NonNull
FlutterView
.
RenderMode
renderMode
,
@NonNull
FlutterView
.
TransparencyMode
transparencyMode
)
{
this
(
context
,
null
,
renderMode
,
transparencyMode
);
...
...
@@ -104,9 +168,11 @@ public class XFlutterView extends FrameLayout {
/**
* Constructs a {@code FlutterSurfaceView} in an XML-inflation-compliant manner.
*
* // TODO(mattcarroll): expose renderMode in XML when build system supports R.attr
* <p>
* {@code FlutterView} requires an {@code Activity} instead of a generic {@code Context}
* to be compatible with {@link PlatformViewsController}.
*/
// TODO(mattcarroll): expose renderMode in XML when build system supports R.attr
public
XFlutterView
(
@NonNull
Context
context
,
@Nullable
AttributeSet
attrs
)
{
this
(
context
,
attrs
,
null
,
null
);
}
...
...
@@ -121,17 +187,17 @@ public class XFlutterView extends FrameLayout {
}
private
void
init
()
{
Log
.
d
(
TAG
,
"Initializing FlutterView"
);
Log
.
v
(
TAG
,
"Initializing FlutterView"
);
switch
(
renderMode
)
{
case
surface:
Log
.
d
(
TAG
,
"Internally creat
ing a FlutterSurfaceView."
);
Log
.
v
(
TAG
,
"Internally us
ing a FlutterSurfaceView."
);
FlutterSurfaceView
flutterSurfaceView
=
new
FlutterSurfaceView
(
getContext
(),
transparencyMode
==
FlutterView
.
TransparencyMode
.
transparent
);
renderSurface
=
flutterSurfaceView
;
addView
(
flutterSurfaceView
);
break
;
case
texture:
Log
.
d
(
TAG
,
"Internally creat
ing a FlutterTextureView."
);
Log
.
v
(
TAG
,
"Internally us
ing a FlutterTextureView."
);
FlutterTextureView
flutterTextureView
=
new
FlutterTextureView
(
getContext
());
renderSurface
=
flutterTextureView
;
addView
(
flutterTextureView
);
...
...
@@ -143,12 +209,32 @@ public class XFlutterView extends FrameLayout {
setFocusableInTouchMode
(
true
);
}
/**
* Returns true if an attached {@link FlutterEngine} has rendered at least 1 frame to this
* {@code FlutterView}.
* <p>
* Returns false if no {@link FlutterEngine} is attached.
* <p>
* This flag is specific to a given {@link FlutterEngine}. The following hypothetical timeline
* demonstrates how this flag changes over time.
* <ol>
* <li>{@code flutterEngineA} is attached to this {@code FlutterView}: returns false</li>
* <li>{@code flutterEngineA} renders its first frame to this {@code FlutterView}: returns true</li>
* <li>{@code flutterEngineA} is detached from this {@code FlutterView}: returns false</li>
* <li>{@code flutterEngineB} is attached to this {@code FlutterView}: returns false</li>
* <li>{@code flutterEngineB} renders its first frame to this {@code FlutterView}: returns true</li>
* </ol>
*/
public
boolean
hasRenderedFirstFrame
()
{
return
didRenderFirstFrame
;
}
/**
* Adds the given {@code listener} to this {@code FlutterView}, to be notified upon Flutter's
* first rendered frame.
*/
public
void
addOnFirstFrameRenderedListener
(
@NonNull
OnFirstFrameRenderedListener
listener
)
{
renderSurface
.
addOnFirstFrameRenderedListener
(
listener
);
onFirstFrameRenderedListeners
.
add
(
listener
);
}
/**
...
...
@@ -156,7 +242,7 @@ public class XFlutterView extends FrameLayout {
* {@link #addOnFirstFrameRenderedListener(OnFirstFrameRenderedListener)}.
*/
public
void
removeOnFirstFrameRenderedListener
(
@NonNull
OnFirstFrameRenderedListener
listener
)
{
renderSurface
.
removeOnFirstFrameRenderedListener
(
listener
);
onFirstFrameRenderedListeners
.
remove
(
listener
);
}
//------- Start: Process View configuration that Flutter cares about. ------
...
...
@@ -168,16 +254,11 @@ public class XFlutterView extends FrameLayout {
* change, device language change, device text scale factor change, etc.
*/
@Override
protected
void
onConfigurationChanged
(
Configuration
newConfig
)
{
protected
void
onConfigurationChanged
(
@NonNull
Configuration
newConfig
)
{
super
.
onConfigurationChanged
(
newConfig
);
try
{
sendLocalesToFlutter
(
newConfig
);
sendUserSettingsToFlutter
();
}
catch
(
Throwable
e
){
Log
.
e
(
TAG
,
"onConfigurationChanged error "
);
}
Log
.
v
(
TAG
,
"Configuration changed. Sending locales and user settings to Flutter."
);
sendLocalesToFlutter
(
newConfig
);
sendUserSettingsToFlutter
();
}
/**
...
...
@@ -194,6 +275,9 @@ public class XFlutterView extends FrameLayout {
@Override
protected
void
onSizeChanged
(
int
width
,
int
height
,
int
oldWidth
,
int
oldHeight
)
{
super
.
onSizeChanged
(
width
,
height
,
oldWidth
,
oldHeight
);
Log
.
v
(
TAG
,
"Size changed. Sending Flutter new viewport metrics. FlutterView was "
+
oldWidth
+
" x "
+
oldHeight
+
", it is now "
+
width
+
" x "
+
height
);
viewportMetrics
.
width
=
width
;
viewportMetrics
.
height
=
height
;
sendViewportMetricsToFlutter
();
...
...
@@ -212,7 +296,12 @@ public class XFlutterView extends FrameLayout {
@Override
@TargetApi
(
20
)
@RequiresApi
(
20
)
public
final
WindowInsets
onApplyWindowInsets
(
WindowInsets
insets
)
{
// The annotations to suppress "InlinedApi" and "NewApi" lints prevent lint warnings
// caused by usage of Android Q APIs. These calls are safe because they are
// guarded.
@SuppressLint
({
"InlinedApi"
,
"NewApi"
})
@NonNull
public
final
WindowInsets
onApplyWindowInsets
(
@NonNull
WindowInsets
insets
)
{
WindowInsets
newInsets
=
super
.
onApplyWindowInsets
(
insets
);
// Status bar (top) and left/right system insets should partially obscure the content (padding).
...
...
@@ -226,6 +315,23 @@ public class XFlutterView extends FrameLayout {
viewportMetrics
.
viewInsetRight
=
0
;
viewportMetrics
.
viewInsetBottom
=
insets
.
getSystemWindowInsetBottom
();
viewportMetrics
.
viewInsetLeft
=
0
;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Insets systemGestureInsets = insets.getSystemGestureInsets();
// viewportMetrics.systemGestureInsetTop = systemGestureInsets.top;
// viewportMetrics.systemGestureInsetRight = systemGestureInsets.right;
// viewportMetrics.systemGestureInsetBottom = systemGestureInsets.bottom;
// viewportMetrics.systemGestureInsetLeft = systemGestureInsets.left;
// }
Log
.
v
(
TAG
,
"Updating window insets (onApplyWindowInsets()):\n"
+
"Status bar insets: Top: "
+
viewportMetrics
.
paddingTop
+
", Left: "
+
viewportMetrics
.
paddingLeft
+
", Right: "
+
viewportMetrics
.
paddingRight
+
"\n"
+
"Keyboard insets: Bottom: "
+
viewportMetrics
.
viewInsetBottom
+
", Left: "
+
viewportMetrics
.
viewInsetLeft
+
", Right: "
+
viewportMetrics
.
viewInsetRight
+
"System Gesture Insets - Left: "
+
viewportMetrics
.
systemGestureInsetLeft
+
", Top: "
+
viewportMetrics
.
systemGestureInsetTop
+
", Right: "
+
viewportMetrics
.
systemGestureInsetRight
+
", Bottom: "
+
viewportMetrics
.
viewInsetBottom
);
sendViewportMetricsToFlutter
();
return
newInsets
;
...
...
@@ -240,7 +346,7 @@ public class XFlutterView extends FrameLayout {
*/
@Override
@SuppressWarnings
(
"deprecation"
)
protected
boolean
fitSystemWindows
(
Rect
insets
)
{
protected
boolean
fitSystemWindows
(
@NonNull
Rect
insets
)
{
if
(
Build
.
VERSION
.
SDK_INT
<=
Build
.
VERSION_CODES
.
KITKAT
)
{
// Status bar, left/right system insets partially obscure content (padding).
viewportMetrics
.
paddingTop
=
insets
.
top
;
...
...
@@ -253,6 +359,13 @@ public class XFlutterView extends FrameLayout {
viewportMetrics
.
viewInsetRight
=
0
;
viewportMetrics
.
viewInsetBottom
=
insets
.
bottom
;
viewportMetrics
.
viewInsetLeft
=
0
;
Log
.
v
(
TAG
,
"Updating window insets (fitSystemWindows()):\n"
+
"Status bar insets: Top: "
+
viewportMetrics
.
paddingTop
+
", Left: "
+
viewportMetrics
.
paddingLeft
+
", Right: "
+
viewportMetrics
.
paddingRight
+
"\n"
+
"Keyboard insets: Bottom: "
+
viewportMetrics
.
viewInsetBottom
+
", Left: "
+
viewportMetrics
.
viewInsetLeft
+
", Right: "
+
viewportMetrics
.
viewInsetRight
);
sendViewportMetricsToFlutter
();
return
true
;
}
else
{
...
...
@@ -276,7 +389,8 @@ public class XFlutterView extends FrameLayout {
* rather than spread that logic throughout this {@code FlutterView}.
*/
@Override
public
InputConnection
onCreateInputConnection
(
EditorInfo
outAttrs
)
{
@Nullable
public
InputConnection
onCreateInputConnection
(
@NonNull
EditorInfo
outAttrs
)
{
if
(!
isAttachedToFlutterEngine
())
{
return
super
.
onCreateInputConnection
(
outAttrs
);
}
...
...
@@ -284,6 +398,21 @@ public class XFlutterView extends FrameLayout {
return
textInputPlugin
.
createInputConnection
(
this
,
outAttrs
);
}
/**
* Allows a {@code View} that is not currently the input connection target to invoke commands on
* the {@link android.view.inputmethod.InputMethodManager}, which is otherwise disallowed.
* <p>
* Returns true to allow non-input-connection-targets to invoke methods on
* {@code InputMethodManager}, or false to exclusively allow the input connection target to invoke
* such methods.
*/
@Override
public
boolean
checkInputConnectionProxy
(
View
view
)
{
return
flutterEngine
!=
null
?
flutterEngine
.
getPlatformViewsController
().
checkInputConnectionProxy
(
view
)
:
super
.
checkInputConnectionProxy
(
view
);
}
/**
* Invoked when key is released.
*
...
...
@@ -292,13 +421,13 @@ public class XFlutterView extends FrameLayout {
* software keyboard is used, though a software keyboard may choose to invoke
* this method in some situations.
*
* {@link KeyEvent}s are sent from Android to Flutter. {@link
AndroidKeyProcessor
}
* {@link KeyEvent}s are sent from Android to Flutter. {@link }
* may do some additional work with the given {@link KeyEvent}, e.g., combine this
* {@code keyCode} with the previous {@code keyCode} to generate a unicode combined
* character.
*/
@Override
public
boolean
onKeyUp
(
int
keyCode
,
KeyEvent
event
)
{
public
boolean
onKeyUp
(
int
keyCode
,
@NonNull
KeyEvent
event
)
{
if
(!
isAttachedToFlutterEngine
())
{
return
super
.
onKeyUp
(
keyCode
,
event
);
}
...
...
@@ -315,13 +444,13 @@ public class XFlutterView extends FrameLayout {
* software keyboard is used, though a software keyboard may choose to invoke
* this method in some situations.
*
* {@link KeyEvent}s are sent from Android to Flutter. {@link
AndroidKeyProcessor
}
* {@link KeyEvent}s are sent from Android to Flutter. {@link }
* may do some additional work with the given {@link KeyEvent}, e.g., combine this
* {@code keyCode} with the previous {@code keyCode} to generate a unicode combined
* character.
*/
@Override
public
boolean
onKeyDown
(
int
keyCode
,
KeyEvent
event
)
{
public
boolean
onKeyDown
(
int
keyCode
,
@NonNull
KeyEvent
event
)
{
if
(!
isAttachedToFlutterEngine
())
{
return
super
.
onKeyDown
(
keyCode
,
event
);
}
...
...
@@ -337,7 +466,7 @@ public class XFlutterView extends FrameLayout {
* method forwards all {@link MotionEvent} data from Android to Flutter.
*/
@Override
public
boolean
onTouchEvent
(
MotionEvent
event
)
{
public
boolean
onTouchEvent
(
@NonNull
MotionEvent
event
)
{
if
(!
isAttachedToFlutterEngine
())
{
return
super
.
onTouchEvent
(
event
);
}
...
...
@@ -362,7 +491,7 @@ public class XFlutterView extends FrameLayout {
* method forwards all {@link MotionEvent} data from Android to Flutter.
*/
@Override
public
boolean
onGenericMotionEvent
(
MotionEvent
event
)
{
public
boolean
onGenericMotionEvent
(
@NonNull
MotionEvent
event
)
{
boolean
handled
=
isAttachedToFlutterEngine
()
&&
androidTouchProcessor
.
onGenericMotionEvent
(
event
);
return
handled
?
true
:
super
.
onGenericMotionEvent
(
event
);
}
...
...
@@ -379,7 +508,7 @@ public class XFlutterView extends FrameLayout {
* processed here for accessibility purposes.
*/
@Override
public
boolean
onHoverEvent
(
MotionEvent
event
)
{
public
boolean
onHoverEvent
(
@NonNull
MotionEvent
event
)
{
if
(!
isAttachedToFlutterEngine
())
{
return
super
.
onHoverEvent
(
event
);
}
...
...
@@ -395,6 +524,7 @@ public class XFlutterView extends FrameLayout {
//-------- Start: Accessibility -------
@Override
@Nullable
public
AccessibilityNodeProvider
getAccessibilityNodeProvider
()
{
if
(
accessibilityBridge
!=
null
&&
accessibilityBridge
.
isAccessibilityEnabled
())
{
return
accessibilityBridge
;
...
...
@@ -406,12 +536,8 @@ public class XFlutterView extends FrameLayout {
}
}
// TODO(mattcarroll): Confer with Ian as to why we need this method. Delete if possible, otherwise add comments.
private
void
resetWillNotDraw
(
boolean
isAccessibilityEnabled
,
boolean
isTouchExplorationEnabled
)
{
if
(
flutterEngine
==
null
)
return
;
if
(
flutterEngine
.
getRenderer
()==
null
)
return
;
if
(!
flutterEngine
.
getRenderer
().
isSoftwareRenderingEnabled
())
{
setWillNotDraw
(!(
isAccessibilityEnabled
||
isTouchExplorationEnabled
));
}
else
{
...
...
@@ -431,9 +557,10 @@ public class XFlutterView extends FrameLayout {
* See {@link #detachFromFlutterEngine()} for information on how to detach from a
* {@link FlutterEngine}.
*/
public
void
attachToFlutterEngine
(
@NonNull
FlutterEngine
flutterEngine
)
{
Log
.
d
(
TAG
,
"attachToFlutterEngine()"
);
public
void
attachToFlutterEngine
(
@NonNull
FlutterEngine
flutterEngine
)
{
Log
.
d
(
TAG
,
"Attaching to a FlutterEngine: "
+
flutterEngine
);
if
(
isAttachedToFlutterEngine
())
{
if
(
flutterEngine
==
this
.
flutterEngine
)
{
// We are already attached to this FlutterEngine
...
...
@@ -442,76 +569,74 @@ public class XFlutterView extends FrameLayout {
}
// Detach from a previous FlutterEngine so we can attach to this new one.
Log
.
d
(
TAG
,
"Currently attached to a different engine. Detaching."
);
Log
.
d
(
TAG
,
"Currently attached to a different engine. Detaching and then attaching"
+
" to new engine."
);
detachFromFlutterEngine
();
}
this
.
flutterEngine
=
flutterEngine
;
// initialize PlatformViewsController
// this.flutterEngine.getPluginRegistry().getPlatformViewsController().attach(getContext(),flutterEngine.getRenderer(),flutterEngine.getDartExecutor());
// Instruct our FlutterRenderer that we are now its designated RenderSurface.
this
.
flutterEngine
.
getRenderer
().
attachToRenderSurface
(
renderSurface
);
FlutterRenderer
flutterRenderer
=
this
.
flutterEngine
.
getRenderer
();
didRenderFirstFrame
=
flutterRenderer
.
hasRenderedFirstFrame
();
flutterRenderer
.
attachToRenderSurface
(
renderSurface
);
flutterRenderer
.
addOnFirstFrameRenderedListener
(
onFirstFrameRenderedListener
);
// Initialize various components that know how to process Android View I/O
// in a way that Flutter understands.
if
(
textInputPlugin
==
null
){
textInputPlugin
=
new
XTextInputPlugin
(
this
,
flutterEngine
.
getTextInputChannel
()
);
if
(
this
.
textInputPlugin
!=
null
){
this
.
textInputPlugin
.
destroy
();
}
textInputPlugin
.
setTextInputMethodHandler
();
textInputPlugin
.
getInputMethodManager
().
restartInput
(
this
);
androidKeyProcessor
=
new
XAndroidKeyProcessor
(
this
.
flutterEngine
.
getKeyEventChannel
(),
textInputPlugin
);
this
.
textInputPlugin
=
new
TextInputPlugin
(
this
,
this
.
flutterEngine
.
getDartExecutor
(),
this
.
flutterEngine
.
getPlatformViewsController
());
androidTouchProcessor
=
new
AndroidTouchProcessor
(
this
.
flutterEngine
.
getRenderer
()
);
this
.
textInputPlugin
.
getInputMethodManager
().
restartInput
(
this
);
if
(
accessibilityBridge
==
null
){
accessibilityBridge
=
new
AccessibilityBridge
(
this
,
flutterEngine
.
getAccessibilityChannel
(),
(
AccessibilityManager
)
getContext
().
getSystemService
(
Context
.
ACCESSIBILITY_SERVICE
),
getContext
().
getContentResolver
(),
// TODO(mattcaroll): plumb the platform views controller to the accessibility bridge.
// https://github.com/flutter/flutter/issues/29618
null
);
accessibilityBridge
.
setOnAccessibilityChangeListener
(
onAccessibilityChangeListener
);
resetWillNotDraw
(
accessibilityBridge
.
isAccessibilityEnabled
(),
accessibilityBridge
.
isTouchExplorationEnabled
()
);
}
this
.
androidKeyProcessor
=
new
AndroidKeyProcessor
(
this
.
flutterEngine
.
getKeyEventChannel
(),
textInputPlugin
);
this
.
androidTouchProcessor
=
new
AndroidTouchProcessor
(
this
.
flutterEngine
.
getRenderer
());
this
.
accessibilityBridge
=
new
AccessibilityBridge
(
this
,
flutterEngine
.
getAccessibilityChannel
(),
(
AccessibilityManager
)
getContext
().
getSystemService
(
Context
.
ACCESSIBILITY_SERVICE
),
getContext
().
getContentResolver
(),
this
.
flutterEngine
.
getPlatformViewsController
()
);
accessibilityBridge
.
setOnAccessibilityChangeListener
(
onAccessibilityChangeListener
);
resetWillNotDraw
(
accessibilityBridge
.
isAccessibilityEnabled
(),
accessibilityBridge
.
isTouchExplorationEnabled
()
);
// Connect AccessibilityBridge to the PlatformViewsController within the FlutterEngine.
// This allows platform Views to hook into Flutter's overall accessibility system.
this
.
flutterEngine
.
getPlatformViewsController
().
attachAccessibilityBridge
(
accessibilityBridge
);
// Inform the Android framework that it should retrieve a new InputConnection
// now that an engine is attached.
// TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin
// textInputPlugin.getInputMethodManager().restartInput(this);
// Push View and Context related information from Android to Flutter.
sendUserSettingsToFlutter
();
sendLocalesToFlutter
(
getResources
().
getConfiguration
());
sendViewportMetricsToFlutter
();
}
public
void
release
(){
if
(
accessibilityBridge
!=
null
){
accessibilityBridge
.
release
();
// Notify engine attachment listeners of the attachment.
for
(
FlutterView
.
FlutterEngineAttachmentListener
listener
:
flutterEngineAttachmentListeners
)
{
listener
.
onFlutterEngineAttachedToFlutterView
(
flutterEngine
);
}
textInputPlugin
.
release
();
// If the first frame has already been rendered, notify all first frame listeners.
// Do this after all other initialization so that listeners don't inadvertently interact
// with a FlutterView that is only partially attached to a FlutterEngine.
if
(
didRenderFirstFrame
)
{
onFirstFrameRenderedListener
.
onFirstFrameRendered
();
}
}
/**
...
...
@@ -525,46 +650,79 @@ public class XFlutterView extends FrameLayout {
* {@link FlutterEngine}.
*/
public
void
detachFromFlutterEngine
()
{
Log
.
d
(
TAG
,
"
detachFromFlutterEngine()"
);
Log
.
d
(
TAG
,
"
Detaching from a FlutterEngine: "
+
flutterEngine
);
if
(!
isAttachedToFlutterEngine
())
{
Log
.
d
(
TAG
,
"Not attached to an engine. Doing nothing."
);
return
;
}
Log
.
d
(
TAG
,
"Detaching from Flutter Engine"
);
// detach platformviews in page in case memory leak
// flutterEngine.getPluginRegistry().getPlatformViewsController().detach();
// flutterEngine.getPluginRegistry().getPlatformViewsController().onFlutterViewDestroyed();
// Notify engine attachment listeners of the detachment.
for
(
FlutterView
.
FlutterEngineAttachmentListener
listener
:
flutterEngineAttachmentListeners
)
{
listener
.
onFlutterEngineDetachedFromFlutterView
();
}
// Disconnect the FlutterEngine's PlatformViewsController from the AccessibilityBridge.
flutterEngine
.
getPlatformViewsController
().
detachAccessibiltyBridge
();
// Disconnect and clean up the AccessibilityBridge.
accessibilityBridge
.
release
();
accessibilityBridge
=
null
;
// Inform the Android framework that it should retrieve a new InputConnection
// now that the engine is detached. The new InputConnection will be null, which
// signifies that this View does not process input (until a new engine is attached).
// TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin
// textInputPlugin.getInputMethodManager().restartInput(this);
textInputPlugin
.
getInputMethodManager
().
restartInput
(
this
);
// textInputPlugin.destroy();
// Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface.
// this.textInputPlugin.getInputMethodManager().restartInput(this);
flutterEngine
.
getRenderer
().
detachFromRenderSurface
();
FlutterRenderer
flutterRenderer
=
flutterEngine
.
getRenderer
();
didRenderFirstFrame
=
false
;
flutterRenderer
.
removeOnFirstFrameRenderedListener
(
onFirstFrameRenderedListener
);
flutterRenderer
.
detachFromRenderSurface
();
flutterEngine
=
null
;
// TODO(mattcarroll): clear the surface when JNI doesn't blow up
// if (isSurfaceAvailableForRendering) {
// Canvas canvas = surfaceHolder.lockCanvas();
// canvas.drawColor(Color.RED);
// surfaceHolder.unlockCanvasAndPost(canvas);
// }
}
private
boolean
isAttachedToFlutterEngine
()
{
/**
* Returns true if this {@code FlutterView} is currently attached to a {@link FlutterEngine}.
*/
@VisibleForTesting
public
boolean
isAttachedToFlutterEngine
()
{
return
flutterEngine
!=
null
;
}
/**
* Returns the {@link FlutterEngine} to which this {@code FlutterView} is currently attached,
* or null if this {@code FlutterView} is not currently attached to a {@link FlutterEngine}.
*/
@VisibleForTesting
@Nullable
public
FlutterEngine
getAttachedFlutterEngine
()
{
return
flutterEngine
;
}
/**
* attached to/detaches from a {@link FlutterEngine}.
*/
@VisibleForTesting
public
void
addFlutterEngineAttachmentListener
(
@NonNull
FlutterView
.
FlutterEngineAttachmentListener
listener
)
{
flutterEngineAttachmentListeners
.
add
(
listener
);
}
/**
*/
@VisibleForTesting
public
void
removeFlutterEngineAttachmentListener
(
@NonNull
FlutterView
.
FlutterEngineAttachmentListener
listener
)
{
flutterEngineAttachmentListeners
.
remove
(
listener
);
}
/**
* Send the current {@link Locale} configuration to Flutter.
*
* FlutterEngine must be non-null when this method is invoked.
*/
@SuppressWarnings
(
"deprecation"
)
private
void
sendLocalesToFlutter
(
Configuration
config
)
{
private
void
sendLocalesToFlutter
(
@NonNull
Configuration
config
)
{
List
<
Locale
>
locales
=
new
ArrayList
<>();
if
(
Build
.
VERSION
.
SDK_INT
>=
android
.
os
.
Build
.
VERSION_CODES
.
N
)
{
LocaleList
localeList
=
config
.
getLocales
();
...
...
@@ -576,9 +734,7 @@ public class XFlutterView extends FrameLayout {
}
else
{
locales
.
add
(
config
.
locale
);
}
if
(
flutterEngine
!=
null
&&
flutterEngine
.
getLocalizationChannel
()!=
null
){
flutterEngine
.
getLocalizationChannel
().
sendLocales
(
locales
);
}
flutterEngine
.
getLocalizationChannel
().
sendLocales
(
locales
);
}
/**
...
...
@@ -590,20 +746,17 @@ public class XFlutterView extends FrameLayout {
* FlutterEngine must be non-null when this method is invoked.
*/
private
void
sendUserSettingsToFlutter
()
{
if
(
flutterEngine
!=
null
&&
flutterEngine
.
getSettingsChannel
()!=
null
){
flutterEngine
.
getSettingsChannel
().
startMessage
()
.
setTextScaleFactor
(
getResources
().
getConfiguration
().
fontScale
)
.
setUse24HourFormat
(
DateFormat
.
is24HourFormat
(
getContext
()))
.
send
();
}
flutterEngine
.
getSettingsChannel
().
startMessage
()
.
setTextScaleFactor
(
getResources
().
getConfiguration
().
fontScale
)
.
setUse24HourFormat
(
DateFormat
.
is24HourFormat
(
getContext
()))
.
send
();
}
// TODO(mattcarroll): consider introducing a system channel for this communication instead of JNI
private
void
sendViewportMetricsToFlutter
()
{
Log
.
d
(
TAG
,
"sendViewportMetricsToFlutter()"
);
if
(!
isAttachedToFlutterEngine
())
{
Log
.
w
(
TAG
,
"Tried to send viewport metrics from Android to Flutter but this FlutterView was not attached to a FlutterEngine."
);
Log
.
w
(
TAG
,
"Tried to send viewport metrics from Android to Flutter but this "
+
"FlutterView was not attached to a FlutterEngine."
);
return
;
}
...
...
android/src/main/java/com/idlefish/flutterboost/XTextInputPlugin.java
View file @
368ae69d
package
com.idlefish.flutterboost
;
import
android.content.Context
;
import
android.os.Build
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.RequiresApi
;
import
android.text.Editable
;
import
android.text.InputType
;
import
android.text.Selection
;
...
...
@@ -13,20 +11,23 @@ import android.view.inputmethod.BaseInputConnection;
import
android.view.inputmethod.EditorInfo
;
import
android.view.inputmethod.InputConnection
;
import
android.view.inputmethod.InputMethodManager
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.embedding.engine.systemchannels.TextInputChannel
;
import
io.flutter.
view.FlutterView
;
import
io.flutter.
plugin.editing.TextInputPlugin
;
import
io.flutter.plugin.platform.PlatformViewsController
;
/**
* Android implementation of the text input plugin.
*/
public
class
XTextInputPlugin
{
public
class
XTextInputPlugin
{
@NonNull
private
View
mView
;
@NonNull
private
final
InputMethodManager
mImm
;
@NonNull
private
int
mClient
=
0
;
private
final
TextInputChannel
textInputChannel
;
@NonNull
private
InputTarget
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
NO_TARGET
,
0
);
@Nullable
private
TextInputChannel
.
Configuration
configuration
;
@Nullable
...
...
@@ -34,17 +35,27 @@ public class XTextInputPlugin {
private
boolean
mRestartInputPending
;
@Nullable
private
InputConnection
lastInputConnection
;
private
TextInputChannel
textInputChannel
;
public
XTextInputPlugin
(
View
view
,
TextInputChannel
mTextInputChannel
)
{
@NonNull
private
PlatformViewsController
platformViewsController
;
// When true following calls to createInputConnection will return the cached lastInputConnection if the input
// target is a platform view. See the comments on lockPlatformViewInputConnection for more details.
private
boolean
isInputConnectionLocked
;
public
XTextInputPlugin
(
View
view
,
TextInputChannel
textInputChannel
,
PlatformViewsController
platformViewsController
)
{
mView
=
view
;
mImm
=
(
InputMethodManager
)
view
.
getContext
().
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
textInputChannel
=
mTextInputChannel
;
this
.
textInputChannel
=
textInputChannel
;
this
.
platformViewsController
=
platformViewsController
;
// this.platformViewsController.attachTextInputPlugin(this);
}
public
void
release
(){
mView
=
null
;
}
public
void
setTextInputMethodHandler
(){
public
void
setTextInputMethodHandler
(
){
textInputChannel
.
setTextInputMethodHandler
(
new
TextInputChannel
.
TextInputMethodHandler
()
{
@Override
public
void
show
()
{
...
...
@@ -62,8 +73,8 @@ public class XTextInputPlugin {
}
@Override
public
void
setPlatformViewClient
(
int
i
)
{
public
void
setPlatformViewClient
(
int
platformViewId
)
{
setPlatformViewTextInputClient
(
platformViewId
);
}
@Override
...
...
@@ -76,9 +87,7 @@ public class XTextInputPlugin {
clearTextInputClient
();
}
});
}
public
void
release
(){
mView
=
null
;
}
@NonNull
...
...
@@ -86,6 +95,40 @@ public class XTextInputPlugin {
return
mImm
;
}
/***
* Use the current platform view input connection until unlockPlatformViewInputConnection is called.
*
* The current input connection instance is cached and any following call to @{link createInputConnection} returns
* the cached connection until unlockPlatformViewInputConnection is called.
*
* This is a no-op if the current input target isn't a platform view.
*
* This is used to preserve an input connection when moving a platform view from one virtual display to another.
*/
public
void
lockPlatformViewInputConnection
()
{
if
(
inputTarget
.
type
==
InputTarget
.
Type
.
PLATFORM_VIEW
)
{
isInputConnectionLocked
=
true
;
}
}
/**
* Unlocks the input connection.
*
* See also: @{link lockPlatformViewInputConnection}.
*/
public
void
unlockPlatformViewInputConnection
()
{
isInputConnectionLocked
=
false
;
}
/**
* Detaches the text input plugin from the platform views controller.
*
* The TextInputPlugin instance should not be used after calling this.
*/
public
void
destroy
()
{
platformViewsController
.
detachTextInputPlugin
();
}
private
static
int
inputTypeFromTextInputType
(
TextInputChannel
.
InputType
type
,
boolean
obscureText
,
...
...
@@ -114,6 +157,8 @@ public class XTextInputPlugin {
textType
|=
InputType
.
TYPE_TEXT_VARIATION_EMAIL_ADDRESS
;
}
else
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
URL
)
{
textType
|=
InputType
.
TYPE_TEXT_VARIATION_URI
;
}
else
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
VISIBLE_PASSWORD
)
{
textType
|=
InputType
.
TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
;
}
if
(
obscureText
)
{
...
...
@@ -136,8 +181,16 @@ public class XTextInputPlugin {
}
public
InputConnection
createInputConnection
(
View
view
,
EditorInfo
outAttrs
)
{
if
(
mClient
==
0
)
{
if
(
inputTarget
.
type
==
InputTarget
.
Type
.
NO_TARGET
)
{
lastInputConnection
=
null
;
return
null
;
}
if
(
inputTarget
.
type
==
InputTarget
.
Type
.
PLATFORM_VIEW
)
{
if
(
isInputConnectionLocked
)
{
return
lastInputConnection
;
}
lastInputConnection
=
platformViewsController
.
getPlatformViewById
(
inputTarget
.
id
).
onCreateInputConnection
(
outAttrs
);
return
lastInputConnection
;
}
...
...
@@ -166,7 +219,7 @@ public class XTextInputPlugin {
XInputConnectionAdaptor
connection
=
new
XInputConnectionAdaptor
(
view
,
mClient
,
inputTarget
.
id
,
textInputChannel
,
mEditable
);
...
...
@@ -182,24 +235,55 @@ public class XTextInputPlugin {
return
lastInputConnection
;
}
/**
* Clears a platform view text input client if it is the current input target.
*
* This is called when a platform view is disposed to make sure we're not hanging to a stale input
* connection.
*/
public
void
clearPlatformViewClient
(
int
platformViewId
)
{
if
(
inputTarget
.
type
==
InputTarget
.
Type
.
PLATFORM_VIEW
&&
inputTarget
.
id
==
platformViewId
)
{
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
NO_TARGET
,
0
);
hideTextInput
(
mView
);
mImm
.
restartInput
(
mView
);
mRestartInputPending
=
false
;
}
}
private
void
showTextInput
(
View
view
)
{
if
(
view
==
null
)
return
;
view
.
requestFocus
();
mImm
.
showSoftInput
(
view
,
0
);
}
private
void
hideTextInput
(
View
view
)
{
// Note: a race condition may lead to us hiding the keyboard here just after a platform view has shown it.
// This can only potentially happen when switching focus from a Flutter text field to a platform view's text
// field(by text field here I mean anything that keeps the keyboard open).
// See: https://github.com/flutter/flutter/issues/34169
mImm
.
hideSoftInputFromWindow
(
view
.
getApplicationWindowToken
(),
0
);
}
private
void
setTextInputClient
(
int
client
,
TextInputChannel
.
Configuration
configuration
)
{
mClient
=
client
;
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
FRAMEWORK_CLIENT
,
client
)
;
this
.
configuration
=
configuration
;
mEditable
=
Editable
.
Factory
.
getInstance
().
newEditable
(
""
);
// setTextInputClient will be followed by a call to setTextInputEditingState.
// Do a restartInput at that time.
mRestartInputPending
=
true
;
unlockPlatformViewInputConnection
();
}
private
void
setPlatformViewTextInputClient
(
int
platformViewId
)
{
// We need to make sure that the Flutter view is focused so that no imm operations get short circuited.
// Not asking for focus here specifically manifested in a but on API 28 devices where the platform view's
// request to show a keyboard was ignored.
mView
.
requestFocus
();
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
PLATFORM_VIEW
,
platformViewId
);
mImm
.
restartInput
(
mView
);
mRestartInputPending
=
false
;
}
private
void
applyStateToSelection
(
TextInputChannel
.
TextEditState
state
)
{
...
...
@@ -213,7 +297,6 @@ public class XTextInputPlugin {
}
}
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
CUPCAKE
)
private
void
setTextInputEditingState
(
View
view
,
TextInputChannel
.
TextEditState
state
)
{
if
(!
mRestartInputPending
&&
state
.
text
.
equals
(
mEditable
.
toString
()))
{
applyStateToSelection
(
state
);
...
...
@@ -230,6 +313,45 @@ public class XTextInputPlugin {
}
private
void
clearTextInputClient
()
{
mClient
=
0
;
if
(
inputTarget
.
type
==
InputTarget
.
Type
.
PLATFORM_VIEW
)
{
// Focus changes in the framework tree have no guarantees on the order focus nodes are notified. A node
// that lost focus may be notified before or after a node that gained focus.
// When moving the focus from a Flutter text field to an AndroidView, it is possible that the Flutter text
// field's focus node will be notified that it lost focus after the AndroidView was notified that it gained
// focus. When this happens the text field will send a clearTextInput command which we ignore.
// By doing this we prevent the framework from clearing a platform view input client(the only way to do so
// is to set a new framework text client). I don't see an obvious use case for "clearing" a platform views
// text input client, and it may be error prone as we don't know how the platform view manages the input
// connection and we probably shouldn't interfere.
// If we ever want to allow the framework to clear a platform view text client we should probably consider
// changing the focus manager such that focus nodes that lost focus are notified before focus nodes that
// gained focus as part of the same focus event.
return
;
}
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
NO_TARGET
,
0
);
unlockPlatformViewInputConnection
();
}
static
private
class
InputTarget
{
enum
Type
{
NO_TARGET
,
// InputConnection is managed by the TextInputPlugin, and events are forwarded to the Flutter framework.
FRAMEWORK_CLIENT
,
// InputConnection is managed by an embedded platform view.
PLATFORM_VIEW
}
public
InputTarget
(
@NonNull
Type
type
,
int
id
)
{
this
.
type
=
type
;
this
.
id
=
id
;
}
@NonNull
Type
type
;
// The ID of the input target.
//
// For framework clients this is the framework input connection client ID.
// For platform views this is the platform view's ID.
int
id
;
}
}
\ No newline at end of file
android/src/main/java/com/idlefish/flutterboost/containers/FlutterActivityAndFragmentDelegate.java
View file @
368ae69d
...
...
@@ -19,6 +19,7 @@ import java.util.Map;
import
com.idlefish.flutterboost.NewFlutterBoost
;
import
com.idlefish.flutterboost.XFlutterView
;
import
com.idlefish.flutterboost.interfaces.IFlutterViewContainer
;
import
com.idlefish.flutterboost.interfaces.IOperateSyncer
;
import
io.flutter.Log
;
...
...
@@ -44,7 +45,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
@Nullable
private
FlutterSplashView
flutterSplashView
;
@Nullable
private
FlutterView
flutterView
;
private
X
FlutterView
flutterView
;
@Nullable
private
PlatformPlugin
platformPlugin
;
...
...
@@ -167,7 +168,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
mSyncer
=
NewFlutterBoost
.
instance
().
containerManager
().
generateSyncer
(
this
);
ensureAlive
();
flutterView
=
new
FlutterView
(
host
.
getActivity
(),
NewFlutterBoost
.
instance
().
platform
().
renderMode
(),
host
.
getTransparencyMode
());
flutterView
=
new
X
FlutterView
(
host
.
getActivity
(),
NewFlutterBoost
.
instance
().
platform
().
renderMode
(),
host
.
getTransparencyMode
());
flutterView
.
addOnFirstFrameRenderedListener
(
onFirstFrameRenderedListener
);
...
...
@@ -229,6 +230,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
Log
.
v
(
TAG
,
"onPause()"
);
ensureAlive
();
mSyncer
.
onDisappear
();
flutterEngine
.
getLifecycleChannel
().
appIsInactive
();
}
...
...
@@ -236,8 +238,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
void
onStop
()
{
Log
.
v
(
TAG
,
"onStop()"
);
ensureAlive
();
mSyncer
.
onDisappear
();
flutterEngine
.
getLifecycleChannel
().
appIsPaused
();
// flutterView.detachFromFlutterEngine();
}
...
...
android/src/main/java/com/idlefish/flutterboost/containers/FlutterSplashView.java
View file @
368ae69d
...
...
@@ -28,7 +28,7 @@ public class FlutterSplashView extends FrameLayout {
@Nullable
private
SplashScreen
splashScreen
;
@Nullable
private
FlutterView
flutterView
;
private
X
FlutterView
flutterView
;
@Nullable
private
View
splashScreenView
;
@Nullable
...
...
@@ -112,7 +112,7 @@ public class FlutterSplashView extends FrameLayout {
* If no {@code splashScreen} is provided, this {@code FlutterSplashView} displays the
* given {@code flutterView} on its own.
*/
public
void
displayFlutterViewWithSplash
(
@NonNull
FlutterView
flutterView
,
@Nullable
SplashScreen
splashScreen
)
{
public
void
displayFlutterViewWithSplash
(
@NonNull
X
FlutterView
flutterView
,
@Nullable
SplashScreen
splashScreen
)
{
// If we were displaying a previous FlutterView, remove it.
if
(
this
.
flutterView
!=
null
)
{
this
.
flutterView
.
removeOnFirstFrameRenderedListener
(
onFirstFrameRenderedListener
);
...
...
example/lib/main.dart
View file @
368ae69d
...
...
@@ -35,7 +35,7 @@ class _MyAppState extends State<MyApp> {
return
MaterialApp
(
title:
'Flutter Boost example'
,
builder:
FlutterBoost
.
init
(
postPush:
_onRoutePushed
),
home:
FlutterRouteWidget
());
home:
Container
());
}
void
_onRoutePushed
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment