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
1
Merge Requests
1
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
7ead767f
Commit
7ead767f
authored
Sep 21, 2020
by
nightfallsad
Committed by
GitHub
Sep 21, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #9 from alibaba/master
update
parents
14d8bfa0
1571d96c
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
434 additions
and
143 deletions
+434
-143
.gitignore
.gitignore
+1
-0
.travis.yml
.travis.yml
+1
-1
Frequently Asked Question.md
Frequently Asked Question.md
+1
-1
README.md
README.md
+5
-1
README_CN.md
README_CN.md
+4
-1
android/src/main/java/com/idlefish/flutterboost/FlutterBoost.java
...src/main/java/com/idlefish/flutterboost/FlutterBoost.java
+12
-0
android/src/main/java/com/idlefish/flutterboost/FlutterViewContainerManager.java
...om/idlefish/flutterboost/FlutterViewContainerManager.java
+2
-0
android/src/main/java/com/idlefish/flutterboost/XFlutterTextureView.java
...n/java/com/idlefish/flutterboost/XFlutterTextureView.java
+186
-0
android/src/main/java/com/idlefish/flutterboost/XFlutterView.java
...src/main/java/com/idlefish/flutterboost/XFlutterView.java
+19
-52
android/src/main/java/com/idlefish/flutterboost/XInputConnectionAdaptor.java
...va/com/idlefish/flutterboost/XInputConnectionAdaptor.java
+1
-1
android/src/main/java/com/idlefish/flutterboost/XPlatformPlugin.java
.../main/java/com/idlefish/flutterboost/XPlatformPlugin.java
+9
-10
android/src/main/java/com/idlefish/flutterboost/XTextInputPlugin.java
...main/java/com/idlefish/flutterboost/XTextInputPlugin.java
+82
-27
android/src/main/java/com/idlefish/flutterboost/containers/BoostFlutterActivity.java
...dlefish/flutterboost/containers/BoostFlutterActivity.java
+5
-2
android/src/main/java/com/idlefish/flutterboost/containers/BoostViewUtils.java
.../com/idlefish/flutterboost/containers/BoostViewUtils.java
+24
-0
android/src/main/java/com/idlefish/flutterboost/containers/FlutterActivityAndFragmentDelegate.java
...rboost/containers/FlutterActivityAndFragmentDelegate.java
+1
-1
android/src/main/java/com/idlefish/flutterboost/containers/FlutterFragment.java
...com/idlefish/flutterboost/containers/FlutterFragment.java
+1
-4
ios/Classes/container/FLBFlutterViewContainer.m
ios/Classes/container/FLBFlutterViewContainer.m
+9
-1
lib/container/boost_container.dart
lib/container/boost_container.dart
+56
-35
lib/container/boost_page_route.dart
lib/container/boost_page_route.dart
+5
-0
lib/container/container_manager.dart
lib/container/container_manager.dart
+9
-5
lib/observers_holders.dart
lib/observers_holders.dart
+1
-1
No files found.
.gitignore
View file @
7ead767f
...
@@ -17,3 +17,4 @@ example/android/app/.classpath
...
@@ -17,3 +17,4 @@ example/android/app/.classpath
example/android/app/.project
example/android/app/.project
example/android/.project
example/android/.project
flutter_boost
flutter_boost
.flutter-plugins-dependencies
.travis.yml
View file @
7ead767f
...
@@ -9,7 +9,7 @@ addons:
...
@@ -9,7 +9,7 @@ addons:
-
libstdc++6
-
libstdc++6
# - fonts-droid
# - fonts-droid
before_script
:
before_script
:
-
git clone https://github.com/flutter/flutter.git -b
v1.12.13-hotfixes
--depth
1
-
git clone https://github.com/flutter/flutter.git -b
flutter-1.17-candidate.3
--depth
1
-
./flutter/bin/flutter doctor
-
./flutter/bin/flutter doctor
script
:
script
:
-
./flutter/bin/flutter test --coverage --coverage-path=lcov.info
-
./flutter/bin/flutter test --coverage --coverage-path=lcov.info
...
...
Frequently Asked Question.md
View file @
7ead767f
...
@@ -30,7 +30,7 @@ bool isTopContainer = FlutterBoost.BoostContainer.of(context).onstage
...
@@ -30,7 +30,7 @@ bool isTopContainer = FlutterBoost.BoostContainer.of(context).onstage
回答:无障碍模式下目前Flutter Engine有bug,已经提交issue和PR给flutter啦。请参考这个issue:https://github.com/alibaba/flutter_boost/issues/488及其分析。提交给flutter的PR见这里:https://github.com/flutter/engine/pull/14155
回答:无障碍模式下目前Flutter Engine有bug,已经提交issue和PR给flutter啦。请参考这个issue:https://github.com/alibaba/flutter_boost/issues/488及其分析。提交给flutter的PR见这里:https://github.com/flutter/engine/pull/14155
### 5. 在ios模拟器下运行最新的flutter boost会闪退
### 5. 在ios模拟器下运行最新的flutter boost会闪退
回答:如上面第4条所说的,最新的flutter engine在voice over下有bug,会导致crash。因为模拟器下flutter默认会将voice over模式打开,所以其实就是辅助模式,这
回
触发上面的bug:“在ios中voice over打开,demo在点击交互会crash”。
回答:如上面第4条所说的,最新的flutter engine在voice over下有bug,会导致crash。因为模拟器下flutter默认会将voice over模式打开,所以其实就是辅助模式,这
会
触发上面的bug:“在ios中voice over打开,demo在点击交互会crash”。
可参考Engine的代码注释:
可参考Engine的代码注释:
```
c++
```
c++
#if TARGET_OS_SIMULATOR
#if TARGET_OS_SIMULATOR
...
...
README.md
View file @
7ead767f
...
@@ -56,7 +56,11 @@ flutter_boost:
...
@@ -56,7 +56,11 @@ flutter_boost:
# Boost Integration
# Boost Integration
Please see the boost example for details.
Please see
1.
Boost detail example
2.
integrated document
<a
href=
"INTEGRATION.md"
>
Integration
</a>
# FAQ
# FAQ
please read this document:
please read this document:
...
...
README_CN.md
View file @
7ead767f
...
@@ -55,7 +55,10 @@ flutter_boost:
...
@@ -55,7 +55,10 @@ flutter_boost:
## boost集成
## boost集成
集成请看boost的Examples
集成请看:
1.
boost的Examples
2.
集成文档
<a
href=
"INTEGRATION.md"
>
Integration
</a>
...
...
android/src/main/java/com/idlefish/flutterboost/FlutterBoost.java
View file @
7ead767f
...
@@ -64,6 +64,18 @@ public class FlutterBoost {
...
@@ -64,6 +64,18 @@ public class FlutterBoost {
//fix crash:'FlutterBoostPlugin not register yet'
//fix crash:'FlutterBoostPlugin not register yet'
//case: initFlutter after Activity.OnCreate method,and then called start/stop crash
//case: initFlutter after Activity.OnCreate method,and then called start/stop crash
// In SplashActivity ,showDialog(in OnCreate method) to check permission, if authorized, then init sdk and jump homePage)
// In SplashActivity ,showDialog(in OnCreate method) to check permission, if authorized, then init sdk and jump homePage)
// fix bug : The LauncherActivity will be launch by clicking app icon when app enter background in HuaWei Rom, cause missing forgoround event
if
(
mEnterActivityCreate
&&
mCurrentActiveActivity
==
null
)
{
Intent
intent
=
activity
.
getIntent
();
if
(!
activity
.
isTaskRoot
()
&&
intent
!=
null
&&
intent
.
hasCategory
(
Intent
.
CATEGORY_LAUNCHER
)
&&
intent
.
getAction
()
!=
null
&&
intent
.
getAction
().
equals
(
Intent
.
ACTION_MAIN
))
{
return
;
}
}
mEnterActivityCreate
=
true
;
mEnterActivityCreate
=
true
;
mCurrentActiveActivity
=
activity
;
mCurrentActiveActivity
=
activity
;
if
(
mPlatform
.
whenEngineStart
()
==
ConfigBuilder
.
ANY_ACTIVITY_CREATED
)
{
if
(
mPlatform
.
whenEngineStart
()
==
ConfigBuilder
.
ANY_ACTIVITY_CREATED
)
{
...
...
android/src/main/java/com/idlefish/flutterboost/FlutterViewContainerManager.java
View file @
7ead767f
...
@@ -74,6 +74,8 @@ public class FlutterViewContainerManager implements IContainerManager {
...
@@ -74,6 +74,8 @@ public class FlutterViewContainerManager implements IContainerManager {
}
}
void
popRecord
(
IContainerRecord
record
)
{
void
popRecord
(
IContainerRecord
record
)
{
if
(
mRecordStack
.
empty
())
return
;
if
(
mRecordStack
.
peek
()
==
record
)
{
if
(
mRecordStack
.
peek
()
==
record
)
{
mRecordStack
.
pop
();
mRecordStack
.
pop
();
}
}
...
...
android/src/main/java/com/idlefish/flutterboost/XFlutterTextureView.java
0 → 100644
View file @
7ead767f
package
com.idlefish.flutterboost
;
import
android.content.Context
;
import
android.graphics.SurfaceTexture
;
import
android.util.AttributeSet
;
import
android.view.Surface
;
import
android.view.TextureView
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
io.flutter.Log
;
import
io.flutter.embedding.engine.renderer.FlutterRenderer
;
import
io.flutter.embedding.engine.renderer.RenderSurface
;
public
class
XFlutterTextureView
extends
TextureView
implements
RenderSurface
{
private
static
final
String
TAG
=
"FlutterTextureView"
;
private
boolean
isSurfaceAvailableForRendering
=
false
;
private
boolean
isAttachedToFlutterRenderer
=
false
;
@Nullable
private
FlutterRenderer
flutterRenderer
;
private
Surface
renderSurface
;
// Connects the {@code SurfaceTexture} beneath this {@code TextureView} with Flutter's native code.
// Callbacks are received by this Object and then those messages are forwarded to our
// FlutterRenderer, and then on to the JNI bridge over to native Flutter code.
private
final
SurfaceTextureListener
surfaceTextureListener
=
new
SurfaceTextureListener
()
{
@Override
public
void
onSurfaceTextureAvailable
(
SurfaceTexture
surfaceTexture
,
int
width
,
int
height
)
{
Log
.
v
(
TAG
,
"SurfaceTextureListener.onSurfaceTextureAvailable()"
);
isSurfaceAvailableForRendering
=
true
;
// If we're already attached to a FlutterRenderer then we're now attached to both a renderer
// and the Android window, so we can begin rendering now.
if
(
isAttachedToFlutterRenderer
)
{
connectSurfaceToRenderer
();
}
}
@Override
public
void
onSurfaceTextureSizeChanged
(
@NonNull
SurfaceTexture
surface
,
int
width
,
int
height
)
{
Log
.
v
(
TAG
,
"SurfaceTextureListener.onSurfaceTextureSizeChanged()"
);
if
(
isAttachedToFlutterRenderer
)
{
changeSurfaceSize
(
width
,
height
);
}
}
@Override
public
void
onSurfaceTextureUpdated
(
@NonNull
SurfaceTexture
surface
)
{
// Invoked every time a new frame is available. We don't care.
}
@Override
public
boolean
onSurfaceTextureDestroyed
(
@NonNull
SurfaceTexture
surface
)
{
Log
.
v
(
TAG
,
"SurfaceTextureListener.onSurfaceTextureDestroyed()"
);
isSurfaceAvailableForRendering
=
false
;
// If we're attached to a FlutterRenderer then we need to notify it that our SurfaceTexture
// has been destroyed.
if
(
isAttachedToFlutterRenderer
)
{
disconnectSurfaceFromRenderer
();
}
// Return true to indicate that no further painting will take place
// within this SurfaceTexture.
return
true
;
}
};
/**
* Constructs a {@code FlutterTextureView} programmatically, without any XML attributes.
*/
public
XFlutterTextureView
(
@NonNull
Context
context
)
{
this
(
context
,
null
);
}
/**
* Constructs a {@code FlutterTextureView} in an XML-inflation-compliant manner.
*/
public
XFlutterTextureView
(
@NonNull
Context
context
,
@Nullable
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
init
();
}
private
void
init
()
{
// Listen for when our underlying SurfaceTexture becomes available, changes size, or
// gets destroyed, and take the appropriate actions.
setSurfaceTextureListener
(
surfaceTextureListener
);
}
@Nullable
@Override
public
FlutterRenderer
getAttachedRenderer
()
{
return
flutterRenderer
;
}
/**
* Invoked by the owner of this {@code FlutterTextureView} when it wants to begin rendering
* a Flutter UI to this {@code FlutterTextureView}.
*
* If an Android {@link SurfaceTexture} is available, this method will give that
* {@link SurfaceTexture} to the given {@link FlutterRenderer} to begin rendering
* Flutter's UI to this {@code FlutterTextureView}.
*
* If no Android {@link SurfaceTexture} is available yet, this {@code FlutterTextureView}
* will wait until a {@link SurfaceTexture} becomes available and then give that
* {@link SurfaceTexture} to the given {@link FlutterRenderer} to begin rendering
* Flutter's UI to this {@code FlutterTextureView}.
*/
public
void
attachToRenderer
(
@NonNull
FlutterRenderer
flutterRenderer
)
{
Log
.
v
(
TAG
,
"Attaching to FlutterRenderer."
);
if
(
this
.
flutterRenderer
!=
null
)
{
Log
.
v
(
TAG
,
"Already connected to a FlutterRenderer. Detaching from old one and attaching to new one."
);
this
.
flutterRenderer
.
stopRenderingToSurface
();
}
this
.
flutterRenderer
=
flutterRenderer
;
isAttachedToFlutterRenderer
=
true
;
// If we're already attached to an Android window then we're now attached to both a renderer
// and the Android window. We can begin rendering now.
if
(
isSurfaceAvailableForRendering
)
{
Log
.
v
(
TAG
,
"Surface is available for rendering. Connecting FlutterRenderer to Android surface."
);
connectSurfaceToRenderer
();
}
}
/**
* Invoked by the owner of this {@code FlutterTextureView} when it no longer wants to render
* a Flutter UI to this {@code FlutterTextureView}.
*
* This method will cease any on-going rendering from Flutter to this {@code FlutterTextureView}.
*/
public
void
detachFromRenderer
()
{
if
(
flutterRenderer
!=
null
)
{
// If we're attached to an Android window then we were rendering a Flutter UI. Now that
// this FlutterTextureView is detached from the FlutterRenderer, we need to stop rendering.
// TODO(mattcarroll): introduce a isRendererConnectedToSurface() to wrap "getWindowToken() != null"
if
(
getWindowToken
()
!=
null
)
{
Log
.
v
(
TAG
,
"Disconnecting FlutterRenderer from Android surface."
);
disconnectSurfaceFromRenderer
();
}
flutterRenderer
=
null
;
isAttachedToFlutterRenderer
=
false
;
}
else
{
Log
.
w
(
TAG
,
"detachFromRenderer() invoked when no FlutterRenderer was attached."
);
}
}
// FlutterRenderer and getSurfaceTexture() must both be non-null.
private
void
connectSurfaceToRenderer
()
{
if
(
flutterRenderer
==
null
||
getSurfaceTexture
()
==
null
)
{
throw
new
IllegalStateException
(
"connectSurfaceToRenderer() should only be called when flutterRenderer and getSurfaceTexture() are non-null."
);
}
// flutterRenderer.startRenderingToSurface(new Surface(getSurfaceTexture()));
renderSurface
=
new
Surface
(
getSurfaceTexture
());
flutterRenderer
.
startRenderingToSurface
(
renderSurface
);
}
// FlutterRenderer must be non-null.
private
void
changeSurfaceSize
(
int
width
,
int
height
)
{
if
(
flutterRenderer
==
null
)
{
throw
new
IllegalStateException
(
"changeSurfaceSize() should only be called when flutterRenderer is non-null."
);
}
Log
.
v
(
TAG
,
"Notifying FlutterRenderer that Android surface size has changed to "
+
width
+
" x "
+
height
);
flutterRenderer
.
surfaceChanged
(
width
,
height
);
}
// FlutterRenderer must be non-null.
private
void
disconnectSurfaceFromRenderer
()
{
if
(
flutterRenderer
==
null
)
{
throw
new
IllegalStateException
(
"disconnectSurfaceFromRenderer() should only be called when flutterRenderer is non-null."
);
}
flutterRenderer
.
stopRenderingToSurface
();
if
(
renderSurface
!=
null
){
renderSurface
.
release
();
renderSurface
=
null
;
}
}
}
\ No newline at end of file
android/src/main/java/com/idlefish/flutterboost/XFlutterView.java
View file @
7ead767f
...
@@ -38,32 +38,12 @@ import io.flutter.embedding.engine.FlutterEngine;
...
@@ -38,32 +38,12 @@ import io.flutter.embedding.engine.FlutterEngine;
import
io.flutter.embedding.engine.renderer.FlutterRenderer
;
import
io.flutter.embedding.engine.renderer.FlutterRenderer
;
import
io.flutter.embedding.engine.renderer.FlutterUiDisplayListener
;
import
io.flutter.embedding.engine.renderer.FlutterUiDisplayListener
;
import
io.flutter.embedding.engine.renderer.RenderSurface
;
import
io.flutter.embedding.engine.renderer.RenderSurface
;
import
io.flutter.embedding.engine.systemchannels.
TextInput
Channel
;
import
io.flutter.embedding.engine.systemchannels.
Settings
Channel
;
import
io.flutter.plugin.editing.TextInputPlugin
;
import
io.flutter.plugin.editing.TextInputPlugin
;
import
io.flutter.plugin.platform.PlatformViewsController
;
import
io.flutter.plugin.platform.PlatformViewsController
;
import
io.flutter.view.AccessibilityBridge
;
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
{
public
class
XFlutterView
extends
FrameLayout
{
private
static
final
String
TAG
=
"FlutterView"
;
private
static
final
String
TAG
=
"FlutterView"
;
...
@@ -150,26 +130,12 @@ public class XFlutterView extends FrameLayout {
...
@@ -150,26 +130,12 @@ public class XFlutterView extends FrameLayout {
this
(
context
,
null
,
null
,
null
);
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
)
{
public
XFlutterView
(
@NonNull
Context
context
,
@NonNull
FlutterView
.
RenderMode
renderMode
)
{
this
(
context
,
null
,
renderMode
,
null
);
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
)
{
public
XFlutterView
(
@NonNull
Context
context
,
@NonNull
FlutterView
.
TransparencyMode
transparencyMode
)
{
this
(
context
,
null
,
FlutterView
.
RenderMode
.
surface
,
transparencyMode
);
this
(
context
,
null
,
FlutterView
.
RenderMode
.
surface
,
transparencyMode
);
}
}
...
@@ -217,7 +183,7 @@ public class XFlutterView extends FrameLayout {
...
@@ -217,7 +183,7 @@ public class XFlutterView extends FrameLayout {
break
;
break
;
case
texture:
case
texture:
Log
.
v
(
TAG
,
"Internally using a FlutterTextureView."
);
Log
.
v
(
TAG
,
"Internally using a FlutterTextureView."
);
FlutterTextureView
flutterTextureView
=
new
FlutterTextureView
(
getContext
());
XFlutterTextureView
flutterTextureView
=
new
X
FlutterTextureView
(
getContext
());
renderSurface
=
flutterTextureView
;
renderSurface
=
flutterTextureView
;
addView
(
flutterTextureView
);
addView
(
flutterTextureView
);
break
;
break
;
...
@@ -434,7 +400,7 @@ public class XFlutterView extends FrameLayout {
...
@@ -434,7 +400,7 @@ public class XFlutterView extends FrameLayout {
*/
*/
@Override
@Override
public
boolean
checkInputConnectionProxy
(
View
view
)
{
public
boolean
checkInputConnectionProxy
(
View
view
)
{
return
flutterEngine
!=
null
return
flutterEngine
!=
null
&&
view
!=
null
?
flutterEngine
.
getPlatformViewsController
().
checkInputConnectionProxy
(
view
)
?
flutterEngine
.
getPlatformViewsController
().
checkInputConnectionProxy
(
view
)
:
super
.
checkInputConnectionProxy
(
view
);
:
super
.
checkInputConnectionProxy
(
view
);
}
}
...
@@ -609,16 +575,9 @@ public class XFlutterView extends FrameLayout {
...
@@ -609,16 +575,9 @@ public class XFlutterView extends FrameLayout {
this
.
flutterEngine
.
getPlatformViewsController
().
attachToView
(
this
);
this
.
flutterEngine
.
getPlatformViewsController
().
attachToView
(
this
);
textInputPlugin
=
XTextInputPlugin
.
getTextInputPlugin
(
this
.
flutterEngine
.
getDartExecutor
(),
if
(
textInputPlugin
==
null
){
this
.
flutterEngine
.
getPlatformViewsController
());
textInputPlugin
=
new
XTextInputPlugin
(
textInputPlugin
.
updateView
(
this
);
this
,
flutterEngine
.
getTextInputChannel
(),
this
.
flutterEngine
.
getPlatformViewsController
()
);
}
textInputPlugin
.
setTextInputMethodHandler
();
textInputPlugin
.
getInputMethodManager
().
restartInput
(
this
);
textInputPlugin
.
getInputMethodManager
().
restartInput
(
this
);
...
@@ -717,7 +676,7 @@ public class XFlutterView extends FrameLayout {
...
@@ -717,7 +676,7 @@ public class XFlutterView extends FrameLayout {
}
}
public
void
release
(){
public
void
release
(){
if
(
textInputPlugin
!=
null
){
if
(
textInputPlugin
!=
null
){
textInputPlugin
.
release
();
textInputPlugin
.
release
(
this
);
}
}
}
}
...
@@ -788,9 +747,17 @@ public class XFlutterView extends FrameLayout {
...
@@ -788,9 +747,17 @@ public class XFlutterView extends FrameLayout {
*/
*/
private
void
sendUserSettingsToFlutter
()
{
private
void
sendUserSettingsToFlutter
()
{
if
(
flutterEngine
!=
null
&&
flutterEngine
.
getSettingsChannel
()!=
null
){
if
(
flutterEngine
!=
null
&&
flutterEngine
.
getSettingsChannel
()!=
null
){
flutterEngine
.
getSettingsChannel
().
startMessage
()
// Lookup the current brightness of the Android OS.
boolean
isNightModeOn
=
(
getResources
().
getConfiguration
().
uiMode
&
Configuration
.
UI_MODE_NIGHT_MASK
)
==
Configuration
.
UI_MODE_NIGHT_YES
;
SettingsChannel
.
PlatformBrightness
brightness
=
isNightModeOn
?
SettingsChannel
.
PlatformBrightness
.
dark
:
SettingsChannel
.
PlatformBrightness
.
light
;
flutterEngine
.
getSettingsChannel
().
startMessage
()
.
setTextScaleFactor
(
getResources
().
getConfiguration
().
fontScale
)
.
setTextScaleFactor
(
getResources
().
getConfiguration
().
fontScale
)
.
setUse24HourFormat
(
DateFormat
.
is24HourFormat
(
getContext
()))
.
setUse24HourFormat
(
DateFormat
.
is24HourFormat
(
getContext
()))
.
setPlatformBrightness
(
brightness
)
.
send
();
.
send
();
}
}
}
}
...
...
android/src/main/java/com/idlefish/flutterboost/XInputConnectionAdaptor.java
View file @
7ead767f
...
@@ -31,6 +31,7 @@ import io.flutter.plugin.common.ErrorLogResult;
...
@@ -31,6 +31,7 @@ import io.flutter.plugin.common.ErrorLogResult;
import
io.flutter.plugin.common.MethodChannel
;
import
io.flutter.plugin.common.MethodChannel
;
class
XInputConnectionAdaptor
extends
BaseInputConnection
{
class
XInputConnectionAdaptor
extends
BaseInputConnection
{
private
final
View
mFlutterView
;
private
final
View
mFlutterView
;
private
final
int
mClient
;
private
final
int
mClient
;
private
final
TextInputChannel
textInputChannel
;
private
final
TextInputChannel
textInputChannel
;
...
@@ -221,7 +222,6 @@ class XInputConnectionAdaptor extends BaseInputConnection {
...
@@ -221,7 +222,6 @@ class XInputConnectionAdaptor extends BaseInputConnection {
mEditable
.
delete
(
selStart
,
selEnd
);
mEditable
.
delete
(
selStart
,
selEnd
);
mEditable
.
insert
(
selStart
,
String
.
valueOf
((
char
)
character
));
mEditable
.
insert
(
selStart
,
String
.
valueOf
((
char
)
character
));
setSelection
(
selStart
+
1
,
selStart
+
1
);
setSelection
(
selStart
+
1
,
selStart
+
1
);
updateEditingState
();
}
}
return
true
;
return
true
;
}
}
...
...
android/src/main/java/com/idlefish/flutterboost/XPlatformPlugin.java
View file @
7ead767f
...
@@ -28,8 +28,8 @@ public class XPlatformPlugin {
...
@@ -28,8 +28,8 @@ public class XPlatformPlugin {
public
static
final
int
DEFAULT_SYSTEM_UI
=
View
.
SYSTEM_UI_FLAG_LAYOUT_STABLE
public
static
final
int
DEFAULT_SYSTEM_UI
=
View
.
SYSTEM_UI_FLAG_LAYOUT_STABLE
|
View
.
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
;
|
View
.
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
;
private
Activity
activity
;
private
Activity
activity
;
private
PlatformChannel
platformChannel
;
private
PlatformChannel
platformChannel
;
private
PlatformChannel
.
SystemChromeStyle
currentTheme
;
private
PlatformChannel
.
SystemChromeStyle
currentTheme
;
private
int
mEnabledOverlays
;
private
int
mEnabledOverlays
;
...
@@ -95,26 +95,25 @@ public class XPlatformPlugin {
...
@@ -95,26 +95,25 @@ public class XPlatformPlugin {
}
}
};
};
public
XPlatformPlugin
(
PlatformChannel
platformChannel
)
{
public
XPlatformPlugin
(
PlatformChannel
platformChannel
)
{
this
.
platformChannel
=
platformChannel
;
this
.
platformChannel
=
platformChannel
;
this
.
platformChannel
.
setPlatformMessageHandler
(
mPlatformMessageHandler
);
mEnabledOverlays
=
DEFAULT_SYSTEM_UI
;
mEnabledOverlays
=
DEFAULT_SYSTEM_UI
;
}
}
public
void
attachToActivity
(
Activity
activity
){
public
void
attachToActivity
(
Activity
activity
){
this
.
activity
=
activity
;
this
.
activity
=
activity
;
this
.
platformChannel
.
setPlatformMessageHandler
(
mPlatformMessageHandler
);
}
}
/**
/**
* Releases all resources held by this {@code PlatformPlugin}.
* Releases all resources held by this {@code PlatformPlugin}.
* <p>
* <p>
* Do not invoke any methods on a {@code PlatformPlugin} after invoking this method.
* Do not invoke any methods on a {@code PlatformPlugin} after invoking this method.
*/
*/
public
void
detachActivity
()
{
public
void
detachActivity
(
Activity
activity
)
{
this
.
activity
=
null
;
if
(
activity
==
this
.
activity
)
{
this
.
mPlatformMessageHandler
=
null
;
this
.
activity
=
null
;
}
}
}
private
void
playSystemSound
(
PlatformChannel
.
SoundType
soundType
)
{
private
void
playSystemSound
(
PlatformChannel
.
SoundType
soundType
)
{
...
...
android/src/main/java/com/idlefish/flutterboost/XTextInputPlugin.java
View file @
7ead767f
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package
com.idlefish.flutterboost
;
package
com.idlefish.flutterboost
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.content.Context
;
import
androidx.annotation.NonNull
;
import
android.os.Build
;
import
androidx.annotation.Nullable
;
import
android.provider.Settings
;
import
android.text.Editable
;
import
android.text.Editable
;
import
android.text.InputType
;
import
android.text.InputType
;
import
android.text.Selection
;
import
android.text.Selection
;
...
@@ -11,6 +17,11 @@ import android.view.inputmethod.BaseInputConnection;
...
@@ -11,6 +17,11 @@ import android.view.inputmethod.BaseInputConnection;
import
android.view.inputmethod.EditorInfo
;
import
android.view.inputmethod.EditorInfo
;
import
android.view.inputmethod.InputConnection
;
import
android.view.inputmethod.InputConnection
;
import
android.view.inputmethod.InputMethodManager
;
import
android.view.inputmethod.InputMethodManager
;
import
android.view.inputmethod.InputMethodSubtype
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.VisibleForTesting
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.embedding.engine.systemchannels.TextInputChannel
;
import
io.flutter.embedding.engine.systemchannels.TextInputChannel
;
...
@@ -21,11 +32,11 @@ import io.flutter.plugin.platform.PlatformViewsController;
...
@@ -21,11 +32,11 @@ import io.flutter.plugin.platform.PlatformViewsController;
*/
*/
public
class
XTextInputPlugin
{
public
class
XTextInputPlugin
{
@NonNull
@NonNull
private
View
mView
;
private
View
mView
;
@NonNull
@NonNull
private
final
InputMethodManager
mImm
;
private
InputMethodManager
mImm
;
@NonNull
@NonNull
private
final
TextInputChannel
textInputChannel
;
private
TextInputChannel
textInputChannel
;
@NonNull
@NonNull
private
InputTarget
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
NO_TARGET
,
0
);
private
InputTarget
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
NO_TARGET
,
0
);
@Nullable
@Nullable
...
@@ -37,26 +48,43 @@ public class XTextInputPlugin {
...
@@ -37,26 +48,43 @@ public class XTextInputPlugin {
private
InputConnection
lastInputConnection
;
private
InputConnection
lastInputConnection
;
@NonNull
@NonNull
private
PlatformViewsController
platformViewsController
;
private
PlatformViewsController
platformViewsController
;
private
boolean
restartAlwaysRequired
;
// When true following calls to createInputConnection will return the cached lastInputConnection if the input
// 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.
// target is a platform view. See the comments on lockPlatformViewInputConnection for more details.
private
boolean
isInputConnectionLocked
;
private
boolean
isInputConnectionLocked
;
private
static
XTextInputPlugin
xTextInputPlugin
;
public
static
XTextInputPlugin
getTextInputPlugin
(
DartExecutor
dartExecutor
,
@NonNull
PlatformViewsController
platformViewsController
){
if
(
xTextInputPlugin
!=
null
)
return
xTextInputPlugin
;
xTextInputPlugin
=
new
XTextInputPlugin
(
dartExecutor
,
platformViewsController
);
return
xTextInputPlugin
;
}
public
XTextInputPlugin
(
@NonNull
DartExecutor
dartExecutor
,
@NonNull
PlatformViewsController
platformViewsController
)
{
public
XTextInputPlugin
(
View
view
,
@NonNull
TextInputChannel
textInputChannel
,
@NonNull
PlatformViewsController
platformViewsController
)
{
mView
=
view
;
textInputChannel
=
new
TextInputChannel
(
dartExecutor
)
;
mImm
=
(
InputMethodManager
)
view
.
getContext
().
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
t
his
.
textInputChannel
=
textInputChannel
;
t
extInputChannel
.
requestExistingInputState
()
;
this
.
platformViewsController
=
platformViewsController
;
this
.
platformViewsController
=
platformViewsController
;
// this.platformViewsController.attachTextInputPlugin(this);
// this.platformViewsController.attachTextInputPlugin(this);
}
}
public
void
release
()
{
mView
=
null
;
public
void
release
(
View
v
){
if
(
mView
!=
null
&&
mView
.
hashCode
()==
v
.
hashCode
()){
mView
=
null
;
}
}
}
public
void
setTextInputMethodHandler
()
{
public
void
updateView
(
View
view
){
mView
=
view
;
mImm
=
(
InputMethodManager
)
view
.
getContext
().
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
textInputChannel
.
setTextInputMethodHandler
(
new
TextInputChannel
.
TextInputMethodHandler
()
{
textInputChannel
.
setTextInputMethodHandler
(
new
TextInputChannel
.
TextInputMethodHandler
()
{
@Override
@Override
...
@@ -89,8 +117,12 @@ public class XTextInputPlugin {
...
@@ -89,8 +117,12 @@ public class XTextInputPlugin {
clearTextInputClient
();
clearTextInputClient
();
}
}
});
});
restartAlwaysRequired
=
isRestartAlwaysRequired
();
}
}
@NonNull
@NonNull
public
InputMethodManager
getInputMethodManager
()
{
public
InputMethodManager
getInputMethodManager
()
{
return
mImm
;
return
mImm
;
...
@@ -114,7 +146,7 @@ public class XTextInputPlugin {
...
@@ -114,7 +146,7 @@ public class XTextInputPlugin {
/**
/**
* Unlocks the input connection.
* Unlocks the input connection.
*
<p>
*
* See also: @{link lockPlatformViewInputConnection}.
* See also: @{link lockPlatformViewInputConnection}.
*/
*/
public
void
unlockPlatformViewInputConnection
()
{
public
void
unlockPlatformViewInputConnection
()
{
...
@@ -123,7 +155,7 @@ public class XTextInputPlugin {
...
@@ -123,7 +155,7 @@ public class XTextInputPlugin {
/**
/**
* Detaches the text input plugin from the platform views controller.
* Detaches the text input plugin from the platform views controller.
*
<p>
*
* The TextInputPlugin instance should not be used after calling this.
* The TextInputPlugin instance should not be used after calling this.
*/
*/
public
void
destroy
()
{
public
void
destroy
()
{
...
@@ -134,6 +166,7 @@ public class XTextInputPlugin {
...
@@ -134,6 +166,7 @@ public class XTextInputPlugin {
TextInputChannel
.
InputType
type
,
TextInputChannel
.
InputType
type
,
boolean
obscureText
,
boolean
obscureText
,
boolean
autocorrect
,
boolean
autocorrect
,
boolean
enableSuggestions
,
TextInputChannel
.
TextCapitalization
textCapitalization
TextInputChannel
.
TextCapitalization
textCapitalization
)
{
)
{
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
DATETIME
)
{
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
DATETIME
)
{
...
@@ -168,6 +201,7 @@ public class XTextInputPlugin {
...
@@ -168,6 +201,7 @@ public class XTextInputPlugin {
textType
|=
InputType
.
TYPE_TEXT_VARIATION_PASSWORD
;
textType
|=
InputType
.
TYPE_TEXT_VARIATION_PASSWORD
;
}
else
{
}
else
{
if
(
autocorrect
)
textType
|=
InputType
.
TYPE_TEXT_FLAG_AUTO_CORRECT
;
if
(
autocorrect
)
textType
|=
InputType
.
TYPE_TEXT_FLAG_AUTO_CORRECT
;
if
(!
enableSuggestions
)
textType
|=
InputType
.
TYPE_TEXT_FLAG_NO_SUGGESTIONS
;
}
}
if
(
textCapitalization
==
TextInputChannel
.
TextCapitalization
.
CHARACTERS
)
{
if
(
textCapitalization
==
TextInputChannel
.
TextCapitalization
.
CHARACTERS
)
{
...
@@ -191,19 +225,15 @@ public class XTextInputPlugin {
...
@@ -191,19 +225,15 @@ public class XTextInputPlugin {
if
(
isInputConnectionLocked
)
{
if
(
isInputConnectionLocked
)
{
return
lastInputConnection
;
return
lastInputConnection
;
}
}
View
platformView
=
platformViewsController
.
getPlatformViewById
(
inputTarget
.
id
);
lastInputConnection
=
platformViewsController
.
getPlatformViewById
(
inputTarget
.
id
).
onCreateInputConnection
(
outAttrs
);
if
(
platformView
!=
null
)
{
return
lastInputConnection
;
lastInputConnection
=
platformView
.
onCreateInputConnection
(
outAttrs
);
return
lastInputConnection
;
}
else
{
return
null
;
}
}
}
outAttrs
.
inputType
=
inputTypeFromTextInputType
(
outAttrs
.
inputType
=
inputTypeFromTextInputType
(
configuration
.
inputType
,
configuration
.
inputType
,
configuration
.
obscureText
,
configuration
.
obscureText
,
configuration
.
autocorrect
,
configuration
.
autocorrect
,
configuration
.
enableSuggestions
,
configuration
.
textCapitalization
configuration
.
textCapitalization
);
);
outAttrs
.
imeOptions
=
EditorInfo
.
IME_FLAG_NO_FULLSCREEN
;
outAttrs
.
imeOptions
=
EditorInfo
.
IME_FLAG_NO_FULLSCREEN
;
...
@@ -243,7 +273,7 @@ public class XTextInputPlugin {
...
@@ -243,7 +273,7 @@ public class XTextInputPlugin {
/**
/**
* Clears a platform view text input client if it is the current input target.
* Clears a platform view text input client if it is the current input target.
*
<p>
*
* This is called when a platform view is disposed to make sure we're not hanging to a stale input
* This is called when a platform view is disposed to make sure we're not hanging to a stale input
* connection.
* connection.
*/
*/
...
@@ -269,7 +299,8 @@ public class XTextInputPlugin {
...
@@ -269,7 +299,8 @@ public class XTextInputPlugin {
mImm
.
hideSoftInputFromWindow
(
view
.
getApplicationWindowToken
(),
0
);
mImm
.
hideSoftInputFromWindow
(
view
.
getApplicationWindowToken
(),
0
);
}
}
private
void
setTextInputClient
(
int
client
,
TextInputChannel
.
Configuration
configuration
)
{
@VisibleForTesting
void
setTextInputClient
(
int
client
,
TextInputChannel
.
Configuration
configuration
)
{
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
FRAMEWORK_CLIENT
,
client
);
inputTarget
=
new
InputTarget
(
InputTarget
.
Type
.
FRAMEWORK_CLIENT
,
client
);
this
.
configuration
=
configuration
;
this
.
configuration
=
configuration
;
mEditable
=
Editable
.
Factory
.
getInstance
().
newEditable
(
""
);
mEditable
=
Editable
.
Factory
.
getInstance
().
newEditable
(
""
);
...
@@ -301,8 +332,8 @@ public class XTextInputPlugin {
...
@@ -301,8 +332,8 @@ public class XTextInputPlugin {
}
}
}
}
private
void
setTextInputEditingState
(
View
view
,
TextInputChannel
.
TextEditState
state
)
{
@VisibleForTesting
void
setTextInputEditingState
(
View
view
,
TextInputChannel
.
TextEditState
state
)
{
if
(!
mRestartInputPending
&&
state
.
text
.
equals
(
mEditable
.
toString
()))
{
if
(!
restartAlwaysRequired
&&
!
mRestartInputPending
&&
state
.
text
.
equals
(
mEditable
.
toString
()))
{
applyStateToSelection
(
state
);
applyStateToSelection
(
state
);
mImm
.
updateSelection
(
mView
,
Math
.
max
(
Selection
.
getSelectionStart
(
mEditable
),
0
),
mImm
.
updateSelection
(
mView
,
Math
.
max
(
Selection
.
getSelectionStart
(
mEditable
),
0
),
Math
.
max
(
Selection
.
getSelectionEnd
(
mEditable
),
0
),
Math
.
max
(
Selection
.
getSelectionEnd
(
mEditable
),
0
),
...
@@ -316,6 +347,30 @@ public class XTextInputPlugin {
...
@@ -316,6 +347,30 @@ public class XTextInputPlugin {
}
}
}
}
// Samsung's Korean keyboard has a bug where it always attempts to combine characters based on
// its internal state, ignoring if and when the cursor is moved programmatically. The same bug
// also causes non-korean keyboards to occasionally duplicate text when tapping in the middle
// of existing text to edit it.
//
// Fully restarting the IMM works around this because it flushes the keyboard's internal state
// and stops it from trying to incorrectly combine characters. However this also has some
// negative performance implications, so we don't want to apply this workaround in every case.
@SuppressLint
(
"NewApi"
)
// New API guard is inline, the linter can't see it.
@SuppressWarnings
(
"deprecation"
)
private
boolean
isRestartAlwaysRequired
()
{
InputMethodSubtype
subtype
=
mImm
.
getCurrentInputMethodSubtype
();
// Impacted devices all shipped with Android Lollipop or newer.
if
(
subtype
==
null
||
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
LOLLIPOP
||
!
Build
.
MANUFACTURER
.
equals
(
"samsung"
))
{
return
false
;
}
String
keyboardName
=
Settings
.
Secure
.
getString
(
mView
.
getContext
().
getContentResolver
(),
Settings
.
Secure
.
DEFAULT_INPUT_METHOD
);
// The Samsung keyboard is called "com.sec.android.inputmethod/.SamsungKeypad" but look
// for "Samsung" just in case Samsung changes the name of the keyboard.
if
(
keyboardName
==
null
)
return
false
;
return
keyboardName
.
contains
(
"Samsung"
);
}
private
void
clearTextInputClient
()
{
private
void
clearTextInputClient
()
{
if
(
inputTarget
.
type
==
InputTarget
.
Type
.
PLATFORM_VIEW
)
{
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
// Focus changes in the framework tree have no guarantees on the order focus nodes are notified. A node
...
@@ -358,4 +413,4 @@ public class XTextInputPlugin {
...
@@ -358,4 +413,4 @@ public class XTextInputPlugin {
// For platform views this is the platform view's ID.
// For platform views this is the platform view's ID.
int
id
;
int
id
;
}
}
}
}
\ No newline at end of file
android/src/main/java/com/idlefish/flutterboost/containers/BoostFlutterActivity.java
View file @
7ead767f
package
com.idlefish.flutterboost.containers
;
package
com.idlefish.flutterboost.containers
;
import
android.annotation.SuppressLint
;
import
android.app.Activity
;
import
android.app.Activity
;
import
androidx.lifecycle.Lifecycle
;
import
androidx.lifecycle.Lifecycle
;
import
androidx.lifecycle.LifecycleOwner
;
import
androidx.lifecycle.LifecycleOwner
;
...
@@ -56,6 +57,7 @@ public class BoostFlutterActivity extends Activity
...
@@ -56,6 +57,7 @@ public class BoostFlutterActivity extends Activity
// Default configuration.
// Default configuration.
protected
static
final
String
DEFAULT_BACKGROUND_MODE
=
BackgroundMode
.
opaque
.
name
();
protected
static
final
String
DEFAULT_BACKGROUND_MODE
=
BackgroundMode
.
opaque
.
name
();
private
static
XPlatformPlugin
sXPlatformPlugin
;
public
static
Intent
createDefaultIntent
(
@NonNull
Context
launchContext
)
{
public
static
Intent
createDefaultIntent
(
@NonNull
Context
launchContext
)
{
return
withNewEngine
().
build
(
launchContext
);
return
withNewEngine
().
build
(
launchContext
);
...
@@ -185,6 +187,7 @@ public class BoostFlutterActivity extends Activity
...
@@ -185,6 +187,7 @@ public class BoostFlutterActivity extends Activity
*/
*/
@Nullable
@Nullable
@SuppressWarnings
(
"deprecation"
)
@SuppressWarnings
(
"deprecation"
)
@SuppressLint
(
"WrongConstant"
)
private
Drawable
getSplashScreenFromManifest
()
{
private
Drawable
getSplashScreenFromManifest
()
{
try
{
try
{
ActivityInfo
activityInfo
=
getPackageManager
().
getActivityInfo
(
ActivityInfo
activityInfo
=
getPackageManager
().
getActivityInfo
(
...
@@ -440,8 +443,8 @@ public class BoostFlutterActivity extends Activity
...
@@ -440,8 +443,8 @@ public class BoostFlutterActivity extends Activity
@Nullable
@Nullable
@Override
@Override
public
XPlatformPlugin
providePlatformPlugin
(
@NonNull
FlutterEngine
flutterEngine
)
{
public
XPlatformPlugin
providePlatformPlugin
(
@NonNull
FlutterEngine
flutterEngine
)
{
return
new
XPlatformPlugin
(
flutterEngine
.
getPlatformChannel
());
return
BoostViewUtils
.
getPlatformPlugin
(
flutterEngine
.
getPlatformChannel
());
}
}
/**
/**
...
...
android/src/main/java/com/idlefish/flutterboost/containers/BoostViewUtils.java
0 → 100644
View file @
7ead767f
package
com.idlefish.flutterboost.containers
;
import
com.idlefish.flutterboost.XPlatformPlugin
;
import
io.flutter.embedding.engine.systemchannels.PlatformChannel
;
class
BoostViewUtils
{
private
static
volatile
XPlatformPlugin
mInstance
;
private
BoostViewUtils
()
{
}
public
static
XPlatformPlugin
getPlatformPlugin
(
PlatformChannel
channel
)
{
if
(
mInstance
==
null
)
{
synchronized
(
BoostViewUtils
.
class
)
{
if
(
mInstance
==
null
)
{
mInstance
=
new
XPlatformPlugin
(
channel
);
}
}
}
return
mInstance
;
}
}
android/src/main/java/com/idlefish/flutterboost/containers/FlutterActivityAndFragmentDelegate.java
View file @
7ead767f
...
@@ -230,7 +230,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
...
@@ -230,7 +230,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
// Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment,
// Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment,
// and this Fragment's Activity.
// and this Fragment's Activity.
if
(
platformPlugin
!=
null
)
{
if
(
platformPlugin
!=
null
)
{
platformPlugin
.
detachActivity
();
platformPlugin
.
detachActivity
(
getContextActivity
()
);
platformPlugin
=
null
;
platformPlugin
=
null
;
}
}
...
...
android/src/main/java/com/idlefish/flutterboost/containers/FlutterFragment.java
View file @
7ead767f
...
@@ -14,13 +14,11 @@ import androidx.fragment.app.Fragment;
...
@@ -14,13 +14,11 @@ import androidx.fragment.app.Fragment;
import
androidx.fragment.app.FragmentActivity
;
import
androidx.fragment.app.FragmentActivity
;
import
com.idlefish.flutterboost.FlutterBoost
;
import
com.idlefish.flutterboost.FlutterBoost
;
import
com.idlefish.flutterboost.Utils
;
import
com.idlefish.flutterboost.XFlutterView
;
import
com.idlefish.flutterboost.XFlutterView
;
import
com.idlefish.flutterboost.XPlatformPlugin
;
import
com.idlefish.flutterboost.XPlatformPlugin
;
import
io.flutter.embedding.android.*
;
import
io.flutter.embedding.android.*
;
import
io.flutter.embedding.engine.FlutterEngine
;
import
io.flutter.embedding.engine.FlutterEngine
;
import
io.flutter.embedding.engine.FlutterShellArgs
;
import
io.flutter.embedding.engine.FlutterShellArgs
;
import
io.flutter.plugin.platform.PlatformPlugin
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -469,8 +467,7 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
...
@@ -469,8 +467,7 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
@Nullable
@Nullable
@Override
@Override
public
XPlatformPlugin
providePlatformPlugin
(
@NonNull
FlutterEngine
flutterEngine
)
{
public
XPlatformPlugin
providePlatformPlugin
(
@NonNull
FlutterEngine
flutterEngine
)
{
return
new
XPlatformPlugin
(
flutterEngine
.
getPlatformChannel
());
return
BoostViewUtils
.
getPlatformPlugin
(
flutterEngine
.
getPlatformChannel
());
}
}
/**
/**
...
...
ios/Classes/container/FLBFlutterViewContainer.m
View file @
7ead767f
...
@@ -69,6 +69,7 @@
...
@@ -69,6 +69,7 @@
@property
(
nonatomic
,
assign
)
long
long
identifier
;
@property
(
nonatomic
,
assign
)
long
long
identifier
;
@property
(
nonatomic
,
copy
)
NSString
*
flbNibName
;
@property
(
nonatomic
,
copy
)
NSString
*
flbNibName
;
@property
(
nonatomic
,
strong
)
NSBundle
*
flbNibBundle
;
@property
(
nonatomic
,
strong
)
NSBundle
*
flbNibBundle
;
@property
(
nonatomic
,
assign
)
BOOL
deallocNotified
;
@end
@end
#pragma clang diagnostic push
#pragma clang diagnostic push
...
@@ -163,6 +164,7 @@ static NSUInteger kInstanceCounter = 0;
...
@@ -163,6 +164,7 @@ static NSUInteger kInstanceCounter = 0;
pageName:
_name
pageName:
_name
params:
_params
params:
_params
uniqueId:
[
self
uniqueIDString
]];
uniqueId:
[
self
uniqueIDString
]];
self
.
deallocNotified
=
NO
;
}
}
[
super
willMoveToParentViewController
:
parent
];
[
super
willMoveToParentViewController
:
parent
];
}
}
...
@@ -171,23 +173,29 @@ static NSUInteger kInstanceCounter = 0;
...
@@ -171,23 +173,29 @@ static NSUInteger kInstanceCounter = 0;
if
(
!
parent
)
{
if
(
!
parent
)
{
//当VC被移出parent时,就通知flutter层销毁page
//当VC被移出parent时,就通知flutter层销毁page
[
self
notifyWillDealloc
];
[
self
notifyWillDealloc
];
self
.
deallocNotified
=
YES
;
}
}
[
super
didMoveToParentViewController
:
parent
];
[
super
didMoveToParentViewController
:
parent
];
}
}
-
(
void
)
dismissViewControllerAnimated
:(
BOOL
)
flag
completion
:(
void
(
^
)(
void
))
completion
{
-
(
void
)
dismissViewControllerAnimated
:(
BOOL
)
flag
completion
:(
void
(
^
)(
void
))
completion
{
__weak
__typeof__
(
self
)
weakSelf
=
self
;
[
super
dismissViewControllerAnimated
:
flag
completion
:
^
(){
[
super
dismissViewControllerAnimated
:
flag
completion
:
^
(){
__strong
__typeof__
(
weakSelf
)
self
=
weakSelf
;
if
(
completion
)
{
if
(
completion
)
{
completion
();
completion
();
}
}
//当VC被dismiss时,就通知flutter层销毁page
//当VC被dismiss时,就通知flutter层销毁page
[
self
notifyWillDealloc
];
[
self
notifyWillDealloc
];
self
.
deallocNotified
=
YES
;
}];
}];
}
}
-
(
void
)
dealloc
-
(
void
)
dealloc
{
{
if
(
!
self
.
deallocNotified
)
{
[
self
notifyWillDealloc
];
}
[
NSNotificationCenter
.
defaultCenter
removeObserver
:
self
];
[
NSNotificationCenter
.
defaultCenter
removeObserver
:
self
];
}
}
...
...
lib/container/boost_container.dart
View file @
7ead767f
...
@@ -39,9 +39,9 @@ enum ContainerLifeCycle {
...
@@ -39,9 +39,9 @@ enum ContainerLifeCycle {
}
}
typedef
BoostContainerLifeCycleObserver
=
void
Function
(
typedef
BoostContainerLifeCycleObserver
=
void
Function
(
ContainerLifeCycle
state
,
ContainerLifeCycle
state
,
BoostContainerSettings
settings
,
BoostContainerSettings
settings
,
);
);
class
BoostContainer
extends
Navigator
{
class
BoostContainer
extends
Navigator
{
const
BoostContainer
({
const
BoostContainer
({
...
@@ -52,17 +52,17 @@ class BoostContainer extends Navigator {
...
@@ -52,17 +52,17 @@ class BoostContainer extends Navigator {
RouteFactory
onUnknownRoute
,
RouteFactory
onUnknownRoute
,
List
<
NavigatorObserver
>
observers
,
List
<
NavigatorObserver
>
observers
,
})
:
super
(
})
:
super
(
key:
key
,
key:
key
,
initialRoute:
initialRoute
,
initialRoute:
initialRoute
,
onGenerateRoute:
onGenerateRoute
,
onGenerateRoute:
onGenerateRoute
,
onUnknownRoute:
onUnknownRoute
,
onUnknownRoute:
onUnknownRoute
,
observers:
observers
,
observers:
observers
,
);
);
factory
BoostContainer
.
copy
(
factory
BoostContainer
.
copy
(
Navigator
navigator
,
[
Navigator
navigator
,
[
BoostContainerSettings
settings
=
const
BoostContainerSettings
(),
BoostContainerSettings
settings
=
const
BoostContainerSettings
(),
])
=>
])
=>
BoostContainer
(
BoostContainer
(
key:
GlobalKey
<
BoostContainerState
>(),
key:
GlobalKey
<
BoostContainerState
>(),
settings:
settings
,
settings:
settings
,
...
@@ -73,9 +73,9 @@ class BoostContainer extends Navigator {
...
@@ -73,9 +73,9 @@ class BoostContainer extends Navigator {
);
);
factory
BoostContainer
.
obtain
(
factory
BoostContainer
.
obtain
(
Navigator
navigator
,
Navigator
navigator
,
BoostContainerSettings
settings
,
BoostContainerSettings
settings
,
)
=>
)
=>
BoostContainer
(
BoostContainer
(
key:
GlobalKey
<
BoostContainerState
>(),
key:
GlobalKey
<
BoostContainerState
>(),
settings:
settings
,
settings:
settings
,
...
@@ -86,7 +86,11 @@ class BoostContainer extends Navigator {
...
@@ -86,7 +86,11 @@ class BoostContainer extends Navigator {
params:
settings
.
params
,
params:
settings
.
params
,
uniqueId:
settings
.
uniqueId
,
uniqueId:
settings
.
uniqueId
,
animated:
false
,
animated:
false
,
settings:
routeSettings
,
settings:
RouteSettings
(
name:
settings
.
name
,
isInitialRoute:
routeSettings
.
isInitialRoute
,
arguments:
routeSettings
.
arguments
,
),
builder:
settings
.
builder
,
builder:
settings
.
builder
,
);
);
}
else
{
}
else
{
...
@@ -110,18 +114,20 @@ class BoostContainer extends Navigator {
...
@@ -110,18 +114,20 @@ class BoostContainer extends Navigator {
static
BoostContainerState
tryOf
(
BuildContext
context
)
{
static
BoostContainerState
tryOf
(
BuildContext
context
)
{
final
BoostContainerState
container
=
final
BoostContainerState
container
=
context
.
findAncestorStateOfType
<
BoostContainerState
>();
context
.
findAncestorStateOfType
<
BoostContainerState
>();
return
container
;
return
container
;
}
}
static
BoostContainerState
of
(
BuildContext
context
)
{
static
BoostContainerState
of
(
BuildContext
context
)
{
final
BoostContainerState
container
=
final
BoostContainerState
container
=
context
.
findAncestorStateOfType
<
BoostContainerState
>();
context
.
findAncestorStateOfType
<
BoostContainerState
>();
assert
(
container
!=
null
,
'not in flutter boost'
);
assert
(
container
!=
null
,
'not in flutter boost'
);
return
container
;
return
container
;
}
}
String
desc
()
=>
'{uniqueId=
${settings.uniqueId}
,name=
${settings.name}
}'
;
String
desc
()
=>
'{uniqueId=
${settings.uniqueId}
,name=
${settings.name}
}'
;
RouteListFactory
get
initialRoutes
=>
super
.
onGenerateInitialRoutes
;
}
}
class
BoostContainerState
extends
NavigatorState
{
class
BoostContainerState
extends
NavigatorState
{
...
@@ -161,6 +167,15 @@ class BoostContainerState extends NavigatorState {
...
@@ -161,6 +167,15 @@ class BoostContainerState extends NavigatorState {
void
initState
()
{
void
initState
()
{
super
.
initState
();
super
.
initState
();
backPressedHandler
=
()
=>
maybePop
();
backPressedHandler
=
()
=>
maybePop
();
final
String
initRoute
=
widget
.
initialRoute
??
Navigator
.
defaultRouteName
;
if
(
initRoute
!=
null
&&
routerHistory
.
isEmpty
)
{
routerHistory
.
addAll
(
widget
.
initialRoutes
(
this
,
widget
.
initialRoute
??
Navigator
.
defaultRouteName
)
);
}
}
}
@override
@override
...
@@ -177,22 +192,28 @@ class BoostContainerState extends NavigatorState {
...
@@ -177,22 +192,28 @@ class BoostContainerState extends NavigatorState {
@override
@override
Future
<
bool
>
maybePop
<
T
extends
Object
>([
T
result
])
async
{
Future
<
bool
>
maybePop
<
T
extends
Object
>([
T
result
])
async
{
if
(
routerHistory
.
isEmpty
)
{
pop
(
result
);
return
true
;
}
final
Route
<
T
>
route
=
routerHistory
.
last
as
Route
<
T
>;
final
Route
<
T
>
route
=
routerHistory
.
last
as
Route
<
T
>;
final
RoutePopDisposition
disposition
=
await
route
.
willPop
();
final
RoutePopDisposition
disposition
=
await
route
.
willPop
();
if
(
mounted
)
{
if
(
mounted
)
{
switch
(
disposition
)
{
switch
(
disposition
)
{
case
RoutePopDisposition
.
pop
:
case
RoutePopDisposition
.
pop
:
pop
(
result
);
pop
(
result
);
return
true
;
return
true
;
break
;
break
;
case
RoutePopDisposition
.
doNotPop
:
case
RoutePopDisposition
.
doNotPop
:
return
false
;
return
false
;
break
;
break
;
case
RoutePopDisposition
.
bubble
:
case
RoutePopDisposition
.
bubble
:
pop
(
result
);
pop
(
result
);
return
true
;
return
true
;
break
;
break
;
}
}
}
}
return
false
;
return
false
;
}
}
...
@@ -238,10 +259,10 @@ class BoostContainerState extends NavigatorState {
...
@@ -238,10 +259,10 @@ class BoostContainerState extends NavigatorState {
VoidCallback
addLifeCycleObserver
(
BoostContainerLifeCycleObserver
observer
)
{
VoidCallback
addLifeCycleObserver
(
BoostContainerLifeCycleObserver
observer
)
{
return
FlutterBoost
.
singleton
.
addBoostContainerLifeCycleObserver
(
return
FlutterBoost
.
singleton
.
addBoostContainerLifeCycleObserver
(
(
(
ContainerLifeCycle
state
,
ContainerLifeCycle
state
,
BoostContainerSettings
settings
,
BoostContainerSettings
settings
,
)
{
)
{
if
(
settings
.
uniqueId
==
uniqueId
)
{
if
(
settings
.
uniqueId
==
uniqueId
)
{
observer
(
state
,
settings
);
observer
(
state
,
settings
);
}
}
...
...
lib/container/boost_page_route.dart
View file @
7ead767f
...
@@ -62,4 +62,9 @@ class BoostPageRoute<T> extends MaterialPageRoute<T> {
...
@@ -62,4 +62,9 @@ class BoostPageRoute<T> extends MaterialPageRoute<T> {
return
null
;
return
null
;
}
}
}
}
@override
Future
<
RoutePopDisposition
>
willPop
()
{
return
Future
<
RoutePopDisposition
>.
value
(
RoutePopDisposition
.
pop
);
}
}
}
lib/container/container_manager.dart
View file @
7ead767f
...
@@ -69,7 +69,6 @@ class ContainerManagerState extends State<BoostContainerManager> {
...
@@ -69,7 +69,6 @@ class ContainerManagerState extends State<BoostContainerManager> {
final
List
<
BoostContainer
>
_offstage
=
<
BoostContainer
>[];
final
List
<
BoostContainer
>
_offstage
=
<
BoostContainer
>[];
List
<
_ContainerOverlayEntry
>
_leastEntries
;
List
<
_ContainerOverlayEntry
>
_leastEntries
;
BoostContainer
_onstage
;
BoostContainer
_onstage
;
bool
_foreground
=
true
;
bool
_foreground
=
true
;
...
@@ -158,15 +157,20 @@ class ContainerManagerState extends State<BoostContainerManager> {
...
@@ -158,15 +157,20 @@ class ContainerManagerState extends State<BoostContainerManager> {
}
}
}
}
final
List
<
BoostContainer
>
containers
=
<
BoostContainer
>[];
final
List
<
Widget
>
containers
=
<
Widget
>[];
containers
.
addAll
(
_offstage
);
containers
.
addAll
(
_offstage
.
map
<
Widget
>(
(
BoostContainer
container
)
=>
HeroControllerScope
(
controller:
null
,
child:
container
)
));
assert
(
_onstage
!=
null
,
'Should have a least one BoostContainer'
);
assert
(
_onstage
!=
null
,
'Should have a least one BoostContainer'
);
containers
.
add
(
_onstage
);
containers
.
add
(
_onstage
);
_leastEntries
=
containers
_leastEntries
=
containers
.
map
<
_ContainerOverlayEntry
>(
.
map
<
_ContainerOverlayEntry
>(
(
BoostContainer
container
)
=>
_ContainerOverlayEntry
(
container
))
(
Widget
container
)
=>
_ContainerOverlayEntry
(
container
))
.
toList
(
growable:
false
);
.
toList
(
growable:
false
);
overlayState
.
insertAll
(
_leastEntries
);
overlayState
.
insertAll
(
_leastEntries
);
...
@@ -336,7 +340,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
...
@@ -336,7 +340,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
}
}
class
_ContainerOverlayEntry
extends
OverlayEntry
{
class
_ContainerOverlayEntry
extends
OverlayEntry
{
_ContainerOverlayEntry
(
BoostContainer
container
)
_ContainerOverlayEntry
(
Widget
container
)
:
super
(
:
super
(
builder:
(
BuildContext
ctx
)
=>
container
,
builder:
(
BuildContext
ctx
)
=>
container
,
opaque:
true
,
opaque:
true
,
...
...
lib/observers_holders.dart
View file @
7ead767f
...
@@ -38,7 +38,7 @@ class ObserversHolder {
...
@@ -38,7 +38,7 @@ class ObserversHolder {
void
removeObserver
<
T
>(
T
observer
)
=>
void
removeObserver
<
T
>(
T
observer
)
=>
_observers
[
T
.
toString
()]?.
remove
(
observer
);
_observers
[
T
.
toString
()]?.
remove
(
observer
);
void
cleanObservers
<
T
>(
T
observer
)
=>
_observers
[
T
.
toString
()]?.
clear
();
void
cleanObservers
<
T
>()
=>
_observers
[
T
.
toString
()]?.
clear
();
Set
<
T
>
observersOf
<
T
>()
=>
_observers
[
T
.
toString
()]
as
Set
<
T
>
??
<
T
>{};
Set
<
T
>
observersOf
<
T
>()
=>
_observers
[
T
.
toString
()]
as
Set
<
T
>
??
<
T
>{};
}
}
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