我有一个带有像这样的项目的RecyclerView:
我使用ItemTouchHelper.SimpleCallback
来监听swipe,并使用onChildDraw()在刷子项时绘制画布:
再刷一下:
我想在项目列表中的第一个项目上模拟滑动(在运行时);我需要在X轴上(或多或少)-100像素的第一个项目,然后回到原始位置。怎么做到这一点?
答案 0 :(得分:2)
我创建了一些实用程序方法,以防有人需要
import android.animation.ValueAnimator
import android.os.SystemClock
import android.view.MotionEvent
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
/**
* @author Oleh Haidaienko
* @since 29.07.2020
*/
object SwipeUtils {
/**
* Programmatically swipe RecyclerView item
* @param recyclerView RecyclerView which item will be swiped
* @param index Position of item
* @param distance Swipe distance
* @param direction Swipe direction, can be [ItemTouchHelper.START] or [ItemTouchHelper.END]
* @param time Animation time in milliseconds
*/
fun swipeRecyclerViewItem(
recyclerView: RecyclerView,
index: Int,
distance: Int,
direction: Int,
time: Long
) {
val childView = recyclerView.getChildAt(index) ?: return
val x = childView.width / 2F
val viewLocation = IntArray(2)
childView.getLocationInWindow(viewLocation)
val y = (viewLocation[1] + childView.height) / 2F
val downTime = SystemClock.uptimeMillis()
recyclerView.dispatchTouchEvent(
MotionEvent.obtain(
downTime,
downTime,
MotionEvent.ACTION_DOWN,
x,
y,
0
)
)
ValueAnimator.ofInt(0, distance).apply {
duration = time
addUpdateListener {
val dX = it.animatedValue as Int
val mX = when (direction) {
ItemTouchHelper.END -> x + dX
ItemTouchHelper.START -> x - dX
else -> 0F
}
recyclerView.dispatchTouchEvent(
MotionEvent.obtain(
downTime,
SystemClock.uptimeMillis(),
MotionEvent.ACTION_MOVE,
mX,
y,
0
)
)
}
}.start()
}
}
答案 1 :(得分:0)
我想您可以通过RecyclerView
为DataObserver
注册Adapter
来实现这一目标, adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override public void onChanged() {
super.onChanged();
adapter.unregisterAdapterDataObserver(this);//unregister the adapter since no longer needed.
}
});
会在项目被删除,插入或更改时通知您。让我们考虑一下这个场景
recyclerView.getChildAt(0).translateX(-100);
上面代码中的会在插入项目后通知您,然后您可以使用recyclerView.getChildAt(0).translateX(0);
来模拟滑动,只需reposition
X
view
onChanged()
{ {1}}返回方法{{1}}。
答案 2 :(得分:0)
此扩展功能可以为您提供帮助:
fun ViewGroup.performSwipeToLeft(target: View, distance: Float) {
this.performSwipe(target, distanceX = -distance, distanceY = 0f)
}
fun ViewGroup.performSwipeToRight(target: View, distance: Float) {
this.performSwipe(target, distanceX = +distance, distanceY = 0f)
}
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
}
)
}
在您的情况下,您可以按以下方式使用它:
recylerView.performSwipeToLeft(recyclerView.getChildAt(0), 100f)