Support dragging native platform views (flutter/engine#21396)

This commit is contained in:
Emmanuel Garcia 2020-09-25 17:46:34 -07:00 committed by GitHub
parent f7bbb7d405
commit dbca16555e
4 changed files with 103 additions and 4 deletions

View File

@ -439,6 +439,7 @@ action("robolectric_tests") {
"test/io/flutter/embedding/engine/dart/DartExecutorTest.java",
"test/io/flutter/embedding/engine/loader/ApplicationInfoLoaderTest.java",
"test/io/flutter/embedding/engine/loader/FlutterLoaderTest.java",
"test/io/flutter/embedding/engine/mutatorsstack/FlutterMutatorViewTest.java",
"test/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistryTest.java",
"test/io/flutter/embedding/engine/renderer/FlutterRendererTest.java",
"test/io/flutter/embedding/engine/systemchannels/KeyEventChannelTest.java",

View File

@ -19,6 +19,8 @@ public class FlutterMutatorView extends FrameLayout {
private float screenDensity;
private int left;
private int top;
private int prevLeft;
private int prevTop;
private final AndroidTouchProcessor androidTouchProcessor;
@ -122,11 +124,26 @@ public class FlutterMutatorView extends FrameLayout {
return super.onTouchEvent(event);
}
// Mutator view itself doesn't rotate, scale, skew, etc.
// we only need to account for translation.
Matrix screenMatrix = new Matrix();
screenMatrix.postTranslate(left, top);
final Matrix screenMatrix = new Matrix();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
prevLeft = left;
prevTop = top;
screenMatrix.postTranslate(left, top);
break;
case MotionEvent.ACTION_MOVE:
// While the view is dragged, use the left and top positions as
// they were at the moment the touch event fired.
screenMatrix.postTranslate(prevLeft, prevTop);
prevLeft = left;
prevTop = top;
break;
case MotionEvent.ACTION_UP:
default:
screenMatrix.postTranslate(left, top);
break;
}
return androidTouchProcessor.onTouchEvent(event, screenMatrix);
}
}

View File

@ -18,6 +18,7 @@ import io.flutter.embedding.engine.LocalizationPluginTest;
import io.flutter.embedding.engine.RenderingComponentTest;
import io.flutter.embedding.engine.loader.ApplicationInfoLoaderTest;
import io.flutter.embedding.engine.loader.FlutterLoaderTest;
import io.flutter.embedding.engine.mutatorsstack.FlutterMutatorViewTest;
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistryTest;
import io.flutter.embedding.engine.renderer.FlutterRendererTest;
import io.flutter.embedding.engine.systemchannels.KeyEventChannelTest;
@ -60,6 +61,7 @@ import test.io.flutter.embedding.engine.dart.DartExecutorTest;
FlutterJNITest.class,
FlutterLaunchTests.class,
FlutterLoaderTest.class,
FlutterMutatorViewTest.class,
FlutterShellArgsTest.class,
FlutterRendererTest.class,
FlutterShellArgsTest.class,

View File

@ -0,0 +1,79 @@
package io.flutter.embedding.engine.mutatorsstack;
import static junit.framework.TestCase.*;
import static org.mockito.Mockito.*;
import android.graphics.Matrix;
import android.view.MotionEvent;
import io.flutter.embedding.android.AndroidTouchProcessor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@Config(manifest = Config.NONE)
@RunWith(RobolectricTestRunner.class)
public class FlutterMutatorViewTest {
@Test
public void canDragViews() {
final AndroidTouchProcessor touchProcessor = mock(AndroidTouchProcessor.class);
final FlutterMutatorView view =
new FlutterMutatorView(RuntimeEnvironment.systemContext, 1.0f, touchProcessor);
final FlutterMutatorsStack mutatorStack = mock(FlutterMutatorsStack.class);
assertTrue(view.onInterceptTouchEvent(mock(MotionEvent.class)));
{
view.readyToDisplay(mutatorStack, /*left=*/ 1, /*top=*/ 2, /*width=*/ 0, /*height=*/ 0);
view.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0));
final ArgumentCaptor<Matrix> matrixCaptor = ArgumentCaptor.forClass(Matrix.class);
verify(touchProcessor).onTouchEvent(any(), matrixCaptor.capture());
final Matrix screenMatrix = new Matrix();
screenMatrix.postTranslate(1, 2);
assertTrue(matrixCaptor.getValue().equals(screenMatrix));
}
reset(touchProcessor);
{
view.readyToDisplay(mutatorStack, /*left=*/ 3, /*top=*/ 4, /*width=*/ 0, /*height=*/ 0);
view.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0.0f, 0.0f, 0));
final ArgumentCaptor<Matrix> matrixCaptor = ArgumentCaptor.forClass(Matrix.class);
verify(touchProcessor).onTouchEvent(any(), matrixCaptor.capture());
final Matrix screenMatrix = new Matrix();
screenMatrix.postTranslate(1, 2);
assertTrue(matrixCaptor.getValue().equals(screenMatrix));
}
reset(touchProcessor);
{
view.readyToDisplay(mutatorStack, /*left=*/ 5, /*top=*/ 6, /*width=*/ 0, /*height=*/ 0);
view.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0.0f, 0.0f, 0));
final ArgumentCaptor<Matrix> matrixCaptor = ArgumentCaptor.forClass(Matrix.class);
verify(touchProcessor).onTouchEvent(any(), matrixCaptor.capture());
final Matrix screenMatrix = new Matrix();
screenMatrix.postTranslate(3, 4);
assertTrue(matrixCaptor.getValue().equals(screenMatrix));
}
reset(touchProcessor);
{
view.readyToDisplay(mutatorStack, /*left=*/ 7, /*top=*/ 8, /*width=*/ 0, /*height=*/ 0);
view.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0));
final ArgumentCaptor<Matrix> matrixCaptor = ArgumentCaptor.forClass(Matrix.class);
verify(touchProcessor).onTouchEvent(any(), matrixCaptor.capture());
final Matrix screenMatrix = new Matrix();
screenMatrix.postTranslate(7, 8);
assertTrue(matrixCaptor.getValue().equals(screenMatrix));
}
}
}