Commit 802756a1 authored by justin's avatar justin

Pick from support 把xtextinputplugin 改成单列,但会持有最后一个activity,解决输入框问题

parent 5fdf44dc
......@@ -43,27 +43,7 @@ import io.flutter.plugin.editing.TextInputPlugin;
import io.flutter.plugin.platform.PlatformViewsController;
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 = "FlutterView";
......@@ -150,26 +130,12 @@ public class XFlutterView extends FrameLayout {
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);
}
......@@ -609,16 +575,9 @@ public class XFlutterView extends FrameLayout {
this.flutterEngine.getPlatformViewsController().attachToView(this);
if(textInputPlugin==null){
textInputPlugin = new XTextInputPlugin(
this,
flutterEngine.getTextInputChannel(),
this.flutterEngine.getPlatformViewsController()
);
}
textInputPlugin.setTextInputMethodHandler();
textInputPlugin= XTextInputPlugin.getTextInputPlugin( this.flutterEngine.getDartExecutor(),
this.flutterEngine.getPlatformViewsController());
textInputPlugin.updateView(this);
textInputPlugin.getInputMethodManager().restartInput(this);
......@@ -717,7 +676,7 @@ public class XFlutterView extends FrameLayout {
}
public void release(){
if(textInputPlugin!=null){
textInputPlugin.release();
// textInputPlugin.release();
}
}
......
......@@ -31,6 +31,7 @@ import io.flutter.plugin.common.ErrorLogResult;
import io.flutter.plugin.common.MethodChannel;
class XInputConnectionAdaptor extends BaseInputConnection {
private final View mFlutterView;
private final int mClient;
private final TextInputChannel textInputChannel;
......@@ -221,7 +222,6 @@ class XInputConnectionAdaptor extends BaseInputConnection {
mEditable.delete(selStart, selEnd);
mEditable.insert(selStart, String.valueOf((char) character));
setSelection(selStart + 1, selStart + 1);
updateEditingState();
}
return true;
}
......
// 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;
import android.annotation.SuppressLint;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.os.Build;
import android.provider.Settings;
import android.text.Editable;
import android.text.InputType;
import android.text.Selection;
......@@ -11,6 +17,11 @@ import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
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.systemchannels.TextInputChannel;
......@@ -23,9 +34,9 @@ public class XTextInputPlugin {
@NonNull
private View mView;
@NonNull
private final InputMethodManager mImm;
private InputMethodManager mImm;
@NonNull
private final TextInputChannel textInputChannel;
private TextInputChannel textInputChannel;
@NonNull
private InputTarget inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
@Nullable
......@@ -37,26 +48,34 @@ public class XTextInputPlugin {
private InputConnection lastInputConnection;
@NonNull
private PlatformViewsController platformViewsController;
private boolean restartAlwaysRequired;
// 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;
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;
mImm = (InputMethodManager) view.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
this.textInputChannel = textInputChannel;
textInputChannel = new TextInputChannel(dartExecutor);
textInputChannel.requestExistingInputState();
this.platformViewsController = platformViewsController;
// this.platformViewsController.attachTextInputPlugin(this);
}
public void release() {
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() {
@Override
......@@ -89,8 +108,12 @@ public class XTextInputPlugin {
clearTextInputClient();
}
});
restartAlwaysRequired = isRestartAlwaysRequired();
}
@NonNull
public InputMethodManager getInputMethodManager() {
return mImm;
......@@ -114,7 +137,7 @@ public class XTextInputPlugin {
/**
* Unlocks the input connection.
* <p>
*
* See also: @{link lockPlatformViewInputConnection}.
*/
public void unlockPlatformViewInputConnection() {
......@@ -123,7 +146,7 @@ public class XTextInputPlugin {
/**
* Detaches the text input plugin from the platform views controller.
* <p>
*
* The TextInputPlugin instance should not be used after calling this.
*/
public void destroy() {
......@@ -134,6 +157,7 @@ public class XTextInputPlugin {
TextInputChannel.InputType type,
boolean obscureText,
boolean autocorrect,
boolean enableSuggestions,
TextInputChannel.TextCapitalization textCapitalization
) {
if (type.type == TextInputChannel.TextInputType.DATETIME) {
......@@ -168,6 +192,7 @@ public class XTextInputPlugin {
textType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
} else {
if (autocorrect) textType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
if (!enableSuggestions) textType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
}
if (textCapitalization == TextInputChannel.TextCapitalization.CHARACTERS) {
......@@ -191,19 +216,15 @@ public class XTextInputPlugin {
if (isInputConnectionLocked) {
return lastInputConnection;
}
View platformView = platformViewsController.getPlatformViewById(inputTarget.id);
if (platformView != null) {
lastInputConnection = platformView.onCreateInputConnection(outAttrs);
lastInputConnection = platformViewsController.getPlatformViewById(inputTarget.id).onCreateInputConnection(outAttrs);
return lastInputConnection;
} else {
return null;
}
}
outAttrs.inputType = inputTypeFromTextInputType(
configuration.inputType,
configuration.obscureText,
configuration.autocorrect,
configuration.enableSuggestions,
configuration.textCapitalization
);
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
......@@ -243,7 +264,7 @@ public class XTextInputPlugin {
/**
* 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
* connection.
*/
......@@ -269,7 +290,8 @@ public class XTextInputPlugin {
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);
this.configuration = configuration;
mEditable = Editable.Factory.getInstance().newEditable("");
......@@ -301,8 +323,8 @@ public class XTextInputPlugin {
}
}
private void setTextInputEditingState(View view, TextInputChannel.TextEditState state) {
if (!mRestartInputPending && state.text.equals(mEditable.toString())) {
@VisibleForTesting void setTextInputEditingState(View view, TextInputChannel.TextEditState state) {
if (!restartAlwaysRequired && !mRestartInputPending && state.text.equals(mEditable.toString())) {
applyStateToSelection(state);
mImm.updateSelection(mView, Math.max(Selection.getSelectionStart(mEditable), 0),
Math.max(Selection.getSelectionEnd(mEditable), 0),
......@@ -316,6 +338,28 @@ 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.
return keyboardName.contains("Samsung");
}
private void clearTextInputClient() {
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
......
......@@ -359,11 +359,23 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 12.0),
clearButtonMode: OverlayVisibilityMode.editing,
textCapitalization: TextCapitalization.words,
autocorrect: false,
decoration: BoxDecoration(
border: Border(bottom: BorderSide(width: 0.0, color: CupertinoColors.inactiveGray)),
),
placeholder: 'Name',
new TextField(
enabled: true,
autocorrect: true,
style: const TextStyle(
fontSize: 20.0,
color: const Color(0xFF222222),
fontWeight: FontWeight.w500),
), new TextField(
controller: new TextEditingController(),
focusNode:FocusNode(),
enabled: true,
autocorrect: false,
style: const TextStyle(
fontSize: 20.0,
color: const Color(0xFF222222),
fontWeight: FontWeight.w500),
),
InkWell(
child: Container(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment