Merge "Show border highlight when dragging display" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
50cee5bf76
39
res/drawable/display_block_selection_marker_background.xml
Normal file
39
res/drawable/display_block_selection_marker_background.xml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2025 The Android Open Source Project
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
-->
|
||||||
|
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<!-- Inner border -->
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<stroke
|
||||||
|
android:color="@color/display_topology_background_color"
|
||||||
|
android:width="@dimen/display_block_padding" />
|
||||||
|
<corners android:radius="@dimen/display_block_corner_radius" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<!-- Outer border -->
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<stroke
|
||||||
|
android:color="@color/system_secondary"
|
||||||
|
android:width="@dimen/display_block_highlight_width" />
|
||||||
|
<corners android:radius="@dimen/display_block_corner_radius" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
23
res/drawable/display_block_unselected_background.xml
Normal file
23
res/drawable/display_block_unselected_background.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2025 The Android Open Source Project
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
-->
|
||||||
|
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<stroke
|
||||||
|
android:color="@color/display_topology_background_color"
|
||||||
|
android:width="@dimen/display_block_padding" />
|
||||||
|
<corners android:radius="@dimen/display_block_corner_radius" />
|
||||||
|
</shape>
|
@@ -82,5 +82,6 @@
|
|||||||
|
|
||||||
<!-- Connected displays -->
|
<!-- Connected displays -->
|
||||||
<color name="display_topology_background_color">@color/settingslib_color_charcoal</color>
|
<color name="display_topology_background_color">@color/settingslib_color_charcoal</color>
|
||||||
|
<color name="system_secondary">@android:color/system_secondary_dark</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
@@ -224,4 +224,5 @@
|
|||||||
|
|
||||||
<!-- Connected displays -->
|
<!-- Connected displays -->
|
||||||
<color name="display_topology_background_color">@color/settingslib_color_grey100</color>
|
<color name="display_topology_background_color">@color/settingslib_color_grey100</color>
|
||||||
|
<color name="system_secondary">@android:color/system_secondary_light</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
@@ -550,4 +550,7 @@
|
|||||||
|
|
||||||
<!-- Connected displays -->
|
<!-- Connected displays -->
|
||||||
<dimen name="display_topology_pane_margin">24dp</dimen>
|
<dimen name="display_topology_pane_margin">24dp</dimen>
|
||||||
|
<dimen name="display_block_padding">5dp</dimen>
|
||||||
|
<dimen name="display_block_highlight_width">2dp</dimen>
|
||||||
|
<dimen name="display_block_corner_radius">10dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
@@ -20,12 +20,15 @@ import android.app.WallpaperManager
|
|||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Point
|
import android.graphics.Point
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.graphics.drawable.LayerDrawable
|
||||||
import android.hardware.display.DisplayManager
|
import android.hardware.display.DisplayManager
|
||||||
import android.hardware.display.DisplayTopology
|
import android.hardware.display.DisplayTopology
|
||||||
import android.hardware.display.DisplayTopology.TreeNode.POSITION_BOTTOM
|
import android.hardware.display.DisplayTopology.TreeNode.POSITION_BOTTOM
|
||||||
@@ -168,36 +171,54 @@ class TopologyScale(
|
|||||||
|
|
||||||
const val TOPOLOGY_PREFERENCE_KEY = "display_topology_preference"
|
const val TOPOLOGY_PREFERENCE_KEY = "display_topology_preference"
|
||||||
|
|
||||||
/** Padding in pane coordinate pixels on each side of a display block. */
|
|
||||||
const val BLOCK_PADDING = 2f
|
|
||||||
|
|
||||||
/** Represents a draggable block in the topology pane. */
|
/** Represents a draggable block in the topology pane. */
|
||||||
class DisplayBlock(context : Context) : Button(context) {
|
class DisplayBlock(context : Context) : Button(context) {
|
||||||
|
@VisibleForTesting var mSelectedImage: Drawable = ColorDrawable(Color.BLACK)
|
||||||
|
@VisibleForTesting var mUnselectedImage: Drawable = ColorDrawable(Color.BLACK)
|
||||||
|
|
||||||
|
private val mSelectedBg = context.getDrawable(
|
||||||
|
R.drawable.display_block_selection_marker_background)!!
|
||||||
|
private val mUnselectedBg = context.getDrawable(
|
||||||
|
R.drawable.display_block_unselected_background)!!
|
||||||
|
private val mInsetPx = context.resources.getDimensionPixelSize(R.dimen.display_block_padding)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
isScrollContainer = false
|
isScrollContainer = false
|
||||||
isVerticalScrollBarEnabled = false
|
isVerticalScrollBarEnabled = false
|
||||||
isHorizontalScrollBarEnabled = false
|
isHorizontalScrollBarEnabled = false
|
||||||
|
|
||||||
|
// Prevents shadow from appearing around edge of button.
|
||||||
|
stateListAnimator = null
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets position of the block given unpadded coordinates. */
|
/** Sets position of the block given unpadded coordinates. */
|
||||||
fun place(topLeft: PointF) {
|
fun place(topLeft: PointF) {
|
||||||
x = topLeft.x + BLOCK_PADDING
|
x = topLeft.x
|
||||||
y = topLeft.y + BLOCK_PADDING
|
y = topLeft.y
|
||||||
}
|
}
|
||||||
|
|
||||||
val unpaddedX: Float
|
fun setWallpaper(wallpaper: Bitmap?) {
|
||||||
get() = x - BLOCK_PADDING
|
val wallpaperDrawable = BitmapDrawable(context.resources, wallpaper ?: return)
|
||||||
|
|
||||||
val unpaddedY: Float
|
fun framedBy(bg: Drawable): Drawable =
|
||||||
get() = y - BLOCK_PADDING
|
LayerDrawable(arrayOf(wallpaperDrawable, bg)).apply {
|
||||||
|
setLayerInsetRelative(0, mInsetPx, mInsetPx, mInsetPx, mInsetPx)
|
||||||
|
}
|
||||||
|
mSelectedImage = framedBy(mSelectedBg)
|
||||||
|
mUnselectedImage = framedBy(mUnselectedBg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setHighlighted(value: Boolean) {
|
||||||
|
background = if (value) mSelectedImage else mUnselectedImage
|
||||||
|
}
|
||||||
|
|
||||||
/** Sets position and size of the block given unpadded bounds. */
|
/** Sets position and size of the block given unpadded bounds. */
|
||||||
fun placeAndSize(bounds : RectF, scale : TopologyScale) {
|
fun placeAndSize(bounds : RectF, scale : TopologyScale) {
|
||||||
val topLeft = scale.displayToPaneCoor(bounds.left, bounds.top)
|
val topLeft = scale.displayToPaneCoor(bounds.left, bounds.top)
|
||||||
val bottomRight = scale.displayToPaneCoor(bounds.right, bounds.bottom)
|
val bottomRight = scale.displayToPaneCoor(bounds.right, bounds.bottom)
|
||||||
val layout = layoutParams
|
val layout = layoutParams
|
||||||
layout.width = (bottomRight.x - topLeft.x - BLOCK_PADDING * 2f).toInt()
|
layout.width = (bottomRight.x - topLeft.x).toInt()
|
||||||
layout.height = (bottomRight.y - topLeft.y - BLOCK_PADDING * 2f).toInt()
|
layout.height = (bottomRight.y - topLeft.y).toInt()
|
||||||
layoutParams = layout
|
layoutParams = layout
|
||||||
place(topLeft)
|
place(topLeft)
|
||||||
}
|
}
|
||||||
@@ -284,8 +305,8 @@ class DisplayTopologyPreference(context : Context)
|
|||||||
get() = displayManager.displayTopology
|
get() = displayManager.displayTopology
|
||||||
set(value) { displayManager.displayTopology = value }
|
set(value) { displayManager.displayTopology = value }
|
||||||
|
|
||||||
open val wallpaper : Drawable
|
open val wallpaper: Bitmap?
|
||||||
get() = WallpaperManager.getInstance(context).drawable ?: ColorDrawable(Color.BLACK)
|
get() = WallpaperManager.getInstance(context).bitmap
|
||||||
|
|
||||||
open fun registerTopologyListener(listener: Consumer<DisplayTopology>) {
|
open fun registerTopologyListener(listener: Consumer<DisplayTopology>) {
|
||||||
displayManager.registerTopologyListener(context.mainExecutor, listener)
|
displayManager.registerTopologyListener(context.mainExecutor, listener)
|
||||||
@@ -386,14 +407,20 @@ class DisplayTopologyPreference(context : Context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var wallpaperBitmap : Bitmap? = null
|
||||||
|
|
||||||
newBounds.forEach { (id, pos) ->
|
newBounds.forEach { (id, pos) ->
|
||||||
val block = recycleableBlocks.removeFirstOrNull() ?: DisplayBlock(context).apply {
|
val block = recycleableBlocks.removeFirstOrNull() ?: DisplayBlock(context).apply {
|
||||||
|
if (wallpaperBitmap == null) {
|
||||||
|
wallpaperBitmap = injector.wallpaper
|
||||||
|
}
|
||||||
// We need a separate wallpaper Drawable for each display block, since each needs to
|
// We need a separate wallpaper Drawable for each display block, since each needs to
|
||||||
// be drawn at a separate size.
|
// be drawn at a separate size.
|
||||||
background = injector.wallpaper
|
setWallpaper(wallpaperBitmap)
|
||||||
|
|
||||||
mPaneContent.addView(this)
|
mPaneContent.addView(this)
|
||||||
}
|
}
|
||||||
|
block.setHighlighted(false)
|
||||||
|
|
||||||
block.placeAndSize(pos, scaling)
|
block.placeAndSize(pos, scaling)
|
||||||
block.setOnTouchListener { view, ev ->
|
block.setOnTouchListener { view, ev ->
|
||||||
@@ -422,12 +449,15 @@ class DisplayTopologyPreference(context : Context)
|
|||||||
|
|
||||||
val stationaryDisps = positions.filter { it.first != displayId }
|
val stationaryDisps = positions.filter { it.first != displayId }
|
||||||
|
|
||||||
|
mDrag?.display?.setHighlighted(false)
|
||||||
|
block.setHighlighted(true)
|
||||||
|
|
||||||
// We have to use rawX and rawY for the coordinates since the view receiving the event is
|
// We have to use rawX and rawY for the coordinates since the view receiving the event is
|
||||||
// also the view that is moving. We need coordinates relative to something that isn't
|
// also the view that is moving. We need coordinates relative to something that isn't
|
||||||
// moving, and the raw coordinates are relative to the screen.
|
// moving, and the raw coordinates are relative to the screen.
|
||||||
mDrag = BlockDrag(
|
mDrag = BlockDrag(
|
||||||
stationaryDisps.toList(), block, displayId, displayPos.width(), displayPos.height(),
|
stationaryDisps.toList(), block, displayId, displayPos.width(), displayPos.height(),
|
||||||
ev.rawX - block.unpaddedX, ev.rawY - block.unpaddedY)
|
ev.rawX - block.x, ev.rawY - block.y)
|
||||||
|
|
||||||
// Prevents a container of this view from intercepting the touch events in the case the
|
// Prevents a container of this view from intercepting the touch events in the case the
|
||||||
// pointer moves outside of the display block or the pane.
|
// pointer moves outside of the display block or the pane.
|
||||||
@@ -454,9 +484,10 @@ class DisplayTopologyPreference(context : Context)
|
|||||||
val drag = mDrag ?: return false
|
val drag = mDrag ?: return false
|
||||||
val topology = mTopologyInfo ?: return false
|
val topology = mTopologyInfo ?: return false
|
||||||
mPaneContent.requestDisallowInterceptTouchEvent(false)
|
mPaneContent.requestDisallowInterceptTouchEvent(false)
|
||||||
|
drag.display.setHighlighted(false)
|
||||||
|
|
||||||
val newCoor = topology.scaling.paneToDisplayCoor(
|
val newCoor = topology.scaling.paneToDisplayCoor(
|
||||||
drag.display.unpaddedX, drag.display.unpaddedY)
|
drag.display.x, drag.display.y)
|
||||||
val newTopology = topology.topology.copy()
|
val newTopology = topology.topology.copy()
|
||||||
val newPositions = drag.stationaryDisps.map { (id, pos) -> id to PointF(pos.left, pos.top) }
|
val newPositions = drag.stationaryDisps.map { (id, pos) -> id to PointF(pos.left, pos.top) }
|
||||||
.plus(drag.displayId to newCoor)
|
.plus(drag.displayId to newCoor)
|
||||||
|
@@ -21,9 +21,9 @@ import android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT
|
|||||||
import android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP
|
import android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.ColorDrawable
|
|
||||||
import android.hardware.display.DisplayTopology
|
import android.hardware.display.DisplayTopology
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -50,7 +50,8 @@ class DisplayTopologyPreferenceTest {
|
|||||||
val injector = TestInjector(context)
|
val injector = TestInjector(context)
|
||||||
val rootView = View.inflate(context, preference.layoutResource, /*parent=*/ null)
|
val rootView = View.inflate(context, preference.layoutResource, /*parent=*/ null)
|
||||||
val holder = PreferenceViewHolder.createInstanceForTests(rootView)
|
val holder = PreferenceViewHolder.createInstanceForTests(rootView)
|
||||||
val wallpaper = ColorDrawable(Color.MAGENTA)
|
val wallpaper = Bitmap.createBitmap(
|
||||||
|
intArrayOf(Color.MAGENTA), /*width=*/ 1, /*height=*/ 1, Bitmap.Config.RGB_565)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
preference.injector = injector
|
preference.injector = injector
|
||||||
@@ -60,14 +61,14 @@ class DisplayTopologyPreferenceTest {
|
|||||||
|
|
||||||
class TestInjector(context : Context) : DisplayTopologyPreference.Injector(context) {
|
class TestInjector(context : Context) : DisplayTopologyPreference.Injector(context) {
|
||||||
var topology: DisplayTopology? = null
|
var topology: DisplayTopology? = null
|
||||||
var systemWallpaper: Drawable? = null
|
var systemWallpaper: Bitmap? = null
|
||||||
var topologyListener: Consumer<DisplayTopology>? = null
|
var topologyListener: Consumer<DisplayTopology>? = null
|
||||||
|
|
||||||
override var displayTopology : DisplayTopology?
|
override var displayTopology : DisplayTopology?
|
||||||
get() = topology
|
get() = topology
|
||||||
set(value) { topology = value }
|
set(value) { topology = value }
|
||||||
|
|
||||||
override val wallpaper : Drawable
|
override val wallpaper: Bitmap?
|
||||||
get() = systemWallpaper!!
|
get() = systemWallpaper!!
|
||||||
|
|
||||||
override fun registerTopologyListener(listener: Consumer<DisplayTopology>) {
|
override fun registerTopologyListener(listener: Consumer<DisplayTopology>) {
|
||||||
@@ -164,14 +165,14 @@ class DisplayTopologyPreferenceTest {
|
|||||||
val (childBlock, rootBlock) = setupTwoDisplays()
|
val (childBlock, rootBlock) = setupTwoDisplays()
|
||||||
|
|
||||||
// After accounting for padding, child should be half the length of root in each dimension.
|
// After accounting for padding, child should be half the length of root in each dimension.
|
||||||
assertThat(childBlock.layoutParams.width + BLOCK_PADDING)
|
assertThat(childBlock.layoutParams.width)
|
||||||
.isEqualTo(rootBlock.layoutParams.width / 2)
|
.isEqualTo(rootBlock.layoutParams.width / 2)
|
||||||
assertThat(childBlock.layoutParams.height + BLOCK_PADDING)
|
assertThat(childBlock.layoutParams.height)
|
||||||
.isEqualTo(rootBlock.layoutParams.height / 2)
|
.isEqualTo(rootBlock.layoutParams.height / 2)
|
||||||
assertThat(childBlock.y).isGreaterThan(rootBlock.y)
|
assertThat(childBlock.y).isGreaterThan(rootBlock.y)
|
||||||
assertThat(childBlock.background).isEqualTo(wallpaper)
|
assertThat(childBlock.background).isEqualTo(childBlock.mUnselectedImage)
|
||||||
assertThat(rootBlock.background).isEqualTo(wallpaper)
|
assertThat(rootBlock.background).isEqualTo(rootBlock.mUnselectedImage)
|
||||||
assertThat(rootBlock.x - BLOCK_PADDING * 2)
|
assertThat(rootBlock.x)
|
||||||
.isEqualTo(childBlock.x + childBlock.layoutParams.width)
|
.isEqualTo(childBlock.x + childBlock.layoutParams.width)
|
||||||
|
|
||||||
assertThat(preference.mTopologyHint.text)
|
assertThat(preference.mTopologyHint.text)
|
||||||
@@ -180,7 +181,7 @@ class DisplayTopologyPreferenceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun dragDisplayDownward() {
|
fun dragDisplayDownward() {
|
||||||
val (leftBlock, rightBlock) = setupTwoDisplays()
|
val (leftBlock, _) = setupTwoDisplays()
|
||||||
|
|
||||||
val downEvent = MotionEventBuilder.newBuilder()
|
val downEvent = MotionEventBuilder.newBuilder()
|
||||||
.setPointer(0f, 0f)
|
.setPointer(0f, 0f)
|
||||||
@@ -191,7 +192,7 @@ class DisplayTopologyPreferenceTest {
|
|||||||
// coordinates. The original offset is 42, so the new offset will be 42 + 40.
|
// coordinates. The original offset is 42, so the new offset will be 42 + 40.
|
||||||
val moveEvent = MotionEventBuilder.newBuilder()
|
val moveEvent = MotionEventBuilder.newBuilder()
|
||||||
.setAction(MotionEvent.ACTION_MOVE)
|
.setAction(MotionEvent.ACTION_MOVE)
|
||||||
.setPointer(0f, leftBlock.layoutParams.height / 2f + BLOCK_PADDING)
|
.setPointer(0f, leftBlock.layoutParams.height / 2f)
|
||||||
.build()
|
.build()
|
||||||
val upEvent = MotionEventBuilder.newBuilder().setAction(MotionEvent.ACTION_UP).build()
|
val upEvent = MotionEventBuilder.newBuilder().setAction(MotionEvent.ACTION_UP).build()
|
||||||
|
|
||||||
@@ -220,7 +221,7 @@ class DisplayTopologyPreferenceTest {
|
|||||||
val moveEvent = MotionEventBuilder.newBuilder()
|
val moveEvent = MotionEventBuilder.newBuilder()
|
||||||
.setAction(MotionEvent.ACTION_MOVE)
|
.setAction(MotionEvent.ACTION_MOVE)
|
||||||
.setPointer(
|
.setPointer(
|
||||||
-leftBlock.layoutParams.width - 2f * BLOCK_PADDING,
|
-leftBlock.layoutParams.width.toFloat(),
|
||||||
-leftBlock.layoutParams.height / 2f)
|
-leftBlock.layoutParams.height / 2f)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@@ -278,8 +279,8 @@ class DisplayTopologyPreferenceTest {
|
|||||||
// Look for a display with the same unusual aspect ratio as the one we've added.
|
// Look for a display with the same unusual aspect ratio as the one we've added.
|
||||||
val expectedAspectRatio = 300f/320f
|
val expectedAspectRatio = 300f/320f
|
||||||
assertThat(paneChildren
|
assertThat(paneChildren
|
||||||
.map { (it.layoutParams.width.toFloat() + BLOCK_PADDING*2) /
|
.map { it.layoutParams.width.toFloat() /
|
||||||
(it.layoutParams.height.toFloat() + BLOCK_PADDING*2) }
|
it.layoutParams.height.toFloat() }
|
||||||
.filter { abs(it - expectedAspectRatio) < 0.001f }
|
.filter { abs(it - expectedAspectRatio) < 0.001f }
|
||||||
).hasSize(1)
|
).hasSize(1)
|
||||||
}
|
}
|
||||||
@@ -305,7 +306,7 @@ class DisplayTopologyPreferenceTest {
|
|||||||
assertThat(paneChildren).hasSize(1)
|
assertThat(paneChildren).hasSize(1)
|
||||||
val block = paneChildren[0]
|
val block = paneChildren[0]
|
||||||
|
|
||||||
val origY = block.unpaddedY
|
val origY = block.y
|
||||||
|
|
||||||
block.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
block.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
||||||
.setAction(MotionEvent.ACTION_DOWN)
|
.setAction(MotionEvent.ACTION_DOWN)
|
||||||
@@ -316,21 +317,21 @@ class DisplayTopologyPreferenceTest {
|
|||||||
.setPointer(0f, 30f)
|
.setPointer(0f, 30f)
|
||||||
.build())
|
.build())
|
||||||
|
|
||||||
assertThat(block.unpaddedY).isWithin(0.01f).of(origY)
|
assertThat(block.y).isWithin(0.01f).of(origY)
|
||||||
|
|
||||||
block.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
block.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
||||||
.setAction(MotionEvent.ACTION_UP)
|
.setAction(MotionEvent.ACTION_UP)
|
||||||
.build())
|
.build())
|
||||||
|
|
||||||
// Block should be back to original position.
|
// Block should be back to original position.
|
||||||
assertThat(block.unpaddedY).isWithin(0.01f).of(origY)
|
assertThat(block.y).isWithin(0.01f).of(origY)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun updatedTopologyCancelsDragIfNonTrivialChange() {
|
fun updatedTopologyCancelsDragIfNonTrivialChange() {
|
||||||
val (leftBlock, rightBlock) = setupTwoDisplays(POSITION_LEFT, /* childOffset= */ 42f)
|
val (leftBlock, _) = setupTwoDisplays(POSITION_LEFT, /* childOffset= */ 42f)
|
||||||
|
|
||||||
assertThat(leftBlock.unpaddedY).isWithin(0.01f).of(142.17f)
|
assertThat(leftBlock.y).isWithin(0.01f).of(142.17f)
|
||||||
|
|
||||||
leftBlock.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
leftBlock.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
||||||
.setAction(MotionEvent.ACTION_DOWN)
|
.setAction(MotionEvent.ACTION_DOWN)
|
||||||
@@ -340,29 +341,45 @@ class DisplayTopologyPreferenceTest {
|
|||||||
.setAction(MotionEvent.ACTION_MOVE)
|
.setAction(MotionEvent.ACTION_MOVE)
|
||||||
.setPointer(0f, 30f)
|
.setPointer(0f, 30f)
|
||||||
.build())
|
.build())
|
||||||
assertThat(leftBlock.unpaddedY).isWithin(0.01f).of(172.17f)
|
assertThat(leftBlock.y).isWithin(0.01f).of(172.17f)
|
||||||
|
|
||||||
// Offset is only different by 0.5 dp, so the drag will not cancel.
|
// Offset is only different by 0.5 dp, so the drag will not cancel.
|
||||||
injector.topology = twoDisplayTopology(POSITION_LEFT, /* childOffset= */ 41.5f)
|
injector.topology = twoDisplayTopology(POSITION_LEFT, /* childOffset= */ 41.5f)
|
||||||
injector.topologyListener!!.accept(injector.topology!!)
|
injector.topologyListener!!.accept(injector.topology!!)
|
||||||
|
|
||||||
assertThat(leftBlock.unpaddedY).isWithin(0.01f).of(172.17f)
|
assertThat(leftBlock.y).isWithin(0.01f).of(172.17f)
|
||||||
// Move block farther downward.
|
// Move block farther downward.
|
||||||
leftBlock.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
leftBlock.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
||||||
.setAction(MotionEvent.ACTION_MOVE)
|
.setAction(MotionEvent.ACTION_MOVE)
|
||||||
.setPointer(0f, 50f)
|
.setPointer(0f, 50f)
|
||||||
.build())
|
.build())
|
||||||
assertThat(leftBlock.unpaddedY).isWithin(0.01f).of(192.17f)
|
assertThat(leftBlock.y).isWithin(0.01f).of(192.17f)
|
||||||
|
|
||||||
injector.topology = twoDisplayTopology(POSITION_LEFT, /* childOffset= */ 20f)
|
injector.topology = twoDisplayTopology(POSITION_LEFT, /* childOffset= */ 20f)
|
||||||
injector.topologyListener!!.accept(injector.topology!!)
|
injector.topologyListener!!.accept(injector.topology!!)
|
||||||
|
|
||||||
assertThat(leftBlock.unpaddedY).isWithin(0.01f).of(125.67f)
|
assertThat(leftBlock.y).isWithin(0.01f).of(125.67f)
|
||||||
// Another move in the opposite direction should not move the left block.
|
// Another move in the opposite direction should not move the left block.
|
||||||
leftBlock.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
leftBlock.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
||||||
.setAction(MotionEvent.ACTION_MOVE)
|
.setAction(MotionEvent.ACTION_MOVE)
|
||||||
.setPointer(0f, -20f)
|
.setPointer(0f, -20f)
|
||||||
.build())
|
.build())
|
||||||
assertThat(leftBlock.unpaddedY).isWithin(0.01f).of(125.67f)
|
assertThat(leftBlock.y).isWithin(0.01f).of(125.67f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun highlightDuringDrag() {
|
||||||
|
val (leftBlock, _) = setupTwoDisplays(POSITION_LEFT, /* childOffset= */ 42f)
|
||||||
|
|
||||||
|
assertThat(leftBlock.background).isEqualTo(leftBlock.mUnselectedImage)
|
||||||
|
leftBlock.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
||||||
|
.setAction(MotionEvent.ACTION_DOWN)
|
||||||
|
.setPointer(0f, 0f)
|
||||||
|
.build())
|
||||||
|
assertThat(leftBlock.background).isEqualTo(leftBlock.mSelectedImage)
|
||||||
|
leftBlock.dispatchTouchEvent(MotionEventBuilder.newBuilder()
|
||||||
|
.setAction(MotionEvent.ACTION_UP)
|
||||||
|
.build())
|
||||||
|
assertThat(leftBlock.background).isEqualTo(leftBlock.mUnselectedImage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user