forked from flutter/packages
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[web] Add PointerInterceptor widget (flutter#256)
The widget can be used as a wrapper of any widget that is overlaid on top of a platform view, so it can handle clicks "as expected". More info about usage and testing in the corresponding READMEs!
- Loading branch information
Showing
88 changed files
with
2,063 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Miscellaneous | ||
*.class | ||
*.log | ||
*.pyc | ||
*.swp | ||
.DS_Store | ||
.atom/ | ||
.buildlog/ | ||
.history | ||
.svn/ | ||
|
||
# IntelliJ related | ||
*.iml | ||
*.ipr | ||
*.iws | ||
.idea/ | ||
|
||
# The .vscode folder contains launch configuration and tasks you configure in | ||
# VS Code which you may wish to be included in version control, so this line | ||
# is commented out by default. | ||
#.vscode/ | ||
|
||
# Flutter/Dart/Pub related | ||
**/doc/api/ | ||
.dart_tool/ | ||
.flutter-plugins | ||
.flutter-plugins-dependencies | ||
.packages | ||
.pub-cache/ | ||
.pub/ | ||
build/ | ||
|
||
# Android related | ||
**/android/**/gradle-wrapper.jar | ||
**/android/.gradle | ||
**/android/captures/ | ||
**/android/gradlew | ||
**/android/gradlew.bat | ||
**/android/local.properties | ||
**/android/**/GeneratedPluginRegistrant.java | ||
|
||
# iOS/XCode related | ||
**/ios/**/*.mode1v3 | ||
**/ios/**/*.mode2v3 | ||
**/ios/**/*.moved-aside | ||
**/ios/**/*.pbxuser | ||
**/ios/**/*.perspectivev3 | ||
**/ios/**/*sync/ | ||
**/ios/**/.sconsign.dblite | ||
**/ios/**/.tags* | ||
**/ios/**/.vagrant/ | ||
**/ios/**/DerivedData/ | ||
**/ios/**/Icon? | ||
**/ios/**/Pods/ | ||
**/ios/**/.symlinks/ | ||
**/ios/**/profile | ||
**/ios/**/xcuserdata | ||
**/ios/.generated/ | ||
**/ios/Flutter/App.framework | ||
**/ios/Flutter/Flutter.framework | ||
**/ios/Flutter/Flutter.podspec | ||
**/ios/Flutter/Generated.xcconfig | ||
**/ios/Flutter/app.flx | ||
**/ios/Flutter/app.zip | ||
**/ios/Flutter/flutter_assets/ | ||
**/ios/Flutter/flutter_export_environment.sh | ||
**/ios/ServiceDefinitions.json | ||
**/ios/Runner/GeneratedPluginRegistrant.* | ||
|
||
# Exceptions to above rules. | ||
!**/ios/**/default.mode1v3 | ||
!**/ios/**/default.mode2v3 | ||
!**/ios/**/default.pbxuser | ||
!**/ios/**/default.perspectivev3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# This file tracks properties of this Flutter project. | ||
# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
# | ||
# This file should be version controlled and should not be manually edited. | ||
|
||
version: | ||
revision: e6bd95bc5caa5e34c5b0285a559673984374b7ea | ||
channel: master | ||
|
||
project_type: package |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## 0.8.0 | ||
|
||
* Initial release of the `PointerInterceptor` widget. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Copyright 2019 The Flutter Authors. All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are | ||
met: | ||
|
||
* Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above | ||
copyright notice, this list of conditions and the following | ||
disclaimer in the documentation and/or other materials provided | ||
with the distribution. | ||
* Neither the name of Google Inc. nor the names of its | ||
contributors may be used to endorse or promote products derived | ||
from this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# pointer_interceptor | ||
|
||
`PointerInterceptor` is a widget that prevents mouse events (in web) from being captured by an underlying [`HtmlElementView`](https://api.flutter.dev/flutter/widgets/HtmlElementView-class.html). | ||
|
||
You can use this widget in a cross-platform app freely. In mobile, where the issue that this plugin fixes does not exist, the widget acts as a pass-through of its `children`, without adding anything to the render tree. | ||
|
||
## What is the problem? | ||
|
||
When overlaying Flutter widgets on top of `HtmlElementView` widgets that respond to mouse gestures (handle clicks, for example), the clicks will be consumed by the `HtmlElementView`, and not relayed to Flutter. | ||
|
||
The result is that Flutter widget's `onTap` (and other) handlers won't fire as expected, but they'll affect the underlying webview. | ||
|
||
<center> | ||
|
||
![In the dashed areas, clicks won't work](doc/img/affected-areas.png) | ||
|
||
_In the dashed areas, clicks won't work as expected._ | ||
</center> | ||
|
||
## How does this work? | ||
|
||
`PointerInterceptor` creates a platform view consisting of an empty HTML element. The element has the size of its `child` widget, and is inserted in the layer tree _behind_ its child in paint order. | ||
|
||
This empty platform view doesn't do anything with mouse events, other than preventing them from reaching other platform views underneath it. | ||
|
||
This gives an opportunity to the Flutter framework to handle the click, as expected: | ||
|
||
<center> | ||
|
||
![The PointerInterceptor renders between the flutter element, and the platform view](doc/img/fixed-areas.png) | ||
|
||
_Each `PointerInterceptor` (green) renders between Flutter widgets and the underlying `HtmlElementView`. Clicks work as expected._ | ||
</center> | ||
|
||
|
||
## How to use | ||
|
||
Some common scenarios where this widget may come in handy: | ||
|
||
* [FAB](https://api.flutter.dev/flutter/material/FloatingActionButton-class.html) unclickable in an app that renders a full-screen background Map | ||
* Custom Play/Pause buttons on top of a video element don't work | ||
* Drawer contents not interactive when it overlaps an iframe element | ||
* ... | ||
|
||
All the cases above have in common that they attempt to render Flutter widgets *on top* of platform views that handle pointer events. | ||
|
||
There's two ways that the `PointerInterceptor` widget can be used to solve the problems above: | ||
|
||
1. Wrapping your button element directly (FAB, Custom Play/Pause button...): | ||
|
||
```dart | ||
PointerInterceptor( | ||
child: RaisedButton(...), | ||
) | ||
``` | ||
2. As a root container for a "layout" element, wrapping a bunch of other elements (like a Drawer): | ||
```dart | ||
Scaffold( | ||
... | ||
drawer: PointerInterceptor( | ||
child: Drawer( | ||
child: ... | ||
), | ||
), | ||
... | ||
) | ||
``` | ||
### `debug` | ||
The `PointerInterceptor` widget has a `debug` property, that will render it visibly on the screen (similar to the images above). | ||
This may be useful to see what the widget is actually covering when used as a layout element. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Miscellaneous | ||
*.class | ||
*.log | ||
*.pyc | ||
*.swp | ||
.DS_Store | ||
.atom/ | ||
.buildlog/ | ||
.history | ||
.svn/ | ||
|
||
# IntelliJ related | ||
*.iml | ||
*.ipr | ||
*.iws | ||
.idea/ | ||
|
||
# The .vscode folder contains launch configuration and tasks you configure in | ||
# VS Code which you may wish to be included in version control, so this line | ||
# is commented out by default. | ||
#.vscode/ | ||
|
||
# Flutter/Dart/Pub related | ||
**/doc/api/ | ||
**/ios/Flutter/.last_build_id | ||
.dart_tool/ | ||
.flutter-plugins | ||
.flutter-plugins-dependencies | ||
.packages | ||
.pub-cache/ | ||
.pub/ | ||
/build/ | ||
|
||
# Web related | ||
lib/generated_plugin_registrant.dart | ||
|
||
# Symbolication related | ||
app.*.symbols | ||
|
||
# Obfuscation related | ||
app.*.map.json | ||
|
||
# Android Studio will place build artifacts here | ||
/android/app/debug | ||
/android/app/profile | ||
/android/app/release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# This file tracks properties of this Flutter project. | ||
# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
# | ||
# This file should be version controlled and should not be manually edited. | ||
|
||
version: | ||
revision: e6bd95bc5caa5e34c5b0285a559673984374b7ea | ||
channel: master | ||
|
||
project_type: app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# pointer_interceptor_example | ||
|
||
An example for the PointerInterceptor widget. | ||
|
||
## Getting Started | ||
|
||
`flutter run -d chrome` to run the sample. You can tweak some code in the `lib/main.dart`, but be careful, changes there can break integration tests! | ||
|
||
## Running tests | ||
|
||
`flutter drive --target integration_test/widget_test.dart --driver test_driver/integration_test.dart --show-web-server-device -d web-server` | ||
|
||
The command above will run the integration tests for this package. | ||
|
||
Make sure that you have `chromedriver` running in port `4444`. | ||
|
||
Read more on: [flutter.dev > Docs > Testing & debugging > Integration testing](https://flutter.dev/docs/testing/integration-tests). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
gradle-wrapper.jar | ||
/.gradle | ||
/captures/ | ||
/gradlew | ||
/gradlew.bat | ||
/local.properties | ||
GeneratedPluginRegistrant.java | ||
|
||
# Remember to never publicly share your keystore. | ||
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app | ||
key.properties |
63 changes: 63 additions & 0 deletions
63
packages/pointer_interceptor/example/android/app/build.gradle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
def localProperties = new Properties() | ||
def localPropertiesFile = rootProject.file('local.properties') | ||
if (localPropertiesFile.exists()) { | ||
localPropertiesFile.withReader('UTF-8') { reader -> | ||
localProperties.load(reader) | ||
} | ||
} | ||
|
||
def flutterRoot = localProperties.getProperty('flutter.sdk') | ||
if (flutterRoot == null) { | ||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") | ||
} | ||
|
||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode') | ||
if (flutterVersionCode == null) { | ||
flutterVersionCode = '1' | ||
} | ||
|
||
def flutterVersionName = localProperties.getProperty('flutter.versionName') | ||
if (flutterVersionName == null) { | ||
flutterVersionName = '1.0' | ||
} | ||
|
||
apply plugin: 'com.android.application' | ||
apply plugin: 'kotlin-android' | ||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" | ||
|
||
android { | ||
compileSdkVersion 29 | ||
|
||
sourceSets { | ||
main.java.srcDirs += 'src/main/kotlin' | ||
} | ||
|
||
lintOptions { | ||
disable 'InvalidPackage' | ||
} | ||
|
||
defaultConfig { | ||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). | ||
applicationId "com.example.example" | ||
minSdkVersion 16 | ||
targetSdkVersion 29 | ||
versionCode flutterVersionCode.toInteger() | ||
versionName flutterVersionName | ||
} | ||
|
||
buildTypes { | ||
release { | ||
// TODO: Add your own signing config for the release build. | ||
// Signing with the debug keys for now, so `flutter run --release` works. | ||
signingConfig signingConfigs.debug | ||
} | ||
} | ||
} | ||
|
||
flutter { | ||
source '../..' | ||
} | ||
|
||
dependencies { | ||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/pointer_interceptor/example/android/app/src/debug/AndroidManifest.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="com.example.example"> | ||
<!-- Flutter needs it to communicate with the running application | ||
to allow setting breakpoints, to provide hot reload, etc. | ||
--> | ||
<uses-permission android:name="android.permission.INTERNET"/> | ||
</manifest> |
41 changes: 41 additions & 0 deletions
41
packages/pointer_interceptor/example/android/app/src/main/AndroidManifest.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="com.example.example"> | ||
<application | ||
android:label="example" | ||
android:icon="@mipmap/ic_launcher"> | ||
<activity | ||
android:name=".MainActivity" | ||
android:launchMode="singleTop" | ||
android:theme="@style/LaunchTheme" | ||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" | ||
android:hardwareAccelerated="true" | ||
android:windowSoftInputMode="adjustResize"> | ||
<!-- Specifies an Android theme to apply to this Activity as soon as | ||
the Android process has started. This theme is visible to the user | ||
while the Flutter UI initializes. After that, this theme continues | ||
to determine the Window background behind the Flutter UI. --> | ||
<meta-data | ||
android:name="io.flutter.embedding.android.NormalTheme" | ||
android:resource="@style/NormalTheme" | ||
/> | ||
<!-- Displays an Android View that continues showing the launch screen | ||
Drawable until Flutter paints its first frame, then this splash | ||
screen fades out. A splash screen is useful to avoid any visual | ||
gap between the end of Android's launch screen and the painting of | ||
Flutter's first frame. --> | ||
<meta-data | ||
android:name="io.flutter.embedding.android.SplashScreenDrawable" | ||
android:resource="@drawable/launch_background" | ||
/> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN"/> | ||
<category android:name="android.intent.category.LAUNCHER"/> | ||
</intent-filter> | ||
</activity> | ||
<!-- Don't delete the meta-data below. | ||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> | ||
<meta-data | ||
android:name="flutterEmbedding" | ||
android:value="2" /> | ||
</application> | ||
</manifest> |
Oops, something went wrong.