自定义垂直 viewpager 不适用于子视图上的 onClick 侦听器
Custom vertical viewpager not work with onClick listener on a child view
我从这里创建了这个自定义 ViewPager (Android: Vertical ViewPager):
class VerticalViewPager : ViewPager {
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null)
: super(context, attrs){
setPageTransformer(false, DefaultTransformer())
overScrollMode = OVER_SCROLL_NEVER
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
val intercepted = super.onInterceptTouchEvent(swapXY(ev))
swapXY(ev) // return touch coordinates to original reference frame for any child views
return intercepted
}
override fun onTouchEvent(ev: MotionEvent?): Boolean {
return super.onTouchEvent(ev)
}
/**
* Swaps the X and Y coordinates of your touch event.
*/
private fun swapXY(ev: MotionEvent): MotionEvent {
val width = width.toFloat()
val height = height.toFloat()
val newX = ev.y / height * width
val newY = ev.x / width * height
ev.setLocation(newX, newY)
return ev
}
private class VerticalPageTransformer : ViewPager.PageTransformer{
override fun transformPage(view: View, position: Float) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.alpha = 0f
} else if (position <= 1) { // [-1,1]
view.alpha = 1f
// Counteract the default slide transition
view.translationX = view.getWidth() * -position
//set Y position to swipe in from top
val yPosition = position * view.getHeight()
view.translationY = yPosition
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.alpha = 0f
}
}
}
}
我使用一个适配器在每个页面中加载一个 ImageView。这个 ImageView 有一个 onClickListener。
open class VerticalViewPagerAdapter(var mContext: Context, val photos : RealmList<ProfilePhoto>?, onPhotoClick: OnPhotoClick?) : PagerAdapter() {
var mLayoutInflater : LayoutInflater? = null
val onPhotoListener = onPhotoClick
init {
mLayoutInflater = mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
}
override fun getCount(): Int {
return photos?.size!!
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view === `object` as FrameLayout
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val itemView = mLayoutInflater?.inflate(R.layout.view_image_profile_viewpager_item, container, false)
val imageView = itemView?.findViewById(R.id.profileImageItemIv) as ImageView
imageView.setOnClickListener{
onPhotoListener?.onPhotoClick(position)
}
imageView.loadUrlImage(photos!![position]?.photo)
container.addView(itemView)
return itemView
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as FrameLayout)
}
}
如果 ImageView 有此侦听器,则自定义 viewpager 上的滑动将不起作用。如果我删除监听器,工作正常。
有人知道可能是什么问题吗?
我终于解决了这个问题。如果用户只点击 viewpager 而不是交换,我将向 onInterceptTouchEvent 添加逻辑以释放 onTouch 事件。这是最终代码:
class VerticalViewPager : ViewPager {
var originalPosY = 0
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null)
: super(context, attrs){
setPageTransformer(false, DefaultTransformer())
}
private fun swapTouchEvent(event: MotionEvent): MotionEvent {
val width = width.toFloat()
val height = height.toFloat()
val swappedX = event.y / height * width
val swappedY = event.x / width * height
event.setLocation(swappedX, swappedY)
return event
}
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
var y : Int = event.rawY.toInt()
return when (event.action) {
MotionEvent.ACTION_DOWN -> {
originalPosY = y
val intercept = super.onInterceptTouchEvent(swapTouchEvent(event))
swapTouchEvent(event)
false
}
MotionEvent.ACTION_MOVE -> {
val intercept = super.onInterceptTouchEvent(swapTouchEvent(event))
val i = swapTouchEvent(event)
true
}
MotionEvent.ACTION_UP -> {
if (Math.abs(originalPosY - y) > 10) {
super.onInterceptTouchEvent(swapTouchEvent(event))
val i = swapTouchEvent(event)
true
}else
false
}
else -> super.onInterceptTouchEvent(swapTouchEvent(event))
}
}
override fun onTouchEvent(event: MotionEvent): Boolean = super.onTouchEvent(swapTouchEvent(event))
}
结果并不完全如我所愿。如果有人可以改进,欢迎
我从这里创建了这个自定义 ViewPager (Android: Vertical ViewPager):
class VerticalViewPager : ViewPager {
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null)
: super(context, attrs){
setPageTransformer(false, DefaultTransformer())
overScrollMode = OVER_SCROLL_NEVER
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
val intercepted = super.onInterceptTouchEvent(swapXY(ev))
swapXY(ev) // return touch coordinates to original reference frame for any child views
return intercepted
}
override fun onTouchEvent(ev: MotionEvent?): Boolean {
return super.onTouchEvent(ev)
}
/**
* Swaps the X and Y coordinates of your touch event.
*/
private fun swapXY(ev: MotionEvent): MotionEvent {
val width = width.toFloat()
val height = height.toFloat()
val newX = ev.y / height * width
val newY = ev.x / width * height
ev.setLocation(newX, newY)
return ev
}
private class VerticalPageTransformer : ViewPager.PageTransformer{
override fun transformPage(view: View, position: Float) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.alpha = 0f
} else if (position <= 1) { // [-1,1]
view.alpha = 1f
// Counteract the default slide transition
view.translationX = view.getWidth() * -position
//set Y position to swipe in from top
val yPosition = position * view.getHeight()
view.translationY = yPosition
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.alpha = 0f
}
}
}
}
我使用一个适配器在每个页面中加载一个 ImageView。这个 ImageView 有一个 onClickListener。
open class VerticalViewPagerAdapter(var mContext: Context, val photos : RealmList<ProfilePhoto>?, onPhotoClick: OnPhotoClick?) : PagerAdapter() {
var mLayoutInflater : LayoutInflater? = null
val onPhotoListener = onPhotoClick
init {
mLayoutInflater = mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
}
override fun getCount(): Int {
return photos?.size!!
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view === `object` as FrameLayout
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val itemView = mLayoutInflater?.inflate(R.layout.view_image_profile_viewpager_item, container, false)
val imageView = itemView?.findViewById(R.id.profileImageItemIv) as ImageView
imageView.setOnClickListener{
onPhotoListener?.onPhotoClick(position)
}
imageView.loadUrlImage(photos!![position]?.photo)
container.addView(itemView)
return itemView
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as FrameLayout)
}
}
如果 ImageView 有此侦听器,则自定义 viewpager 上的滑动将不起作用。如果我删除监听器,工作正常。
有人知道可能是什么问题吗?
我终于解决了这个问题。如果用户只点击 viewpager 而不是交换,我将向 onInterceptTouchEvent 添加逻辑以释放 onTouch 事件。这是最终代码:
class VerticalViewPager : ViewPager {
var originalPosY = 0
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null)
: super(context, attrs){
setPageTransformer(false, DefaultTransformer())
}
private fun swapTouchEvent(event: MotionEvent): MotionEvent {
val width = width.toFloat()
val height = height.toFloat()
val swappedX = event.y / height * width
val swappedY = event.x / width * height
event.setLocation(swappedX, swappedY)
return event
}
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
var y : Int = event.rawY.toInt()
return when (event.action) {
MotionEvent.ACTION_DOWN -> {
originalPosY = y
val intercept = super.onInterceptTouchEvent(swapTouchEvent(event))
swapTouchEvent(event)
false
}
MotionEvent.ACTION_MOVE -> {
val intercept = super.onInterceptTouchEvent(swapTouchEvent(event))
val i = swapTouchEvent(event)
true
}
MotionEvent.ACTION_UP -> {
if (Math.abs(originalPosY - y) > 10) {
super.onInterceptTouchEvent(swapTouchEvent(event))
val i = swapTouchEvent(event)
true
}else
false
}
else -> super.onInterceptTouchEvent(swapTouchEvent(event))
}
}
override fun onTouchEvent(event: MotionEvent): Boolean = super.onTouchEvent(swapTouchEvent(event))
}
结果并不完全如我所愿。如果有人可以改进,欢迎