浏览代码
Merge branch 'dev_1.17.5' of github.com:Unity-Technologies/com.unity.uiwidgets into zxw/refine_debug_mode
Merge branch 'dev_1.17.5' of github.com:Unity-Technologies/com.unity.uiwidgets into zxw/refine_debug_mode
# Conflicts: # com.unity.uiwidgets/Editor/UIWidgetsPanelEditor.cs # com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanel.cs/siyaoH-1.17-PlatformMessage
Xingwei Zhu
4 年前
当前提交
64720e9b
共有 41 个文件被更改,包括 1553 次插入 和 74 次删除
-
1Samples/UIWidgetsSamples_2019_4/Assets/Script/CountTest.cs
-
1Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/CustomPaintSample.cs
-
2Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/DragDropSample.cs
-
99Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/HttpRequestSample.cs
-
2Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/LongPressSample.cs
-
1Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/NavigationSample.cs
-
1Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/PageViewSample.cs
-
1Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/ScrollbarSample.cs
-
1Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/ToDoAppSample.cs
-
38com.unity.uiwidgets/Runtime/engine/UIWidgetsMessageManager.cs
-
23com.unity.uiwidgets/Runtime/engine2/AndroidPlatformUtil.cs
-
102com.unity.uiwidgets/Runtime/engine2/DisplayMetrics.cs
-
25com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanel.cs
-
2com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanelWrapper.cs
-
1com.unity.uiwidgets/Runtime/rendering/binding.cs
-
15com.unity.uiwidgets/Runtime/services/keyboard.cs
-
3com.unity.uiwidgets/Runtime/services/text_input.cs
-
4com.unity.uiwidgets/Runtime/ui2/hooks.cs
-
5com.unity.uiwidgets/Runtime/ui2/window.cs
-
1com.unity.uiwidgets/Runtime/widgets/binding.cs
-
3engine/Build.bee.cs
-
88Samples/UIWidgetsSamples_2019_4/Assets/WidgetsSample/ImageFormatSample.cs
-
15engine/src/shell/platform/unity/darwin/ios/device_screen.mm
-
14engine/src/shell/platform/unity/darwin/ios/uiwidgets_device.h
-
140engine/src/shell/platform/unity/darwin/ios/uiwidgets_device.mm
-
44com.unity.uiwidgets/Runtime/Plugins/Android/UIWidgetsMessageManager.java
-
32com.unity.uiwidgets/Runtime/Plugins/Android/UIWidgetsMessageManager.java.meta
-
209com.unity.uiwidgets/Runtime/Plugins/Android/UIWidgetsViewController.java
-
32com.unity.uiwidgets/Runtime/Plugins/Android/UIWidgetsViewController.java.meta
-
13com.unity.uiwidgets/Runtime/Plugins/Android/UIWidgetsViewMetrics.java
-
32com.unity.uiwidgets/Runtime/Plugins/Android/UIWidgetsViewMetrics.java.meta
-
21com.unity.uiwidgets/Runtime/Plugins/Android/Utils.java
-
32com.unity.uiwidgets/Runtime/Plugins/Android/Utils.java.meta
-
229com.unity.uiwidgets/Runtime/Plugins/Android/InputConnectionAdaptor.java
-
31com.unity.uiwidgets/Runtime/Plugins/Android/InputConnectionAdaptor.java.meta
-
31com.unity.uiwidgets/Runtime/Plugins/Android/TextInputPlugin.java.meta
-
48com.unity.uiwidgets/Runtime/Plugins/Android/TextInputView.java
-
31com.unity.uiwidgets/Runtime/Plugins/Android/TextInputView.java.meta
-
254com.unity.uiwidgets/Runtime/Plugins/Android/TextInputPlugin.java
|
|||
using System.Collections.Generic; |
|||
using uiwidgets; |
|||
using Unity.UIWidgets.engine2; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using Image = Unity.UIWidgets.widgets.Image; |
|||
using ui_ = Unity.UIWidgets.widgets.ui_; |
|||
|
|||
namespace UIWidgetsSample |
|||
{ |
|||
public class ImageFormatSample : UIWidgetsPanel |
|||
{ |
|||
protected override void main() |
|||
{ |
|||
ui_.runApp(new MyApp()); |
|||
} |
|||
|
|||
class MyApp : StatelessWidget |
|||
{ |
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new WidgetsApp( |
|||
home: new ImageFormatApp(), |
|||
color: Color.white, |
|||
pageRouteBuilder: (settings, builder) => |
|||
new PageRouteBuilder( |
|||
settings: settings, |
|||
pageBuilder: (buildContext, animation, secondaryAnimation) => builder(context) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
class ImageFormatApp : StatefulWidget |
|||
{ |
|||
public override State createState() |
|||
{ |
|||
return new ImageFormatAppState(); |
|||
} |
|||
} |
|||
|
|||
class ImageFormatAppState : State<ImageFormatApp> |
|||
{ |
|||
private int imageId; |
|||
|
|||
private static List<string> imagePath = new List<string> |
|||
{ |
|||
"shrine_images/0-0.jpg", |
|||
"shrine_images/2.0x/1-0.jpg", |
|||
"shrine_images/diamond.png", |
|||
"gallery/people/square/ali.png", |
|||
"gallery/10-0.jpg", |
|||
"gallery/glasses.jpg" |
|||
}; |
|||
|
|||
|
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new Container( |
|||
child: new Column( |
|||
children: new List<Widget> |
|||
{ |
|||
new Container( |
|||
width: 100, |
|||
height: 100, |
|||
decoration: new BoxDecoration( |
|||
borderRadius: BorderRadius.all(Radius.circular(8)) |
|||
), |
|||
child: Image.file(imagePath[imageId]) |
|||
), |
|||
new Text(imagePath[imageId]), |
|||
new GestureDetector( |
|||
onTap: () => { setState(() => { imageId = (imageId + 1) % imagePath.Count; }); }, |
|||
child: new Container( |
|||
color: Color.black, |
|||
padding: EdgeInsets.symmetric(20, 20), |
|||
child: new Text("Next" |
|||
) |
|||
)) |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|
|||
#import <UIKit/UIKit.h> |
|||
#import "uiwidgets_device.h" |
|||
#include "runtime/mono_api.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
UIWIDGETS_API(float) IOSDeviceScaleFactor() |
|||
{ |
|||
float scale = [[UIScreen mainScreen] scale] * 1.0; |
|||
if ([UIWidgetsDevice NeedScreenDownSample]) { |
|||
scale *= 0.8696; |
|||
} |
|||
return scale; |
|||
} |
|||
} |
|
|||
#ifndef UIWidgetsDevice_h |
|||
#define UIWidgetsDevice_h |
|||
|
|||
#import <UIKit/UIKit.h> |
|||
|
|||
@interface UIWidgetsDevice : NSObject |
|||
|
|||
+(NSString *) deviceName; |
|||
|
|||
+(BOOL) NeedScreenDownSample; |
|||
|
|||
@end |
|||
|
|||
#endif |
|
|||
#include "uiwidgets_device.h" |
|||
#import <sys/utsname.h> |
|||
#import <UIKit/UIKit.h> |
|||
|
|||
static NSString* _deviceName = nil; |
|||
|
|||
@implementation UIWidgetsDevice |
|||
|
|||
+ (NSString *) deviceName |
|||
{ |
|||
if (_deviceName != nil) { |
|||
return _deviceName; |
|||
} |
|||
|
|||
struct utsname systemInfo; |
|||
uname(&systemInfo); |
|||
NSString* code = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; |
|||
|
|||
NSDictionary* deviceNamesByCode = @{ |
|||
@"i386" : @"Simulator", |
|||
@"x86_64" : @"Simulator", |
|||
@"iPod1,1" : @"iPod Touch", // (Original) |
|||
@"iPod2,1" : @"iPod Touch", // (Second Generation) |
|||
@"iPod3,1" : @"iPod Touch", // (Third Generation) |
|||
@"iPod4,1" : @"iPod Touch", // (Fourth Generation) |
|||
@"iPod7,1" : @"iPod Touch", // (6th Generation) |
|||
@"iPhone1,1" : @"iPhone", // (Original) |
|||
@"iPhone1,2" : @"iPhone", // (3G) |
|||
@"iPhone2,1" : @"iPhone", // (3GS) |
|||
@"iPad1,1" : @"iPad", // (Original) |
|||
@"iPad2,1" : @"iPad 2", // |
|||
@"iPad3,1" : @"iPad", // (3rd Generation) |
|||
@"iPhone3,1" : @"iPhone 4", // (GSM) |
|||
@"iPhone3,3" : @"iPhone 4", // (CDMA/Verizon/Sprint) |
|||
@"iPhone4,1" : @"iPhone 4S", // |
|||
@"iPhone5,1" : @"iPhone 5", // (model A1428, AT&T/Canada) |
|||
@"iPhone5,2" : @"iPhone 5", // (model A1429, everything else) |
|||
@"iPad3,4" : @"iPad", // (4th Generation) |
|||
@"iPad2,5" : @"iPad Mini", // (Original) |
|||
@"iPhone5,3" : @"iPhone 5C", // (model A1456, A1532 | GSM) |
|||
@"iPhone5,4" : @"iPhone 5C", // (model A1507, A1516, A1526 (China), A1529 | Global) |
|||
@"iPhone6,1" : @"iPhone 5S", // (model A1433, A1533 | GSM) |
|||
@"iPhone6,2" : @"iPhone 5S", // (model A1457, A1518, A1528 (China), A1530 | Global) |
|||
@"iPhone7,1" : @"iPhone 6 Plus", // |
|||
@"iPhone7,2" : @"iPhone 6", // |
|||
@"iPhone8,1" : @"iPhone 6S", // |
|||
@"iPhone8,2" : @"iPhone 6S Plus", // |
|||
@"iPhone8,4" : @"iPhone SE", // |
|||
@"iPhone9,1" : @"iPhone 7", // |
|||
@"iPhone9,3" : @"iPhone 7", // |
|||
@"iPhone9,2" : @"iPhone 7 Plus", // |
|||
@"iPhone9,4" : @"iPhone 7 Plus", // |
|||
@"iPhone10,1": @"iPhone 8", // CDMA |
|||
@"iPhone10,4": @"iPhone 8", // GSM |
|||
@"iPhone10,2": @"iPhone 8 Plus", // CDMA |
|||
@"iPhone10,5": @"iPhone 8 Plus", // GSM |
|||
@"iPhone10,3": @"iPhone X", // CDMA |
|||
@"iPhone10,6": @"iPhone X", // GSM |
|||
@"iPhone11,2": @"iPhone XS", // |
|||
@"iPhone11,4": @"iPhone XS Max", // |
|||
@"iPhone11,6": @"iPhone XS Max", // China |
|||
@"iPhone11,8": @"iPhone XR", // |
|||
|
|||
@"iPad4,1" : @"iPad Air", // 5th Generation iPad (iPad Air) - Wifi |
|||
@"iPad4,2" : @"iPad Air", // 5th Generation iPad (iPad Air) - Cellular |
|||
@"iPad4,4" : @"iPad Mini", // (2nd Generation iPad Mini - Wifi) |
|||
@"iPad4,5" : @"iPad Mini", // (2nd Generation iPad Mini - Cellular) |
|||
@"iPad4,7" : @"iPad Mini", // (3rd Generation iPad Mini - Wifi (model A1599)) |
|||
@"iPad6,7" : @"iPad Pro (12.9\")", // iPad Pro 12.9 inches - (model A1584) |
|||
@"iPad6,8" : @"iPad Pro (12.9\")", // iPad Pro 12.9 inches - (model A1652) |
|||
@"iPad6,3" : @"iPad Pro (9.7\")", // iPad Pro 9.7 inches - (model A1673) |
|||
@"iPad6,4" : @"iPad Pro (9.7\")" |
|||
}; |
|||
_deviceName = [deviceNamesByCode objectForKey:code]; |
|||
|
|||
if (!_deviceName) { |
|||
if ([code rangeOfString:@"iPod"].location != NSNotFound) { |
|||
_deviceName = @"iPod Touch"; |
|||
} |
|||
else if([code rangeOfString:@"iPad"].location != NSNotFound) { |
|||
_deviceName = @"iPad"; |
|||
} |
|||
else if([code rangeOfString:@"iPhone"].location != NSNotFound){ |
|||
_deviceName = @"iPhone"; |
|||
} |
|||
else { |
|||
_deviceName = @"Unknown"; |
|||
} |
|||
} |
|||
|
|||
if ([_deviceName isEqualToString:@"Simulator"]) { |
|||
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { |
|||
switch ((int)[[UIScreen mainScreen] nativeBounds].size.height) { |
|||
//iPhone 5 or 5S or 5C |
|||
case 1136: |
|||
_deviceName = @"iPhone 5 Simulator"; |
|||
break; |
|||
//iPhone 6 or 6S or 7 or 8 |
|||
case 1334: |
|||
_deviceName = @"iPhone 6 Simulator"; |
|||
break; |
|||
//iPhone 6+ or 6S+ or 7+ or 8+ |
|||
case 1920: |
|||
_deviceName = @"iPhone 6 Plus Simulator"; |
|||
break; |
|||
//iPhone 6+ or 6S+ or 7+ or 8+ |
|||
case 2208: |
|||
_deviceName = @"iPhone 6 Plus Simulator"; |
|||
break; |
|||
//iPhone X or XS |
|||
case 2436: |
|||
_deviceName = @"iPhone X Simulator"; |
|||
break; |
|||
//iPhone XS Max |
|||
case 2688: |
|||
_deviceName = @"iPhone XS Max Simulator"; |
|||
break; |
|||
//iPhone XR |
|||
case 1792: |
|||
_deviceName = @"iPhone XR Simulator"; |
|||
break; |
|||
default: |
|||
_deviceName = @"Unknown Simulator"; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return _deviceName; |
|||
} |
|||
|
|||
+ (BOOL) NeedScreenDownSample |
|||
{ |
|||
return [[UIWidgetsDevice deviceName] isEqualToString:@"iPhone 6 Plus"] || |
|||
[[UIWidgetsDevice deviceName] isEqualToString:@"iPhone 6S Plus"] || |
|||
[[UIWidgetsDevice deviceName] isEqualToString:@"iPhone 7 Plus"] || |
|||
[[UIWidgetsDevice deviceName] isEqualToString:@"iPhone 8 Plus"]; |
|||
} |
|||
|
|||
@end |
|
|||
package com.unity.uiwidgets.plugin; |
|||
|
|||
import android.util.Log; |
|||
|
|||
import com.unity3d.player.UnityPlayer; |
|||
|
|||
import org.json.JSONArray; |
|||
import org.json.JSONException; |
|||
import org.json.JSONObject; |
|||
|
|||
import java.util.List; |
|||
|
|||
public class UIWidgetsMessageManager { |
|||
public static final String TAG = "UIWidgets"; |
|||
|
|||
private static UIWidgetsMessageManager _instance; |
|||
|
|||
private String gameObjectName; |
|||
|
|||
|
|||
public static UIWidgetsMessageManager getInstance() { |
|||
if (_instance == null) { |
|||
_instance = new UIWidgetsMessageManager(); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
public void SetObjectName(String name) { |
|||
gameObjectName = name; |
|||
} |
|||
|
|||
public void UIWidgetsMethodMessage(String channel, String method, List<Object> args) { |
|||
JSONObject object = new JSONObject(); |
|||
|
|||
try { |
|||
object.put("channel", channel); |
|||
object.put("method", method); |
|||
object.put("args", new JSONArray(args)); |
|||
UnityPlayer.UnitySendMessage(gameObjectName, "OnUIWidgetsMethodMessage", object.toString()); |
|||
} catch (JSONException e) { |
|||
Log.e(TAG, "error parse json", e); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fbff29dbbe1ce46a5bd2b95fef473852 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
validateReferences: 1 |
|||
platformData: |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
DefaultValueInitialized: true |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
package com.unity.uiwidgets.plugin; |
|||
|
|||
import android.util.Log; |
|||
|
|||
import com.unity3d.player.UnityPlayer; |
|||
import android.graphics.Rect; |
|||
import android.os.Build; |
|||
import android.util.Log; |
|||
import android.util.TypedValue; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.view.ViewTreeObserver; |
|||
import android.app.Activity; |
|||
import android.content.res.Configuration; |
|||
import android.content.res.Resources; |
|||
import android.view.Surface; |
|||
import java.util.Arrays; |
|||
import android.view.WindowManager; |
|||
import android.os.Handler; |
|||
import java.lang.reflect.Method; |
|||
|
|||
public class UIWidgetsViewController { |
|||
|
|||
private static UIWidgetsViewController _instance; |
|||
|
|||
public static UIWidgetsViewController getInstance() { |
|||
if (_instance == null) { |
|||
_instance = new UIWidgetsViewController(); |
|||
_instance.setup(); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
private UIWidgetsViewMetrics viewMetrics; |
|||
private boolean keyboardOpen; |
|||
|
|||
private float statusHeight; |
|||
private float navigationBarHeight; |
|||
|
|||
private void setup() { |
|||
keyboardOpen = false; |
|||
viewMetrics = new UIWidgetsViewMetrics(); |
|||
setupHeights(); |
|||
updateViewMetrics(); |
|||
|
|||
setupViewMetricsChangedListener(); |
|||
} |
|||
|
|||
private void setupHeights() { |
|||
final View unityView = ((ViewGroup)UnityPlayer.currentActivity.findViewById(android.R.id.content)).getChildAt(0); |
|||
Rect rect = new Rect(); |
|||
unityView.getWindowVisibleDisplayFrame(rect); |
|||
|
|||
statusHeight = rect.top; |
|||
navigationBarHeight = unityView.getRootView().getHeight() - rect.bottom; |
|||
} |
|||
|
|||
public static UIWidgetsViewMetrics getMetrics() { |
|||
UIWidgetsViewController controller = getInstance(); |
|||
return controller.viewMetrics; |
|||
} |
|||
|
|||
enum ZeroSides { NONE, LEFT, RIGHT, BOTH } |
|||
ZeroSides calculateShouldZeroSides(View unityView) { |
|||
Activity activity = UnityPlayer.currentActivity; |
|||
int orientation = activity.getResources().getConfiguration().orientation; |
|||
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); |
|||
|
|||
if (orientation == Configuration.ORIENTATION_LANDSCAPE) { |
|||
if (rotation == Surface.ROTATION_90) { |
|||
return ZeroSides.RIGHT; |
|||
} |
|||
else if (rotation == Surface.ROTATION_270) { |
|||
return Build.VERSION.SDK_INT >= 23 ? ZeroSides.LEFT : ZeroSides.RIGHT; |
|||
} else if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) { |
|||
return ZeroSides.BOTH; |
|||
} |
|||
} |
|||
|
|||
return ZeroSides.NONE; |
|||
} |
|||
|
|||
public boolean lastStatusBarHidden = true; |
|||
|
|||
private int calculateBottomKeyboardInset(Rect insets) { |
|||
if (keyboardOpen) { |
|||
return insets.bottom; |
|||
} else { |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
|
|||
private int getNavigationBarHeight() { |
|||
Resources resources = UnityPlayer.currentActivity.getResources(); |
|||
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); |
|||
if (resourceId > 0) |
|||
{ |
|||
return hasNavigationBar() ? resources.getDimensionPixelSize(resourceId) : 0; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
private boolean hasNavigationBar() { |
|||
boolean hasBar = false; |
|||
Resources resources = UnityPlayer.currentActivity.getResources(); |
|||
int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); |
|||
if (id > 0) { |
|||
hasBar = resources.getBoolean(id); |
|||
} |
|||
try { |
|||
Class systemPropertiesClass = Class.forName("android.os.SystemProperties"); |
|||
Method m = systemPropertiesClass.getMethod("get", String.class); |
|||
String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys"); |
|||
if ("1".equals(navBarOverride)) { |
|||
hasBar = false; |
|||
} else if ("0".equals(navBarOverride)) { |
|||
hasBar = true; |
|||
} |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return hasBar; |
|||
} |
|||
|
|||
public void updateViewMetrics() { |
|||
final View unityView = ((ViewGroup)UnityPlayer.currentActivity.findViewById(android.R.id.content)).getChildAt(0); |
|||
Rect rect = new Rect(); |
|||
unityView.getWindowVisibleDisplayFrame(rect); |
|||
|
|||
|
|||
rect.bottom = unityView.getRootView().getHeight() - (rect.bottom - rect.top) - rect.top; |
|||
// rect.right = unityView.getRootView().getWidth() - (rect.right - rect.left) - rect.left; |
|||
|
|||
boolean statusBarHidden = (View.SYSTEM_UI_FLAG_FULLSCREEN & unityView.getWindowSystemUiVisibility()) != 0; |
|||
boolean navigationBarHidden = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION & unityView.getWindowSystemUiVisibility()) != 0; |
|||
|
|||
ZeroSides zeroSides = ZeroSides.NONE; |
|||
if (navigationBarHidden) { |
|||
zeroSides = calculateShouldZeroSides(unityView); |
|||
} |
|||
|
|||
// viewMetrics.padding_top = rect.top; |
|||
// viewMetrics.padding_right = zeroSides == ZeroSides.RIGHT || zeroSides == ZeroSides.BOTH ? 0 : rect.right; |
|||
// viewMetrics.padding_bottom = 0; |
|||
// viewMetrics.padding_left = zeroSides == ZeroSides.LEFT || zeroSides == ZeroSides.BOTH ? 0 : rect.left; |
|||
|
|||
viewMetrics.insets_top = 0; |
|||
viewMetrics.insets_right = 0; |
|||
viewMetrics.insets_bottom = navigationBarHidden? calculateBottomKeyboardInset(rect) : rect.bottom; |
|||
viewMetrics.insets_left = 0; |
|||
|
|||
//adjust |
|||
viewMetrics.insets_bottom -= navigationBarHeight; |
|||
// viewMetrics.padding_top -= statusHeight; |
|||
|
|||
} |
|||
|
|||
public void setupViewMetricsChangedListener() { |
|||
final View unityView = ((ViewGroup)UnityPlayer.currentActivity.findViewById(android.R.id.content)).getChildAt(0); |
|||
|
|||
UnityPlayer.currentActivity.runOnUiThread(new Runnable() { |
|||
@Override |
|||
public void run() { |
|||
unityView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { |
|||
@Override |
|||
public void onSystemUiVisibilityChange(final int visibility){ |
|||
boolean statusBarHidden = (View.SYSTEM_UI_FLAG_FULLSCREEN & visibility) != 0; |
|||
unityView.setSystemUiVisibility(visibility); |
|||
UIWidgetsViewController controller = getInstance(); |
|||
if (statusBarHidden != controller.lastStatusBarHidden) { |
|||
controller.onViewMetricsChanged(); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
|
|||
unityView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { |
|||
private final int defaultKeyboardHeightDP = 100; |
|||
private final int estimatedKeyboardDP = defaultKeyboardHeightDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0); |
|||
private final Rect rect = new Rect(); |
|||
|
|||
@Override |
|||
public void onGlobalLayout() { |
|||
int estimatedKeyboardHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, estimatedKeyboardDP, unityView.getResources().getDisplayMetrics()); |
|||
unityView.getWindowVisibleDisplayFrame(rect); |
|||
int heightDiff = unityView.getRootView().getHeight() - (rect.bottom - rect.top); |
|||
boolean isShown = heightDiff >= estimatedKeyboardHeight; |
|||
|
|||
if (keyboardOpen == isShown) { |
|||
return; |
|||
} |
|||
|
|||
keyboardOpen = isShown; |
|||
onViewMetricsChanged(); |
|||
} |
|||
} |
|||
); |
|||
} |
|||
|
|||
public void onViewMetricsChanged() { |
|||
updateViewMetrics(); |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("ViewportMetricsChanged", "UIWidgetViewController.keyboardChanged", |
|||
Arrays.asList("")); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: dd01a28ebf279449dace0dc8580a9ece |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
validateReferences: 1 |
|||
platformData: |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
DefaultValueInitialized: true |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
package com.unity.uiwidgets.plugin; |
|||
|
|||
public class UIWidgetsViewMetrics { |
|||
public float insets_top; |
|||
public float insets_bottom; |
|||
public float insets_left; |
|||
public float insets_right; |
|||
|
|||
public float padding_top; |
|||
public float padding_bottom; |
|||
public float padding_left; |
|||
public float padding_right; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: efb8c112055a04b7dae8566ccf299bc7 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
validateReferences: 1 |
|||
platformData: |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
DefaultValueInitialized: true |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
package com.unity.uiwidgets.plugin; |
|||
import android.view.View; |
|||
import android.view.WindowManager; |
|||
|
|||
import com.unity3d.player.UnityPlayer; |
|||
|
|||
public class Utils { |
|||
public static final String TAG = "UIWidgets"; |
|||
|
|||
public static void SetStatusBarState(final boolean show) { |
|||
UnityPlayer.currentActivity.runOnUiThread(new Runnable() { |
|||
public void run() { |
|||
if (show) { |
|||
UnityPlayer.currentActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); |
|||
} else { |
|||
UnityPlayer.currentActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 418c6c9d61a804a9e817e77aa7f83f67 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
validateReferences: 1 |
|||
platformData: |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
DefaultValueInitialized: true |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
package com.unity.uiwidgets.plugin.editing; |
|||
|
|||
import android.content.Context; |
|||
import android.text.Editable; |
|||
import android.text.Selection; |
|||
import android.view.KeyEvent; |
|||
import android.view.View; |
|||
import android.view.inputmethod.BaseInputConnection; |
|||
import android.view.inputmethod.EditorInfo; |
|||
import android.view.inputmethod.InputMethodManager; |
|||
|
|||
import com.unity.uiwidgets.plugin.UIWidgetsMessageManager; |
|||
|
|||
|
|||
import java.util.Arrays; |
|||
import java.util.HashMap; |
|||
|
|||
class InputConnectionAdaptor extends BaseInputConnection { |
|||
|
|||
private View mTextInputView; |
|||
private final int mClient; |
|||
private final Editable mEditable; |
|||
private int mBatchCount; |
|||
private InputMethodManager mImm; |
|||
|
|||
public InputConnectionAdaptor(View view, int client, |
|||
Editable editable) { |
|||
super(view, true); |
|||
mTextInputView = view; |
|||
mClient = client; |
|||
mEditable = editable; |
|||
mBatchCount = 0; |
|||
mImm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); |
|||
} |
|||
|
|||
// Send the current state of the editable to Flutter. |
|||
private void updateEditingState() { |
|||
// If the IME is in the middle of a batch edit, then wait until it completes. |
|||
if (mBatchCount > 0) |
|||
return; |
|||
|
|||
int selectionStart = Selection.getSelectionStart(mEditable); |
|||
int selectionEnd = Selection.getSelectionEnd(mEditable); |
|||
int composingStart = BaseInputConnection.getComposingSpanStart(mEditable); |
|||
int composingEnd = BaseInputConnection.getComposingSpanEnd(mEditable); |
|||
|
|||
mImm.updateSelection(mTextInputView, |
|||
selectionStart, selectionEnd, |
|||
composingStart, composingEnd); |
|||
|
|||
HashMap<Object, Object> state = new HashMap<Object, Object>(); |
|||
state.put("text", mEditable.toString()); |
|||
state.put("selectionBase", selectionStart); |
|||
state.put("selectionExtent", selectionEnd); |
|||
state.put("composingBase", composingStart); |
|||
state.put("composingExtent", composingEnd); |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.updateEditingState", |
|||
Arrays.asList(mClient, state)); |
|||
} |
|||
|
|||
@Override |
|||
public Editable getEditable() { |
|||
return mEditable; |
|||
} |
|||
|
|||
@Override |
|||
public boolean beginBatchEdit() { |
|||
mBatchCount++; |
|||
return super.beginBatchEdit(); |
|||
} |
|||
|
|||
@Override |
|||
public boolean endBatchEdit() { |
|||
boolean result = super.endBatchEdit(); |
|||
mBatchCount--; |
|||
updateEditingState(); |
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
public boolean commitText(CharSequence text, int newCursorPosition) { |
|||
boolean result = super.commitText(text, newCursorPosition); |
|||
updateEditingState(); |
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
public boolean deleteSurroundingText(int beforeLength, int afterLength) { |
|||
if (Selection.getSelectionStart(mEditable) == -1) |
|||
return true; |
|||
|
|||
boolean result = super.deleteSurroundingText(beforeLength, afterLength); |
|||
updateEditingState(); |
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
public boolean setComposingRegion(int start, int end) { |
|||
boolean result = super.setComposingRegion(start, end); |
|||
updateEditingState(); |
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
public boolean setComposingText(CharSequence text, int newCursorPosition) { |
|||
boolean result; |
|||
if (text.length() == 0) { |
|||
result = super.commitText(text, newCursorPosition); |
|||
} else { |
|||
result = super.setComposingText(text, newCursorPosition); |
|||
} |
|||
updateEditingState(); |
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
public boolean setSelection(int start, int end) { |
|||
boolean result = super.setSelection(start, end); |
|||
updateEditingState(); |
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
public boolean sendKeyEvent(KeyEvent event) { |
|||
if (event.getAction() == KeyEvent.ACTION_DOWN) { |
|||
if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) { |
|||
int selStart = Selection.getSelectionStart(mEditable); |
|||
int selEnd = Selection.getSelectionEnd(mEditable); |
|||
String text = mEditable.toString(); |
|||
if(selStart >= 0 && selStart < text.length() && isTrailSurrogate(text.charAt(selStart))) { |
|||
selStart++; |
|||
} |
|||
if(selEnd >= 0 && selEnd < text.length() && isTrailSurrogate(text.charAt(selEnd))) { |
|||
selEnd++; |
|||
} |
|||
if (selEnd > selStart) { |
|||
// Delete the selection. |
|||
Selection.setSelection(mEditable, selStart); |
|||
mEditable.delete(selStart, selEnd); |
|||
updateEditingState(); |
|||
return true; |
|||
} else if (selStart > 0) { |
|||
// Delete to the left of the cursor. |
|||
int newSel = Math.max(selStart - 1, 0); |
|||
if(selStart >= 2 && isTrailSurrogate(text.charAt(selStart-1))) |
|||
newSel = selStart - 2; |
|||
Selection.setSelection(mEditable, newSel); |
|||
mEditable.delete(newSel, selStart); |
|||
updateEditingState(); |
|||
return true; |
|||
} |
|||
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) { |
|||
int selStart = Selection.getSelectionStart(mEditable); |
|||
int newSel = Math.max(selStart - 1, 0); |
|||
setSelection(newSel, newSel); |
|||
return true; |
|||
} else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) { |
|||
int selStart = Selection.getSelectionStart(mEditable); |
|||
int newSel = Math.min(selStart + 1, mEditable.length()); |
|||
setSelection(newSel, newSel); |
|||
return true; |
|||
} else { |
|||
// Enter a character. |
|||
int character = event.getUnicodeChar(); |
|||
if (character != 0) { |
|||
int selStart = Math.max(0, Selection.getSelectionStart(mEditable)); |
|||
int selEnd = Math.max(0, Selection.getSelectionEnd(mEditable)); |
|||
if (selEnd != selStart) |
|||
mEditable.delete(selStart, selEnd); |
|||
mEditable.insert(selStart, String.valueOf((char) character)); |
|||
setSelection(selStart + 1, selStart + 1); |
|||
updateEditingState(); |
|||
} |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
@Override |
|||
public boolean performEditorAction(int actionCode) { |
|||
switch (actionCode) { |
|||
// TODO(mattcarroll): is newline an appropriate action for "none"? |
|||
case EditorInfo.IME_ACTION_NONE: |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction", |
|||
Arrays.asList(mClient, "TextInputAction.newline")); |
|||
break; |
|||
case EditorInfo.IME_ACTION_UNSPECIFIED: |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction", |
|||
Arrays.asList(mClient, "TextInputAction.unspecified")); |
|||
break; |
|||
case EditorInfo.IME_ACTION_GO: |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction", |
|||
Arrays.asList(mClient, "TextInputAction.go")); |
|||
break; |
|||
case EditorInfo.IME_ACTION_SEARCH: |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction", |
|||
Arrays.asList(mClient, "TextInputAction.search")); |
|||
break; |
|||
case EditorInfo.IME_ACTION_SEND: |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction", |
|||
Arrays.asList(mClient, "TextInputAction.send")); |
|||
break; |
|||
case EditorInfo.IME_ACTION_NEXT: |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction", |
|||
Arrays.asList(mClient, "TextInputAction.next")); |
|||
break; |
|||
case EditorInfo.IME_ACTION_PREVIOUS: |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction", |
|||
Arrays.asList(mClient, "TextInputAction.previous")); |
|||
break; |
|||
default: |
|||
case EditorInfo.IME_ACTION_DONE: |
|||
UIWidgetsMessageManager.getInstance().UIWidgetsMethodMessage("TextInput", "TextInputClient.performAction", |
|||
Arrays.asList(mClient, "TextInputAction.done")); |
|||
break; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
private boolean isLeadSurrogate(int c) { |
|||
return (c & 0xfffffc00) == 0xd800; |
|||
} |
|||
|
|||
|
|||
private boolean isTrailSurrogate(int c) { |
|||
return (c & 0xfffffc00) == 0xdc00; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ee71437b1f6244476b59360f556db8b7 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
platformData: |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
DefaultValueInitialized: true |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 867d39559763e4ea9b82b9a5987a1930 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
platformData: |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
DefaultValueInitialized: true |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
package com.unity.uiwidgets.plugin.editing; |
|||
|
|||
import android.content.Context; |
|||
import android.util.Log; |
|||
import android.view.KeyCharacterMap; |
|||
import android.view.KeyEvent; |
|||
import android.view.View; |
|||
import android.view.inputmethod.EditorInfo; |
|||
import android.view.inputmethod.InputConnection; |
|||
import android.view.inputmethod.InputMethodManager; |
|||
|
|||
import org.json.JSONException; |
|||
|
|||
import static com.unity.uiwidgets.plugin.Utils.TAG; |
|||
|
|||
public class TextInputView extends View { |
|||
private InputConnection mLastInputConnection; |
|||
private final InputMethodManager mImm; |
|||
public TextInputView(Context context) { |
|||
super(context); |
|||
setFocusable(true); |
|||
setFocusableInTouchMode(true); |
|||
mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); |
|||
} |
|||
|
|||
@Override |
|||
public InputConnection onCreateInputConnection(EditorInfo outAttrs) { |
|||
Log.i(TAG, "onCreateInputConnection"); |
|||
try { |
|||
mLastInputConnection = TextInputPlugin.getInstance().createInputConnection(this, outAttrs); |
|||
return mLastInputConnection; |
|||
} catch (JSONException e) { |
|||
Log.e(TAG, "Failed to create input connection", e); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public boolean onKeyDown(int keyCode, KeyEvent event) { |
|||
if (event.getDeviceId() != KeyCharacterMap.VIRTUAL_KEYBOARD) { |
|||
if (mLastInputConnection != null && mImm.isAcceptingText()) { |
|||
mLastInputConnection.sendKeyEvent(event); |
|||
} |
|||
} |
|||
|
|||
return super.onKeyDown(keyCode, event); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: acd0b1bb7c09d4b5ca41554aa9c30257 |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 0 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
platformData: |
|||
- first: |
|||
Android: Android |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
DefaultValueInitialized: true |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
package com.unity.uiwidgets.plugin.editing; |
|||
|
|||
import android.content.Context; |
|||
import android.text.Editable; |
|||
import android.text.InputType; |
|||
import android.text.Selection; |
|||
import android.util.Log; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.view.inputmethod.BaseInputConnection; |
|||
import android.view.inputmethod.EditorInfo; |
|||
import android.view.inputmethod.InputConnection; |
|||
import android.view.inputmethod.InputMethodManager; |
|||
|
|||
import com.unity3d.player.UnityPlayer; |
|||
|
|||
import org.json.JSONException; |
|||
import org.json.JSONObject; |
|||
|
|||
import static com.unity.uiwidgets.plugin.Utils.TAG; |
|||
|
|||
public class TextInputPlugin { |
|||
private final TextInputView mView; |
|||
private final InputMethodManager mImm; |
|||
private int mClient = 0; |
|||
private JSONObject mConfiguration; |
|||
private Editable mEditable; |
|||
private boolean mRestartInputPending; |
|||
|
|||
private static TextInputPlugin _instance; |
|||
public static TextInputPlugin getInstance() { |
|||
if (_instance == null) { |
|||
_instance = new TextInputPlugin(); |
|||
} |
|||
return _instance; |
|||
} |
|||
|
|||
public TextInputPlugin() { |
|||
ViewGroup contentView = (ViewGroup)UnityPlayer.currentActivity.findViewById(android.R.id.content); |
|||
mView = new TextInputView(UnityPlayer.currentActivity); |
|||
mView.requestFocus(); |
|||
contentView.addView(mView, 1, 1); |
|||
mImm = (InputMethodManager) mView.getContext().getSystemService( |
|||
Context.INPUT_METHOD_SERVICE); |
|||
} |
|||
|
|||
public static void show() { |
|||
UnityPlayer.currentActivity.runOnUiThread(new Runnable() { |
|||
@Override |
|||
public void run() { |
|||
TextInputPlugin plugin = getInstance(); |
|||
plugin.showTextInput(plugin.mView); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
|
|||
public static void hide() { |
|||
UnityPlayer.currentActivity.runOnUiThread(new Runnable() { |
|||
@Override |
|||
public void run() { |
|||
TextInputPlugin plugin = getInstance(); |
|||
plugin.hideTextInput(plugin.mView); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void setClient(int client, String configurationJson) { |
|||
UnityPlayer.currentActivity.runOnUiThread(new Runnable() { |
|||
@Override |
|||
public void run() { |
|||
try { |
|||
JSONObject configuration = new JSONObject(configurationJson); |
|||
TextInputPlugin plugin = getInstance(); |
|||
plugin.setTextInputClient(plugin.mView, client, configuration); |
|||
} catch (JSONException e) { |
|||
Log.e(TAG, "error parse json", e); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
} |
|||
|
|||
public static void setEditingState(String stateJson) { |
|||
|
|||
UnityPlayer.currentActivity.runOnUiThread(new Runnable() { |
|||
@Override |
|||
public void run() { |
|||
try { |
|||
TextInputPlugin plugin = getInstance(); |
|||
JSONObject state = new JSONObject(stateJson); |
|||
plugin.setTextInputEditingState(plugin.mView, state); |
|||
} catch (JSONException e) { |
|||
Log.e(TAG, "error parse json", e); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void clearClient() { |
|||
|
|||
UnityPlayer.currentActivity.runOnUiThread(new Runnable() { |
|||
@Override |
|||
public void run() { |
|||
TextInputPlugin plugin = getInstance(); |
|||
plugin.clearTextInputClient(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private static int inputTypeFromTextInputType(JSONObject type, boolean obscureText, |
|||
boolean autocorrect, String textCapitalization) throws JSONException { |
|||
String inputType = type.getString("name"); |
|||
if (inputType.equals("TextInputType.datetime")) return InputType.TYPE_CLASS_DATETIME; |
|||
if (inputType.equals("TextInputType.number")) { |
|||
int textType = InputType.TYPE_CLASS_NUMBER; |
|||
if (type.optBoolean("signed")) textType |= InputType.TYPE_NUMBER_FLAG_SIGNED; |
|||
if (type.optBoolean("decimal")) textType |= InputType.TYPE_NUMBER_FLAG_DECIMAL; |
|||
return textType; |
|||
} |
|||
if (inputType.equals("TextInputType.phone")) return InputType.TYPE_CLASS_PHONE; |
|||
|
|||
int textType = InputType.TYPE_CLASS_TEXT; |
|||
if (inputType.equals("TextInputType.multiline")) |
|||
textType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE; |
|||
else if (inputType.equals("TextInputType.emailAddress")) |
|||
textType |= InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; |
|||
else if (inputType.equals("TextInputType.url")) |
|||
textType |= InputType.TYPE_TEXT_VARIATION_URI; |
|||
if (obscureText) { |
|||
// Note: both required. Some devices ignore TYPE_TEXT_FLAG_NO_SUGGESTIONS. |
|||
textType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; |
|||
textType |= InputType.TYPE_TEXT_VARIATION_PASSWORD; |
|||
} else { |
|||
if (autocorrect) textType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; |
|||
} |
|||
if (textCapitalization.equals("TextCapitalization.characters")) { |
|||
textType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS; |
|||
} else if (textCapitalization.equals("TextCapitalization.words")) { |
|||
textType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS; |
|||
} else if (textCapitalization.equals("TextCapitalization.sentences")) { |
|||
textType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; |
|||
} |
|||
return textType; |
|||
} |
|||
|
|||
private static int inputActionFromTextInputAction(String inputAction) { |
|||
switch (inputAction) { |
|||
case "TextInputAction.newline": |
|||
return EditorInfo.IME_ACTION_NONE; |
|||
case "TextInputAction.none": |
|||
return EditorInfo.IME_ACTION_NONE; |
|||
case "TextInputAction.unspecified": |
|||
return EditorInfo.IME_ACTION_UNSPECIFIED; |
|||
case "TextInputAction.done": |
|||
return EditorInfo.IME_ACTION_DONE; |
|||
case "TextInputAction.go": |
|||
return EditorInfo.IME_ACTION_GO; |
|||
case "TextInputAction.search": |
|||
return EditorInfo.IME_ACTION_SEARCH; |
|||
case "TextInputAction.send": |
|||
return EditorInfo.IME_ACTION_SEND; |
|||
case "TextInputAction.next": |
|||
return EditorInfo.IME_ACTION_NEXT; |
|||
case "TextInputAction.previous": |
|||
return EditorInfo.IME_ACTION_PREVIOUS; |
|||
default: |
|||
// Present default key if bad input type is given. |
|||
return EditorInfo.IME_ACTION_UNSPECIFIED; |
|||
} |
|||
} |
|||
|
|||
public InputConnection createInputConnection(View view, EditorInfo outAttrs) |
|||
throws JSONException { |
|||
if (mClient == 0) return null; |
|||
|
|||
outAttrs.inputType = inputTypeFromTextInputType(mConfiguration.getJSONObject("inputType"), |
|||
mConfiguration.optBoolean("obscureText"), |
|||
mConfiguration.optBoolean("autocorrect", true), |
|||
mConfiguration.getString("textCapitalization")); |
|||
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN; |
|||
int enterAction; |
|||
if (mConfiguration.isNull("inputAction")) { |
|||
// If an explicit input action isn't set, then default to none for multi-line fields |
|||
// and done for single line fields. |
|||
enterAction = (InputType.TYPE_TEXT_FLAG_MULTI_LINE & outAttrs.inputType) != 0 |
|||
? EditorInfo.IME_ACTION_NONE |
|||
: EditorInfo.IME_ACTION_DONE; |
|||
} else { |
|||
enterAction = inputActionFromTextInputAction(mConfiguration.getString("inputAction")); |
|||
} |
|||
if (!mConfiguration.isNull("actionLabel")) { |
|||
outAttrs.actionLabel = mConfiguration.getString("actionLabel"); |
|||
outAttrs.actionId = enterAction; |
|||
} |
|||
outAttrs.imeOptions |= enterAction; |
|||
|
|||
InputConnectionAdaptor connection = |
|||
new InputConnectionAdaptor(view, mClient, mEditable); |
|||
outAttrs.initialSelStart = Selection.getSelectionStart(mEditable); |
|||
outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable); |
|||
|
|||
return connection; |
|||
} |
|||
|
|||
private void showTextInput(View view) { |
|||
view.requestFocus(); |
|||
mImm.showSoftInput(view, 0); |
|||
} |
|||
|
|||
private void hideTextInput(View view) { |
|||
mImm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0); |
|||
} |
|||
|
|||
private void setTextInputClient(View view, int client, JSONObject configuration) { |
|||
mClient = client; |
|||
mConfiguration = configuration; |
|||
mEditable = Editable.Factory.getInstance().newEditable(""); |
|||
|
|||
// setTextInputClient will be followed by a call to setTextInputEditingState. |
|||
// Do a restartInput at that time. |
|||
mRestartInputPending = true; |
|||
} |
|||
|
|||
private void applyStateToSelection(JSONObject state) throws JSONException { |
|||
int selStart = state.getInt("selectionBase"); |
|||
int selEnd = state.getInt("selectionExtent"); |
|||
if (selStart >= 0 && selStart <= mEditable.length() && selEnd >= 0 |
|||
&& selEnd <= mEditable.length()) { |
|||
Selection.setSelection(mEditable, selStart, selEnd); |
|||
} else { |
|||
Selection.removeSelection(mEditable); |
|||
} |
|||
} |
|||
|
|||
private void setTextInputEditingState(View view, JSONObject state) throws JSONException { |
|||
if (!mRestartInputPending && state.getString("text").equals(mEditable.toString())) { |
|||
applyStateToSelection(state); |
|||
mImm.updateSelection(mView, Math.max(Selection.getSelectionStart(mEditable), 0), |
|||
Math.max(Selection.getSelectionEnd(mEditable), 0), |
|||
BaseInputConnection.getComposingSpanStart(mEditable), |
|||
BaseInputConnection.getComposingSpanEnd(mEditable)); |
|||
} else { |
|||
mEditable.replace(0, mEditable.length(), state.getString("text")); |
|||
applyStateToSelection(state); |
|||
mImm.restartInput(view); |
|||
mRestartInputPending = false; |
|||
} |
|||
} |
|||
|
|||
private void clearTextInputClient() { |
|||
mClient = 0; |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue