I have horizontal recyclerViews in vertical RecyclerView. To scroll horizontally I should swipe from 45 degrees to -45 degree. To scroll vertically from 90 degrees to 45 degrees. Is any possibility to override this?
For example, vertical scroll works only with the swipe from 105 to 75 degrees. Else, horizontal scroll.
You need to create MainVerticalRecyclerView like this:
open class MainVerticalRecyclerView : RecyclerView {
private var scrollPointerId = -1
private var pointTouchX = 0
private var pointTouchY = 0
private var touchSlopType = 0
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
val vc = ViewConfiguration.get(context)
touchSlopType = vc.scaledTouchSlop
}
override fun setScrollingTouchSlop(slopConstant: Int) {
super.setScrollingTouchSlop(slopConstant)
val vc = ViewConfiguration.get(context)
when (slopConstant) {
TOUCH_SLOP_DEFAULT -> touchSlopType = vc.scaledTouchSlop
TOUCH_SLOP_PAGING -> touchSlopType = vc.scaledPagingTouchSlop
}
}
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
if (e == null) {
return false
}
val action = e.actionMasked
val actionIndex = e.actionIndex
when (action) {
MotionEvent.ACTION_DOWN -> {
scrollPointerId = e.getPointerId(0)
pointTouchX = Math.round(e.x + 0.5f)
pointTouchY = Math.round(e.y + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_POINTER_DOWN -> {
scrollPointerId = e.getPointerId(actionIndex)
pointTouchX = Math.round(e.getX(actionIndex) + 0.5f)
pointTouchY = Math.round(e.getY(actionIndex) + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_MOVE -> {
val index = e.findPointerIndex(scrollPointerId)
if (index < 0) {
return false
}
val x = Math.round(e.getX(index) + 0.5f)
val y = Math.round(e.getY(index) + 0.5f)
if (scrollState != SCROLL_STATE_DRAGGING) {
val dx = x - pointTouchX
val dy = y - pointTouchY
var startScroll = false
if (layoutManager?.canScrollHorizontally() == true && Math.abs(dx) > touchSlopType && (layoutManager?.canScrollVertically() == true || Math.abs(dx) > Math.abs(dy))) {
startScroll = true
}
if (layoutManager?.canScrollVertically() == true && Math.abs(dy) > touchSlopType && (layoutManager?.canScrollHorizontally() == true || Math.abs(dy) > Math.abs(dx))) {
startScroll = true
}
return startScroll && super.onInterceptTouchEvent(e)
}
return super.onInterceptTouchEvent(e)
}
else -> {
return super.onInterceptTouchEvent(e)
}
}
}
}
and create ChildHorizontalRecyclerView for other nested RecyclerView inside main RecyclerView like this:
class ChildHorizontalRecyclerView : MainVerticalRecyclerView {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
if you want scroll like in PlayStore when you touch HorizontalChildRecyclerView need write:
recyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
if (e.action == MotionEvent.ACTION_DOWN && rv.scrollState == RecyclerView.SCROLL_STATE_SETTLING) {
rv.stopScroll()
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
Related
I'm creating a custom SwipeButton extend RelativeLayout in android which contains an image that I can swipe to right.
On the other hand, I have a Fragment that includes this SwipeButton. My goal is that when swipe has completed (the image has been scrolled to the end) execute a function in fragment
include some code:
1. Fragment
class FirstStep() : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_first_step, container, false)
val swipeButton : SwipeButton = view.findViewById(R.id.swipe_btn)
// I TRIED THIS: ------------------------------
swipeButton.setOnTouchListener { view, motionEvent ->
when(motionEvent.action){
MotionEvent.ACTION_UP -> {
if(swipeButton.completed){
//function that i need to run in firebase
}
return#setOnTouchListener true
}
else -> {return#setOnTouchListener true}
}
}
// I TRIED THIS: ------------------------------
// NOT WORKS *explanation below
return view
}
}
*Didn't work because apparently I think it conflicts with the same on touch listener that is inside the SwipeButton Class and from then the Button not works
2. fragment_first_step.xml
... some layouts
<com.app.SwipeButton
android:id="#+id/swipe_btn"
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="70dp"
/>
3. SwipeButton Class
class SwipeButton : RelativeLayout {
#JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : super(context, attrs, defStyleAttr) {
init(context, attrs)
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) {
init(context, attrs)
}
private var slidingButton: ImageView? = null
private var initialX : Float = 0f
private var active = false
var completed = false
private var initialButtonWidth : Int = 0
private var centerText: TextView? = null
private var disabledDrawable: Drawable? = null
private var enabledDrawable: Drawable? = null
private fun init(context: Context, attrs: AttributeSet?) {
// add Relative Layout
val background = RelativeLayout(context)
val layoutParamsView = LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
layoutParamsView.addRule(CENTER_IN_PARENT, TRUE)
background.background = ContextCompat.getDrawable(context, R.drawable.shape_rounded)
addView(background, layoutParamsView)
// add text to button
val centerText:TextView = TextView(context)
this.centerText = centerText
val layoutParams = LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
layoutParams.addRule(CENTER_IN_PARENT, TRUE)
centerText.text = "SIGUIENTE PASO" //add any text you need
centerText.setTextColor(Color.WHITE)
centerText.setPadding(35, 35, 35, 35)
background.addView(centerText, layoutParams)
// add image to swipe
val swipeButton = ImageView(context)
slidingButton = swipeButton
disabledDrawable =
ContextCompat.getDrawable(getContext(), R.drawable.ic_home)
enabledDrawable =
ContextCompat.getDrawable(getContext(), R.drawable.ic_close_black)
slidingButton!!.setImageDrawable(disabledDrawable)
slidingButton!!.setPadding(40, 40, 40, 40)
val layoutParamsButton = LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
layoutParamsButton.addRule(ALIGN_PARENT_LEFT, TRUE)
layoutParamsButton.addRule(CENTER_VERTICAL, TRUE)
swipeButton.background = ContextCompat.getDrawable(context, R.drawable.shape_button)
swipeButton.setImageDrawable(disabledDrawable)
addView(swipeButton, layoutParamsButton)
// LISTEN TO TOUCH CHANGES
setOnTouchListener(getButtonTouchListener())
this.onFinishInflate()
}
#SuppressLint("ClickableViewAccessibility")
private fun getButtonTouchListener(): OnTouchListener? {
return OnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> return#OnTouchListener true
MotionEvent.ACTION_MOVE -> {
if (initialX.toInt() == 0) {
initialX = slidingButton!!.x;
}
if ((event.x > initialX + slidingButton!!.width.toFloat() / 2) && (event.x + slidingButton!!.width / 2 < width)) {
slidingButton!!.setX(event.x - slidingButton!!.width / 2);
centerText?.setAlpha(1 - 1.3f * (slidingButton!!.x + slidingButton!!.width) / width);
}
if (event.x + slidingButton!!.width / 2 > width && slidingButton!!.x + slidingButton!!.width / 2 < width) {
slidingButton!!.setX((width - slidingButton!!.width).toFloat());
}
if (event.x < slidingButton!!.width / 2 && slidingButton!!.x > 0) {
slidingButton!!.setX(0F)
}
}
MotionEvent.ACTION_UP -> {
if (active) {
collapseButton();
} else {
initialButtonWidth = slidingButton!!.width
if (slidingButton!!.x + slidingButton!!.width > width * 0.85) {
expandButton();
completed = true
// HERE SWIPE IS COMPLETED
} else {
moveButtonBack();
}
}
}
}
false
}
}
private fun expandButton() {
val positionAnimator = ValueAnimator.ofFloat(slidingButton!!.x, 0f)
positionAnimator.addUpdateListener {
val x = positionAnimator.animatedValue as Float
slidingButton!!.x = x
}
val widthAnimator = ValueAnimator.ofInt(
slidingButton!!.width,
width
)
widthAnimator.addUpdateListener {
val params = slidingButton!!.layoutParams
params.width = (widthAnimator.animatedValue as Int)
slidingButton!!.layoutParams = params
}
val animatorSet = AnimatorSet()
animatorSet.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
active = true
slidingButton!!.setImageDrawable(enabledDrawable)
}
})
animatorSet.playTogether(positionAnimator, widthAnimator)
animatorSet.start()
}
private fun collapseButton() {
val widthAnimator = ValueAnimator.ofInt(
slidingButton!!.width,
initialButtonWidth
)
widthAnimator.addUpdateListener {
val params = slidingButton!!.layoutParams
params.width = (widthAnimator.animatedValue as Int)
slidingButton!!.layoutParams = params
}
widthAnimator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
active = false
slidingButton!!.setImageDrawable(disabledDrawable)
}
})
val objectAnimator = ObjectAnimator.ofFloat(
centerText!!, "alpha", 1f
)
val animatorSet = AnimatorSet()
animatorSet.playTogether(objectAnimator, widthAnimator)
animatorSet.start()
}
private fun moveButtonBack() {
val positionAnimator = ValueAnimator.ofFloat(slidingButton!!.x, 0f)
positionAnimator.interpolator = AccelerateDecelerateInterpolator()
positionAnimator.addUpdateListener {
val x = positionAnimator.animatedValue as Float
slidingButton!!.x = x
}
val objectAnimator = ObjectAnimator.ofFloat(
centerText!!, "alpha", 1f
)
positionAnimator.duration = 200
val animatorSet = AnimatorSet()
animatorSet.playTogether(objectAnimator, positionAnimator)
animatorSet.start()
}
}
any help would be greatly appreciated
Thanks!!
I use MaterialAutoCompleteTextView, when i add new item / items and call notifyDataSetChanged(), dropdown automatically closes
How to fix this
VIDEO:
https://drive.google.com/file/d/1AYWW-_HcIpefrn0RcPMx2EsLLoyB2TtY/view?usp=sharing
CODE:
class MainActivity : AppCompatActivity() {
private lateinit var materialAutoComplete: MaterialAutoCompleteTextView
private lateinit var adapter: CustomArrayAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
materialAutoComplete = findViewById(R.id.materialAutoComplete_main)
setupMaterialAutoComplete()
}
private var number = 0
private fun setupMaterialAutoComplete() {
val items = mutableListOf("Shop", "Shop", "Shop", "Shop")
adapter = CustomArrayAdapter(
this,
R.layout.item_goods_material_auto_complete,
items
)
materialAutoComplete.setAdapter(adapter)
object : CountDownTimer(3000, 1000) {
override fun onTick(millisUntilFinished: Long) {
}
override fun onFinish() {
number += 1
adapter.addAll(mutableListOf("$number", "${number + 1}"))
}
}.start()
}
}
Just override this methods
class MaterialAutoCompleteTextViewWithoutAutoCloseDropdown : MaterialAutoCompleteTextView {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet?) : super(context, attributeSet)
constructor(
context: Context, attributeSet: AttributeSet?, defStyleAttr: Int,
) : super(context, attributeSet, defStyleAttr)
override fun dismissDropDown() {
}
override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && isPopupShowing) {
if (event.action == KeyEvent.ACTION_DOWN && event.repeatCount == 0) {
val state = keyDispatcherState
state?.startTracking(event, this)
return true
} else if (event.action == KeyEvent.ACTION_UP) {
val state = keyDispatcherState
state?.handleUpEvent(event)
if (event.isTracking && !event.isCanceled) {
super.dismissDropDown()
return true
}
}
}
return super.onKeyPreIme(keyCode, event)
}
override fun replaceText(text: CharSequence?) {
clearComposingText()
setText(text)
val spannable = getText()
Selection.setSelection(spannable, spannable.length)
super.dismissDropDown()
}
}
I have a custom EditText providig PinEntry functionality looking like this:
class PinEntryView : EditText {
private var mSpace = 15f
private var mCharSize = 0f
private var mNumChars = 4f
private var mLineSpacing = 8f
private val XML_NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android"
private var mClickListener: View.OnClickListener? = null
private var mLineStroke = 1f
private var mLinesPaint: Paint? = null
private var mOnPinEnteredListener: OnPinEnteredListener? = null
private fun updateColorForLines(next: Boolean) {
if (isFocused) {
mLinesPaint!!.color = getColor(context, android.R.color.transparent)
if (next) {
mLinesPaint!!.color = getColor(context, R.color.edit_text_background)
}
} else {
mLinesPaint!!.color = getColor(context, android.R.color.transparent)
}
}
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context, attrs)
}
constructor(
context: Context, attrs: AttributeSet,
defStyleAttr: Int
) : super(context, attrs, defStyleAttr) {
init(context, attrs)
}
private fun init(context: Context, attrs: AttributeSet) {
val multi = context.resources.displayMetrics.density
mLineStroke *= multi
mLinesPaint = Paint(paint)
mLinesPaint!!.strokeWidth = mLineStroke
mSpace *= multi
mLineSpacing *= multi
val mMaxLength = attrs.getAttributeIntValue(
XML_NAMESPACE_ANDROID,
"maxLength",
6
)
paint.color = getColor(context, android.R.color.white)
mNumChars = mMaxLength.toFloat()
super.setCustomSelectionActionModeCallback(
object : ActionMode.Callback {
override fun onPrepareActionMode(
mode: ActionMode,
menu: Menu
): Boolean {
return false
}
override fun onDestroyActionMode(mode: ActionMode) {}
override fun onCreateActionMode(
mode: ActionMode,
menu: Menu
): Boolean {
return false
}
override fun onActionItemClicked(
mode: ActionMode,
item: MenuItem
): Boolean {
return false
}
})
super.setOnClickListener { v ->
setSelection(text.length)
if (mClickListener != null) {
mClickListener!!.onClick(v)
}
}
}
override fun setOnClickListener(l: OnClickListener) {
mClickListener = l
}
override fun onDraw(canvas: Canvas) {
val availableWidth = width - paddingRight - paddingLeft
mCharSize = if (mSpace < 0) {
(availableWidth / (mNumChars * 2 - 1))
} else {
(availableWidth - mSpace * (mNumChars - 1)) / mNumChars
}
var startX = paddingLeft.toFloat()
val bottom = height.toFloat() - paddingBottom.toFloat()
val text = text
val textLength = text.length
val textWidths = FloatArray(textLength)
paint.getTextWidths(getText(), 0, textLength, textWidths)
for (i in 0 until mNumChars.toInt()) {
updateColorForLines(i == textLength)
canvas.drawRoundRect(
startX, 0f, startX + mCharSize, height.toFloat(), 5f, 5f, mLinesPaint
)
if (text.length > i) {
val middle = startX + mCharSize / 2
canvas.drawText(
"******",
i,
i + 1,
middle - textWidths[0] / 2,
bottom - mLineSpacing,
paint
)
}
startX += if (mSpace < 0) {
mCharSize * 2
} else {
mCharSize + mSpace
}
}
}
override fun onTextChanged(text: CharSequence, start: Int, lengthBefore: Int, lengthAfter: Int) {
if (mOnPinEnteredListener != null && text.length.toFloat() == mNumChars) {
mOnPinEnteredListener!!.onPinEntered(text)
}
}
fun setOnPinEnteredListener(l: OnPinEnteredListener) {
mOnPinEnteredListener = l
}
interface OnPinEnteredListener {
fun onPinEntered(str: CharSequence)
}
}
I followed this tutorial: https://medium.com/#ali.muzaffar/building-a-pinentryedittext-in-android-5f2eddcae5d3
And I am getting behavior showed on picture:
But I would like to have a behavior as shown here:
How can I achieve that? How can I add those default dots/symbols? I tried adding it as a hint or default text, but it does not work because of my onDraw function
Hopefully you found already your solution. But here is how I would've done it:
The PinEntryEditText has an attribute you can set in the .xml file.
Adding this to the element will do the trick: app:pinSingleCharHint="•"
For more customisation check out the sample xml from this page
This question already has answers here:
All Editexts be replace by same value after pop a Fragment
(4 answers)
Closed 4 years ago.
I have a custom view with an edittext and an imageview. I use this view multiple times in the same layout. It's behaving very strange though. Whenever I rotate the device the value from the last declared view in the xml is put into all the other views in the layout and I just can't figure out where things go wrong.
My view:
class InputView(context: Context, attrs: AttributeSet?, #AttrRes defStyleAttr: Int) : ConstraintLayout(context, attrs, defStyleAttr) {
private var textInputLayout: TextInputLayout
private var textView: TextInputEditText
private var imageView: ImageView
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
init {
val view = LayoutInflater.from(context).inflate(R.layout.custom_inputview, this, true)
textInputLayout = view.custom_inputview_text_input_layout
textView = view.custom_inputview_text_input_edit_text
imageView = view.custom_inputview_image_view
attrs.let {
context.theme.obtainStyledAttributes(
it,
R.styleable.InputView,
defStyleAttr, 0).apply {
try {
textView.textSize = getDimension(R.styleable.InputView_android_textSize, 16.0f)
textView.text = SpannableStringBuilder(getString(R.styleable.InputView_android_text) ?: "")
textInputLayout.hint = getText(R.styleable.InputView_android_hint)
if (getDrawable(R.styleable.InputView_android_src) == null) {
imageView.isVisible = false
} else {
imageView.setImageDrawable(getDrawable(R.styleable.InputView_android_src))
imageView.setColorFilter(getColorOrThrow(R.styleable.InputView_android_tint))
}
textView.maxLines = getInteger(R.styleable.InputView_android_maxLines, 1)
textView.minLines = getInteger(R.styleable.InputView_android_minLines, 0)
textView.setLines(getInteger(R.styleable.InputView_android_lines, 1))
textView.inputType = getInteger(R.styleable.InputView_android_inputType, EditorInfo.IME_NULL)
textView.setCompoundDrawablesWithIntrinsicBounds(
getDrawable(R.styleable.InputView_android_drawableStart),
getDrawable(R.styleable.InputView_android_drawableTop),
getDrawable(R.styleable.InputView_android_drawableEnd),
getDrawable(R.styleable.InputView_android_drawableBottom))
} finally {
recycle()
}
}
}
}
override fun onSaveInstanceState(): Parcelable {
// 1
val bundle = Bundle()
// 2
bundle.putString("text", textView.text.toString())
// 3
Log.d("InputView", "Saving state text: ${textView.text.toString()}")
bundle.putParcelable("superState", super.onSaveInstanceState())
return bundle
}
override fun onRestoreInstanceState(state: Parcelable) {
// 4
var viewState = state
if (viewState is Bundle) {
// 5
Log.d("InputView", "Textview text: ${viewState.getString("text")}")
textView.text = SpannableStringBuilder(viewState.getString("text"))
// 6
viewState = viewState.getParcelable("superState")
}
super.onRestoreInstanceState(viewState)
}
}
I've tried overriding onSaveIntanceState() and onRestoreInstanceState(), but it doesn't change anything.
Screenshot before rotation:
Screenshot after rotation:
Added this to my custom view and the problem was gone:
class InputView(context: Context, attrs: AttributeSet?, #AttrRes defStyleAttr: Int) : ConstraintLayout(context, attrs, defStyleAttr) {
...
#Suppress("UNCHECKED_CAST")
public override fun onSaveInstanceState(): Parcelable? {
val superState = super.onSaveInstanceState()
val ss = SavedState(superState)
ss.childrenStates = SparseArray()
for (i in 0 until childCount) {
getChildAt(i).saveHierarchyState(ss.childrenStates as SparseArray<Parcelable>)
}
return ss
}
#Suppress("UNCHECKED_CAST")
public override fun onRestoreInstanceState(state: Parcelable) {
val ss = state as SavedState
super.onRestoreInstanceState(ss.superState)
for (i in 0 until childCount) {
getChildAt(i).restoreHierarchyState(ss.childrenStates as SparseArray<Parcelable>)
}
}
override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
dispatchFreezeSelfOnly(container)
}
override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) {
dispatchThawSelfOnly(container)
}
class SavedState(superState: Parcelable?) : BaseSavedState(superState) {
var childrenStates: SparseArray<Any>? = null
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
childrenStates?.let {
out.writeSparseArray(it)
}
}
}
}
I have this custom ViewPager created from here (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
}
}
}
}
I use an adapter that loads an ImageView inside each page. This ImageView has a 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)
}
}
The swipe on the custom viewpager doesn't work if the ImageView has this listener. If I remove the listener, works fine.
Anybody know what can be the problem?
Finally I solved the problem. I was to add logic to onInterceptTouchEvent to release the onTouch event if user only tap the viewpager and not swapping. This is the final code:
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))
}
The result is not all accurate that I want. If someone can improve it, it will be welcome