问题描述
我一直在尝试在Google上找到针对此特定案例的答案,但令人惊讶的是在任何地方都找不到它(这里只是关于检测而不是创建,滑动的答案).我实际上想在屏幕上从右向左模拟"滑动(无关紧要,但最好是从右边缘向左滑动).我尝试过类似的方法,但得到了NPE:
I've been trying to find an answer for this specific case on Google and amazingly couldn't find it anywhere (there's just answers about detecting, not creating, swipes). I want to actually 'run' a simulated swipe from right to left on the screen (doesn't matter where, but ideally from the right edge to the left). I tried something like this, but I get a NPE:
final float viewWidth = view.getWidth();
TouchUtils.drag(null,viewWidth,1f,0f,0f,1);
原因?我需要在没有实际引用页面位置的无限viewpager中强制滑动到下一页(所以我不能只使用setCurrentItem).
The reason? I need to force a swipe to the next page in an infinite viewpager which has no real reference to the page position (so I can't just use setCurrentItem).
有什么想法吗?
推荐答案
如上所述,TouchUtils.drag
使用的Instrumentation
只能在androidTest
中使用.我编写了不需要Instrumentation
的扩展功能,因此可以在发布版本中使用它们:
As already said TouchUtils.drag
uses Instrumentation
that could be used in androidTest
only.I have wrote extension functions that doesn't require Instrumentation
, so they could be used in release build:
fun ViewGroup.performSwipeToLeft(target: View) {
this.performSwipe(target, distanceX = -this.width * .5f, distanceY = 0f)
}
fun ViewGroup.performSwipeToRight(target: View) {
this.performSwipe(target, distanceX = +this.width * .5f, distanceY = 0f)
}
fun ViewGroup.performSwipeToTop(target: View) {
this.performSwipe(target, distanceX = 0f, distanceY = -this.height * .5f)
}
fun ViewGroup.performSwipeToBottom(target: View) {
this.performSwipe(target, distanceX = 0f, distanceY = +this.width * .5f)
}
fun ViewGroup.performSwipe(target: View, distanceX: Float, distanceY: Float) {
val parentCoords = intArrayOf(0, 0)
this.getLocationInWindow(parentCoords)
val childCoords = intArrayOf(0, 0)
target.getLocationInWindow(childCoords)
val initGlobalX = childCoords[0].toFloat() + 1f
val initGlobalY = childCoords[1].toFloat() + 1f
val initLocalX = (childCoords[0] - parentCoords[0]).toFloat() + 1f
val initLocalY = (childCoords[1] - parentCoords[1]).toFloat() + 1f
val downTime = SystemClock.uptimeMillis()
var eventTime = SystemClock.uptimeMillis()
this.dispatchTouchEvent(
MotionEvent.obtain(
downTime,
eventTime,
MotionEvent.ACTION_DOWN,
initGlobalX,
initGlobalY,
0
).apply {
setLocation(initLocalX, initLocalY)
source = InputDevice.SOURCE_TOUCHSCREEN
}
)
val steps = 20
var i = 0
while (i in 0..steps) {
val globalX = initGlobalX + i * distanceX / steps
val globalY = initGlobalY + i * distanceY / steps
val localX = initLocalX + i * distanceX / steps
val localY = initLocalY + i * distanceY / steps
if (globalX <= 10f || globalY <= 10f) {
break
}
this.dispatchTouchEvent(
MotionEvent.obtain(
downTime,
++eventTime,
MotionEvent.ACTION_MOVE,
globalX,
globalY,
0
).apply {
setLocation(localX, localY)
source = InputDevice.SOURCE_TOUCHSCREEN
}
)
i++
}
this.dispatchTouchEvent(
MotionEvent.obtain(
downTime,
++eventTime,
MotionEvent.ACTION_UP,
initGlobalX + i * distanceX,
initGlobalY + i * distanceY,
0
).apply {
setLocation(initLocalX + i * distanceX, initLocalY + i * distanceY)
source = InputDevice.SOURCE_TOUCHSCREEN
}
)
}
要使用它,您需要将当前页面内容作为参数传递,并将viewPager作为此函数的接收者:
To use it you need pass your current page content as an argument, and viewPager as a receiver of this functions:
val viewPager = ...
viewPager.performSwipeToLeft(viewPager.getChildAt(viewPager.currentItem))
这篇关于Android:以编程方式创建滑动手势事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!