Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_43355755
engine
提交
eaf70ca0
E
engine
项目概览
weixin_43355755
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
eaf70ca0
编写于
7月 01, 2021
作者:
C
chunhtai
提交者:
GitHub
7月 01, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixes inset padding in android accessibility bridge (#27083)
上级
3fd50a8b
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
321 addition
and
25 deletion
+321
-25
ci/licenses_golden/licenses_flutter
ci/licenses_golden/licenses_flutter
+1
-0
shell/platform/android/BUILD.gn
shell/platform/android/BUILD.gn
+2
-0
shell/platform/android/io/flutter/util/ViewUtils.java
shell/platform/android/io/flutter/util/ViewUtils.java
+31
-0
shell/platform/android/io/flutter/view/AccessibilityBridge.java
...platform/android/io/flutter/view/AccessibilityBridge.java
+46
-8
shell/platform/android/io/flutter/view/FlutterView.java
shell/platform/android/io/flutter/view/FlutterView.java
+2
-16
shell/platform/android/test/io/flutter/util/ViewUtilsTest.java
.../platform/android/test/io/flutter/util/ViewUtilsTest.java
+33
-0
shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java
...android/test/io/flutter/view/AccessibilityBridgeTest.java
+206
-1
未找到文件。
ci/licenses_golden/licenses_flutter
浏览文件 @
eaf70ca0
...
...
@@ -898,6 +898,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/Virtual
FILE: ../../../flutter/shell/platform/android/io/flutter/util/PathUtils.java
FILE: ../../../flutter/shell/platform/android/io/flutter/util/Preconditions.java
FILE: ../../../flutter/shell/platform/android/io/flutter/util/Predicate.java
FILE: ../../../flutter/shell/platform/android/io/flutter/util/ViewUtils.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/AccessibilityBridge.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterCallbackInformation.java
...
...
shell/platform/android/BUILD.gn
浏览文件 @
eaf70ca0
...
...
@@ -241,6 +241,7 @@ android_java_sources = [
"io/flutter/util/PathUtils.java",
"io/flutter/util/Preconditions.java",
"io/flutter/util/Predicate.java",
"io/flutter/util/ViewUtils.java",
"io/flutter/view/AccessibilityBridge.java",
"io/flutter/view/AccessibilityViewEmbedder.java",
"io/flutter/view/FlutterCallbackInformation.java",
...
...
@@ -504,6 +505,7 @@ action("robolectric_tests") {
"test/io/flutter/plugins/GeneratedPluginRegistrant.java",
"test/io/flutter/util/FakeKeyEvent.java",
"test/io/flutter/util/PreconditionsTest.java",
"test/io/flutter/util/ViewUtilsTest.java",
"test/io/flutter/view/AccessibilityBridgeTest.java",
]
...
...
shell/platform/android/io/flutter/util/ViewUtils.java
0 → 100644
浏览文件 @
eaf70ca0
// 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
io.flutter.util
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.content.ContextWrapper
;
public
final
class
ViewUtils
{
/**
* Retrieves the {@link Activity} from a given {@link Context}.
*
* <p>This method will recursively traverse up the context chain if it is a {@link ContextWrapper}
* until it finds the first instance of the base context that is an {@link Activity}.
*/
public
static
Activity
getActivity
(
Context
context
)
{
if
(
context
==
null
)
{
return
null
;
}
if
(
context
instanceof
Activity
)
{
return
(
Activity
)
context
;
}
if
(
context
instanceof
ContextWrapper
)
{
// Recurse up chain of base contexts until we find an Activity.
return
getActivity
(((
ContextWrapper
)
context
).
getBaseContext
());
}
return
null
;
}
}
shell/platform/android/io/flutter/view/AccessibilityBridge.java
浏览文件 @
eaf70ca0
...
...
@@ -6,7 +6,9 @@ package io.flutter.view;
import
android.annotation.SuppressLint
;
import
android.annotation.TargetApi
;
import
android.app.Activity
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.database.ContentObserver
;
import
android.graphics.Rect
;
import
android.net.Uri
;
...
...
@@ -22,6 +24,7 @@ import android.text.style.TtsSpan;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.view.WindowInsets
;
import
android.view.WindowManager
;
import
android.view.accessibility.AccessibilityEvent
;
import
android.view.accessibility.AccessibilityManager
;
import
android.view.accessibility.AccessibilityNodeInfo
;
...
...
@@ -35,6 +38,7 @@ import io.flutter.Log;
import
io.flutter.embedding.engine.systemchannels.AccessibilityChannel
;
import
io.flutter.plugin.platform.PlatformViewsAccessibilityDelegate
;
import
io.flutter.util.Predicate
;
import
io.flutter.util.ViewUtils
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.nio.charset.Charset
;
...
...
@@ -1507,18 +1511,29 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
if
(
rootObject
!=
null
)
{
final
float
[]
identity
=
new
float
[
16
];
Matrix
.
setIdentityM
(
identity
,
0
);
//
in a
ndroid devices API 23 and above, the system nav bar can be placed on the left side
//
In A
ndroid devices API 23 and above, the system nav bar can be placed on the left side
// of the screen in landscape mode. We must handle the translation ourselves for the
// a11y nodes.
if
(
Build
.
VERSION
.
SDK_INT
>=
23
)
{
WindowInsets
insets
=
rootAccessibilityView
.
getRootWindowInsets
();
if
(
insets
!=
null
)
{
if
(!
lastLeftFrameInset
.
equals
(
insets
.
getSystemWindowInsetLeft
()))
{
rootObject
.
globalGeometryDirty
=
true
;
rootObject
.
inverseTransformDirty
=
true
;
boolean
needsToApplyLeftCutoutInset
=
true
;
// In Android devices API 28 and above, the `layoutInDisplayCutoutMode` window attribute
// can be set to allow overlapping content within the cutout area. Query the attribute
// to figure out whether the content overlaps with the cutout and decide whether to
// apply cutout inset.
if
(
Build
.
VERSION
.
SDK_INT
>=
28
)
{
needsToApplyLeftCutoutInset
=
doesLayoutInDisplayCutoutModeRequireLeftInset
();
}
if
(
needsToApplyLeftCutoutInset
)
{
WindowInsets
insets
=
rootAccessibilityView
.
getRootWindowInsets
();
if
(
insets
!=
null
)
{
if
(!
lastLeftFrameInset
.
equals
(
insets
.
getSystemWindowInsetLeft
()))
{
rootObject
.
globalGeometryDirty
=
true
;
rootObject
.
inverseTransformDirty
=
true
;
}
lastLeftFrameInset
=
insets
.
getSystemWindowInsetLeft
();
Matrix
.
translateM
(
identity
,
0
,
lastLeftFrameInset
,
0
,
0
);
}
lastLeftFrameInset
=
insets
.
getSystemWindowInsetLeft
();
Matrix
.
translateM
(
identity
,
0
,
lastLeftFrameInset
,
0
,
0
);
}
}
rootObject
.
updateRecursively
(
identity
,
visitedObjects
,
false
);
...
...
@@ -1822,6 +1837,29 @@ public class AccessibilityBridge extends AccessibilityNodeProvider {
return
event
;
}
/**
* Reads the {@code layoutInDisplayCutoutMode} value from the window attribute and returns whether
* a left cutout inset is required.
*
* <p>The {@code layoutInDisplayCutoutMode} is added after API level 28.
*/
@TargetApi
(
28
)
@RequiresApi
(
28
)
private
boolean
doesLayoutInDisplayCutoutModeRequireLeftInset
()
{
Context
context
=
rootAccessibilityView
.
getContext
();
Activity
activity
=
ViewUtils
.
getActivity
(
context
);
if
(
activity
==
null
||
activity
.
getWindow
()
==
null
)
{
// The activity is not visible, it does not matter whether to apply left inset
// or not.
return
false
;
}
int
layoutInDisplayCutoutMode
=
activity
.
getWindow
().
getAttributes
().
layoutInDisplayCutoutMode
;
return
layoutInDisplayCutoutMode
==
WindowManager
.
LayoutParams
.
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
||
layoutInDisplayCutoutMode
==
WindowManager
.
LayoutParams
.
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
;
}
/**
* Hook called just before a {@link SemanticsNode} is removed from the Android cache of Flutter's
* semantics tree.
...
...
shell/platform/android/io/flutter/view/FlutterView.java
浏览文件 @
eaf70ca0
...
...
@@ -8,7 +8,6 @@ import android.annotation.SuppressLint;
import
android.annotation.TargetApi
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.content.ContextWrapper
;
import
android.content.res.Configuration
;
import
android.graphics.Bitmap
;
import
android.graphics.Insets
;
...
...
@@ -65,6 +64,7 @@ import io.flutter.plugin.localization.LocalizationPlugin;
import
io.flutter.plugin.mouse.MouseCursorPlugin
;
import
io.flutter.plugin.platform.PlatformPlugin
;
import
io.flutter.plugin.platform.PlatformViewsController
;
import
io.flutter.util.ViewUtils
;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.List
;
...
...
@@ -162,7 +162,7 @@ public class FlutterView extends SurfaceView
public
FlutterView
(
Context
context
,
AttributeSet
attrs
,
FlutterNativeView
nativeView
)
{
super
(
context
,
attrs
);
Activity
activity
=
getActivity
(
getContext
());
Activity
activity
=
ViewUtils
.
getActivity
(
getContext
());
if
(
activity
==
null
)
{
throw
new
IllegalArgumentException
(
"Bad context"
);
}
...
...
@@ -257,20 +257,6 @@ public class FlutterView extends SurfaceView
sendUserPlatformSettingsToDart
();
}
private
static
Activity
getActivity
(
Context
context
)
{
if
(
context
==
null
)
{
return
null
;
}
if
(
context
instanceof
Activity
)
{
return
(
Activity
)
context
;
}
if
(
context
instanceof
ContextWrapper
)
{
// Recurse up chain of base contexts until we find an Activity.
return
getActivity
(((
ContextWrapper
)
context
).
getBaseContext
());
}
return
null
;
}
@NonNull
public
DartExecutor
getDartExecutor
()
{
return
dartExecutor
;
...
...
shell/platform/android/test/io/flutter/util/ViewUtilsTest.java
0 → 100644
浏览文件 @
eaf70ca0
// 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
io.flutter.util
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.content.ContextWrapper
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.RobolectricTestRunner
;
import
org.robolectric.annotation.Config
;
@Config
(
manifest
=
Config
.
NONE
)
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
ViewUtilsTest
{
@Test
public
void
canGetActivity
()
{
// Non activity context returns null
Context
nonActivityContext
=
mock
(
Context
.
class
);
assertEquals
(
null
,
ViewUtils
.
getActivity
(
nonActivityContext
));
Activity
activity
=
mock
(
Activity
.
class
);
assertEquals
(
activity
,
ViewUtils
.
getActivity
(
activity
));
ContextWrapper
wrapper
=
new
ContextWrapper
(
new
ContextWrapper
(
activity
));
assertEquals
(
activity
,
ViewUtils
.
getActivity
(
wrapper
));
}
}
shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java
浏览文件 @
eaf70ca0
...
...
@@ -20,6 +20,7 @@ import static org.mockito.Mockito.verify;
import
static
org
.
mockito
.
Mockito
.
when
;
import
android.annotation.TargetApi
;
import
android.app.Activity
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.graphics.Rect
;
...
...
@@ -30,6 +31,9 @@ import android.text.style.TtsSpan;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.view.ViewParent
;
import
android.view.Window
;
import
android.view.WindowInsets
;
import
android.view.WindowManager
;
import
android.view.accessibility.AccessibilityEvent
;
import
android.view.accessibility.AccessibilityManager
;
import
android.view.accessibility.AccessibilityNodeInfo
;
...
...
@@ -279,6 +283,200 @@ public class AccessibilityBridgeTest {
verify
(
mockNodeInfo2
,
times
(
1
)).
setTraversalAfter
(
eq
(
mockRootView
),
eq
(
1
));
}
@TargetApi
(
28
)
@Test
public
void
itSetCutoutInsetBasedonLayoutModeNever
()
{
int
expectedInsetLeft
=
5
;
int
top
=
0
;
int
left
=
0
;
int
right
=
100
;
int
bottom
=
200
;
AccessibilityViewEmbedder
mockViewEmbedder
=
mock
(
AccessibilityViewEmbedder
.
class
);
AccessibilityManager
mockManager
=
mock
(
AccessibilityManager
.
class
);
View
mockRootView
=
mock
(
View
.
class
);
Activity
context
=
mock
(
Activity
.
class
);
Window
window
=
mock
(
Window
.
class
);
WindowInsets
insets
=
mock
(
WindowInsets
.
class
);
WindowManager
.
LayoutParams
layoutParams
=
new
WindowManager
.
LayoutParams
();
layoutParams
.
layoutInDisplayCutoutMode
=
WindowManager
.
LayoutParams
.
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
;
when
(
mockRootView
.
getContext
()).
thenReturn
(
context
);
when
(
context
.
getWindow
()).
thenReturn
(
window
);
when
(
window
.
getAttributes
()).
thenReturn
(
layoutParams
);
when
(
mockRootView
.
getRootWindowInsets
()).
thenReturn
(
insets
);
when
(
insets
.
getSystemWindowInsetLeft
()).
thenReturn
(
expectedInsetLeft
);
when
(
context
.
getPackageName
()).
thenReturn
(
"test"
);
AccessibilityBridge
accessibilityBridge
=
setUpBridge
(
mockRootView
,
mockManager
,
mockViewEmbedder
);
ViewParent
mockParent
=
mock
(
ViewParent
.
class
);
when
(
mockRootView
.
getParent
()).
thenReturn
(
mockParent
);
when
(
mockManager
.
isEnabled
()).
thenReturn
(
true
);
TestSemanticsNode
root
=
new
TestSemanticsNode
();
root
.
id
=
0
;
root
.
left
=
left
;
root
.
top
=
top
;
root
.
right
=
right
;
root
.
bottom
=
bottom
;
TestSemanticsUpdate
testSemanticsUpdate
=
root
.
toUpdate
();
testSemanticsUpdate
.
sendUpdateToBridge
(
accessibilityBridge
);
AccessibilityBridge
spyAccessibilityBridge
=
spy
(
accessibilityBridge
);
AccessibilityNodeInfo
mockNodeInfo
=
mock
(
AccessibilityNodeInfo
.
class
);
when
(
spyAccessibilityBridge
.
obtainAccessibilityNodeInfo
(
mockRootView
,
0
))
.
thenReturn
(
mockNodeInfo
);
spyAccessibilityBridge
.
createAccessibilityNodeInfo
(
0
);
verify
(
mockNodeInfo
,
times
(
1
))
.
setBoundsInScreen
(
new
Rect
(
left
+
expectedInsetLeft
,
top
,
right
+
expectedInsetLeft
,
bottom
));
}
@TargetApi
(
28
)
@Test
public
void
itSetCutoutInsetBasedonLayoutModeDefault
()
{
int
expectedInsetLeft
=
5
;
int
top
=
0
;
int
left
=
0
;
int
right
=
100
;
int
bottom
=
200
;
AccessibilityViewEmbedder
mockViewEmbedder
=
mock
(
AccessibilityViewEmbedder
.
class
);
AccessibilityManager
mockManager
=
mock
(
AccessibilityManager
.
class
);
View
mockRootView
=
mock
(
View
.
class
);
Activity
context
=
mock
(
Activity
.
class
);
Window
window
=
mock
(
Window
.
class
);
WindowInsets
insets
=
mock
(
WindowInsets
.
class
);
WindowManager
.
LayoutParams
layoutParams
=
new
WindowManager
.
LayoutParams
();
layoutParams
.
layoutInDisplayCutoutMode
=
WindowManager
.
LayoutParams
.
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
;
when
(
mockRootView
.
getContext
()).
thenReturn
(
context
);
when
(
context
.
getWindow
()).
thenReturn
(
window
);
when
(
window
.
getAttributes
()).
thenReturn
(
layoutParams
);
when
(
mockRootView
.
getRootWindowInsets
()).
thenReturn
(
insets
);
when
(
insets
.
getSystemWindowInsetLeft
()).
thenReturn
(
expectedInsetLeft
);
when
(
context
.
getPackageName
()).
thenReturn
(
"test"
);
AccessibilityBridge
accessibilityBridge
=
setUpBridge
(
mockRootView
,
mockManager
,
mockViewEmbedder
);
ViewParent
mockParent
=
mock
(
ViewParent
.
class
);
when
(
mockRootView
.
getParent
()).
thenReturn
(
mockParent
);
when
(
mockManager
.
isEnabled
()).
thenReturn
(
true
);
TestSemanticsNode
root
=
new
TestSemanticsNode
();
root
.
id
=
0
;
root
.
left
=
left
;
root
.
top
=
top
;
root
.
right
=
right
;
root
.
bottom
=
bottom
;
TestSemanticsUpdate
testSemanticsUpdate
=
root
.
toUpdate
();
testSemanticsUpdate
.
sendUpdateToBridge
(
accessibilityBridge
);
AccessibilityBridge
spyAccessibilityBridge
=
spy
(
accessibilityBridge
);
AccessibilityNodeInfo
mockNodeInfo
=
mock
(
AccessibilityNodeInfo
.
class
);
when
(
spyAccessibilityBridge
.
obtainAccessibilityNodeInfo
(
mockRootView
,
0
))
.
thenReturn
(
mockNodeInfo
);
spyAccessibilityBridge
.
createAccessibilityNodeInfo
(
0
);
verify
(
mockNodeInfo
,
times
(
1
))
.
setBoundsInScreen
(
new
Rect
(
left
+
expectedInsetLeft
,
top
,
right
+
expectedInsetLeft
,
bottom
));
}
@TargetApi
(
28
)
@Test
public
void
itSetCutoutInsetBasedonLayoutModeShortEdges
()
{
int
expectedInsetLeft
=
5
;
int
top
=
0
;
int
left
=
0
;
int
right
=
100
;
int
bottom
=
200
;
AccessibilityViewEmbedder
mockViewEmbedder
=
mock
(
AccessibilityViewEmbedder
.
class
);
AccessibilityManager
mockManager
=
mock
(
AccessibilityManager
.
class
);
View
mockRootView
=
mock
(
View
.
class
);
Activity
context
=
mock
(
Activity
.
class
);
Window
window
=
mock
(
Window
.
class
);
WindowInsets
insets
=
mock
(
WindowInsets
.
class
);
WindowManager
.
LayoutParams
layoutParams
=
new
WindowManager
.
LayoutParams
();
layoutParams
.
layoutInDisplayCutoutMode
=
WindowManager
.
LayoutParams
.
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
;
when
(
mockRootView
.
getContext
()).
thenReturn
(
context
);
when
(
context
.
getWindow
()).
thenReturn
(
window
);
when
(
window
.
getAttributes
()).
thenReturn
(
layoutParams
);
when
(
mockRootView
.
getRootWindowInsets
()).
thenReturn
(
insets
);
when
(
insets
.
getSystemWindowInsetLeft
()).
thenReturn
(
expectedInsetLeft
);
when
(
context
.
getPackageName
()).
thenReturn
(
"test"
);
AccessibilityBridge
accessibilityBridge
=
setUpBridge
(
mockRootView
,
mockManager
,
mockViewEmbedder
);
ViewParent
mockParent
=
mock
(
ViewParent
.
class
);
when
(
mockRootView
.
getParent
()).
thenReturn
(
mockParent
);
when
(
mockManager
.
isEnabled
()).
thenReturn
(
true
);
TestSemanticsNode
root
=
new
TestSemanticsNode
();
root
.
id
=
0
;
root
.
left
=
left
;
root
.
top
=
top
;
root
.
right
=
right
;
root
.
bottom
=
bottom
;
TestSemanticsUpdate
testSemanticsUpdate
=
root
.
toUpdate
();
testSemanticsUpdate
.
sendUpdateToBridge
(
accessibilityBridge
);
AccessibilityBridge
spyAccessibilityBridge
=
spy
(
accessibilityBridge
);
AccessibilityNodeInfo
mockNodeInfo
=
mock
(
AccessibilityNodeInfo
.
class
);
when
(
spyAccessibilityBridge
.
obtainAccessibilityNodeInfo
(
mockRootView
,
0
))
.
thenReturn
(
mockNodeInfo
);
spyAccessibilityBridge
.
createAccessibilityNodeInfo
(
0
);
// Does not apply left inset if the layout mode is `short edges`.
verify
(
mockNodeInfo
,
times
(
1
)).
setBoundsInScreen
(
new
Rect
(
left
,
top
,
right
,
bottom
));
}
@TargetApi
(
30
)
@Test
public
void
itSetCutoutInsetBasedonLayoutModeAlways
()
{
int
expectedInsetLeft
=
5
;
int
top
=
0
;
int
left
=
0
;
int
right
=
100
;
int
bottom
=
200
;
AccessibilityViewEmbedder
mockViewEmbedder
=
mock
(
AccessibilityViewEmbedder
.
class
);
AccessibilityManager
mockManager
=
mock
(
AccessibilityManager
.
class
);
View
mockRootView
=
mock
(
View
.
class
);
Activity
context
=
mock
(
Activity
.
class
);
Window
window
=
mock
(
Window
.
class
);
WindowInsets
insets
=
mock
(
WindowInsets
.
class
);
WindowManager
.
LayoutParams
layoutParams
=
new
WindowManager
.
LayoutParams
();
layoutParams
.
layoutInDisplayCutoutMode
=
WindowManager
.
LayoutParams
.
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
;
when
(
mockRootView
.
getContext
()).
thenReturn
(
context
);
when
(
context
.
getWindow
()).
thenReturn
(
window
);
when
(
window
.
getAttributes
()).
thenReturn
(
layoutParams
);
when
(
mockRootView
.
getRootWindowInsets
()).
thenReturn
(
insets
);
when
(
insets
.
getSystemWindowInsetLeft
()).
thenReturn
(
expectedInsetLeft
);
when
(
context
.
getPackageName
()).
thenReturn
(
"test"
);
AccessibilityBridge
accessibilityBridge
=
setUpBridge
(
mockRootView
,
mockManager
,
mockViewEmbedder
);
ViewParent
mockParent
=
mock
(
ViewParent
.
class
);
when
(
mockRootView
.
getParent
()).
thenReturn
(
mockParent
);
when
(
mockManager
.
isEnabled
()).
thenReturn
(
true
);
TestSemanticsNode
root
=
new
TestSemanticsNode
();
root
.
id
=
0
;
root
.
left
=
left
;
root
.
top
=
top
;
root
.
right
=
right
;
root
.
bottom
=
bottom
;
TestSemanticsUpdate
testSemanticsUpdate
=
root
.
toUpdate
();
testSemanticsUpdate
.
sendUpdateToBridge
(
accessibilityBridge
);
AccessibilityBridge
spyAccessibilityBridge
=
spy
(
accessibilityBridge
);
AccessibilityNodeInfo
mockNodeInfo
=
mock
(
AccessibilityNodeInfo
.
class
);
when
(
spyAccessibilityBridge
.
obtainAccessibilityNodeInfo
(
mockRootView
,
0
))
.
thenReturn
(
mockNodeInfo
);
spyAccessibilityBridge
.
createAccessibilityNodeInfo
(
0
);
// Does not apply left inset if the layout mode is `always`.
verify
(
mockNodeInfo
,
times
(
1
)).
setBoundsInScreen
(
new
Rect
(
left
,
top
,
right
,
bottom
));
}
@Test
public
void
itIgnoresUnfocusableNodeDuringHitTest
()
{
AccessibilityViewEmbedder
mockViewEmbedder
=
mock
(
AccessibilityViewEmbedder
.
class
);
...
...
@@ -1235,6 +1433,13 @@ public class AccessibilityBridgeTest {
float
top
=
0.0f
;
float
right
=
0.0f
;
float
bottom
=
0.0f
;
float
[]
transform
=
new
float
[]
{
1.0f
,
0.0f
,
0.0f
,
0.0f
,
0.0f
,
1.0f
,
0.0f
,
0.0f
,
0.0f
,
0.0f
,
1.0f
,
0.0f
,
0.0f
,
0.0f
,
0.0f
,
1.0f
};
final
List
<
TestSemanticsNode
>
children
=
new
ArrayList
<
TestSemanticsNode
>();
public
void
addChild
(
TestSemanticsNode
child
)
{
...
...
@@ -1281,7 +1486,7 @@ public class AccessibilityBridgeTest {
bytes
.
putFloat
(
bottom
);
// transform.
for
(
int
i
=
0
;
i
<
16
;
i
++)
{
bytes
.
putFloat
(
0
);
bytes
.
putFloat
(
transform
[
i
]
);
}
// children in traversal order.
bytes
.
putInt
(
children
.
size
());
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录