koloda.reloadPreviousCard()丢失

时间:2018-07-23 11:54:05

标签: android kotlin koloda

最近我了解了一个像Tinder一样提供滑动功能的库,库名是Yalantis/Koloda-Android。但是,当我使用它时,我发现一些方法回调被错误地放置了,因此,我对其进行了更正,但是现在的主要问题是有一种方法可以重新加载最后一张刷卡。方法名称是“ koloda.reloadPreviousCard()”,但是该方法不在代码中,而是在Github的文档中提到。我试图与该库的作者联系,但没有任何回应,我在Github上打开了一个问题,并通过电子邮件与他们联系,在Github上提到了将近一个月的电子邮件。

如果任何人都遇到过相同的问题并已解决,请在此处分享解决方案。

我正在将代码发布到需要回调方法的位置,如果您需要更多信息,请告诉我。

Koloda.kt:

class Koloda : FrameLayout {

    companion object {
        private const val DEFAULT_MAX_VISIBLE_CARDS = 3
        private const val DEFAULT_ROTATION_ANGLE = 30f
        private const val DEFAULT_SCALE_DIFF = 0.04f
    }

    private var maxVisibleCards = DEFAULT_MAX_VISIBLE_CARDS
    private var cardPositionOffsetX = resources.getDimensionPixelSize(R.dimen.default_card_spacing)
    private var cardPositionOffsetY = resources.getDimensionPixelSize(R.dimen.default_card_spacing)
    private var cardRotationDegrees = DEFAULT_ROTATION_ANGLE
    private var dyingViews = hashSetOf<View>()
    private var activeViews = linkedSetOf<View>()
    private var dataSetObservable: DataSetObserver? = null
    var isNeedCircleLoading = false

    var adapter: Adapter? = null
        set(value) {
            dataSetObservable?.let { field?.unregisterDataSetObserver(it) }
            removeAllViews()
            field = value
            field?.registerDataSetObserver(createDataSetObserver())
            dataSetObservable?.onChanged()
        }
    private var adapterPosition = 0
    private var deckMap = hashMapOf<View, CardOperator>()
    var kolodaListener: KolodaListener? = null
    internal var parentWidth = 0
    private var swipeEnabled = true

    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) {
        init(attrs)
    }

    private fun init(attrs: AttributeSet?) {
        val a = context.obtainStyledAttributes(attrs, R.styleable.Koloda)
        val cardLayoutId = a.getResourceId(R.styleable.Koloda_koloda_card_layout, -1)
        maxVisibleCards = a.getInt(R.styleable.Koloda_koloda_max_visible_cards, DEFAULT_MAX_VISIBLE_CARDS)
        cardPositionOffsetX = a.getDimensionPixelSize(R.styleable.Koloda_koloda_card_offsetX, resources.getDimensionPixelSize(R.dimen.default_card_spacing))
        cardPositionOffsetY = a.getDimensionPixelSize(R.styleable.Koloda_koloda_card_offsetY, resources.getDimensionPixelSize(R.dimen.default_card_spacing))
        cardRotationDegrees = a.getFloat(R.styleable.Koloda_koloda_card_rotate_angle, DEFAULT_ROTATION_ANGLE)

        a.recycle()

        if (isInEditMode) {
            LayoutInflater.from(context).inflate(cardLayoutId, this, true)
        }
    }

    /**
     * Add card to visible stack
     */

    private fun addCardToDeck() {
        if (adapterPosition < adapter?.count ?: 0) {
            val newCard = adapter?.getView(adapterPosition, null, this)
            initializeCardPosition(newCard)
            newCard?.let {
                addView(it, 0)
                deckMap.put(it, CardOperator(this, it, adapterPosition++, cardCallback))
            }
        } else if (isNeedCircleLoading) {
            adapterPosition = 0
            addCardToDeck()
        }
    }

    /**
     * Set up card offset
     * @param view - new card
     */
    private fun initializeCardPosition(view: View?) {
        val childCount = childCount - dyingViews.size

        scaleView(view, 0f, childCount)
        view?.translationY = (cardPositionOffsetY * childCount).toFloat()
        /*-Log.i("----> elem init", childCount.toString())
        Log.i("----> translation init", view?.translationY.toString())*/
        setZTranslations(childCount)
    }

    private fun checkTopCard() {
        val childCount = childCount
        setZTranslations(childCount)
        if (childCount - 1 - dyingViews.size < 0) {
            kolodaListener?.onEmptyDeck()
        } else {
            val topCard = getChildAt(childCount - 1 - dyingViews.size)
            if (deckMap.containsKey(topCard)) {
                deckMap[topCard]?.let { kolodaListener?.onNewTopCard(it.adapterPosition) }
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private fun setZTranslations(childCount: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            (0 until childCount).map {
                getChildAt(it).translationZ = (it * 10).toFloat()
            }
        }
    }

    fun getMaxCardWidth(cardView: View): Float = cardView.height * Math.tan(Math.toRadians(cardRotationDegrees.toDouble())).toFloat()

    fun canSwipe(card: View): Boolean {
        /*-Log.e("====>Swipe ", swipeEnabled.toString())
        Log.e("====>Active viewsempty ", activeViews.isEmpty().toString())
        Log.e("====>Or contains ", (activeViews.contains(card)).toString())
        Log.e("====>Index ", (indexOfChild(card) >= childCount - 2).toString())*/
        return (swipeEnabled && (activeViews.isEmpty() || activeViews.contains(card))
                && indexOfChild(card) >= childCount - 2)
    }

    private fun updateDeckCardsPosition(progress: Float) {
        val visibleChildCount = Math.min(childCount, maxVisibleCards + 1)
        var childCount = Math.min(childCount, maxVisibleCards)
        var cardsWillBeMoved = 0

        var cardView: View

        (0 until visibleChildCount).map {
            cardView = getChildAt(it)
            if (deckMap.containsKey(cardView) && deckMap[cardView]?.isBeingDragged != true) {
                cardsWillBeMoved++
            }
            scaleView(cardView, progress, childCount - it - 1)
        }
        if (progress != 0.0f) {
            for (i in 0 until cardsWillBeMoved) {
                cardView = getChildAt(i)
                cardView.translationY = (cardPositionOffsetY * Math.min(cardsWillBeMoved, visibleChildCount - i - 1) - cardPositionOffsetY * Math.abs(progress))
            }
        }
    }

    private fun scaleView(view: View?, progress: Float, childCount: Int) {
        val currentScale = 1f - (childCount * DEFAULT_SCALE_DIFF)
        val nextScale = 1f - ((childCount - 1) * DEFAULT_SCALE_DIFF)
        val scale = currentScale + (nextScale - currentScale) * Math.abs(progress)
        if (scale <= 1f) {
            view?.scaleX = scale
            view?.scaleY = scale
        }
    }

    private fun updateCardView(card: View, sideProgress: Float) {
        val rotation = cardRotationDegrees.toInt() * sideProgress
        card.rotation = rotation
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (changed) {
            dataSetObservable?.onChanged()
        }
    }

    override fun addView(child: View, index: Int) {
        child.alpha = 0f
        super.addView(child, index)
        child.animate().alpha(1f).duration = 300
    }

    override fun removeAllViews() {
        super.removeAllViews()
        deckMap.clear()
        activeViews.clear()
        dyingViews.clear()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        parentWidth = (this.parent as View).measuredWidth
    }

    private fun createDataSetObserver(): DataSetObserver {
        dataSetObservable = object : DataSetObserver() {
            override fun onChanged() {
                super.onChanged()
                addCards()
            }

            override fun onInvalidated() {
                super.onInvalidated()
                adapterPosition = 0
                removeAllViews()
                addCards()
            }

            private fun addCards() {
                val childCount = childCount - dyingViews.size
                for (i in childCount until maxVisibleCards) {
                    addCardToDeck()
                }
                checkTopCard()
            }
        }
        return dataSetObservable as DataSetObserver
    }

    private var cardCallback: CardCallback = object : CardCallback {
        override fun onCardActionDown(adapterPosition: Int, card: View) {
            activeViews.add(card)
        }

        override fun onCardDrag(adapterPosition: Int, card: View, sideProgress: Float) {
            updateCardView(card, sideProgress)
            kolodaListener?.onCardDrag(adapterPosition, card, sideProgress)
        }

        override fun onCardOffset(adapterPosition: Int, card: View, offsetProgress: Float) {
            updateDeckCardsPosition(offsetProgress)
        }

        override fun onCardActionUp(adapterPosition: Int, card: View, isCardNeedRemove: Boolean) {
            if (isCardNeedRemove) {
                activeViews.remove(card)
            }
        }

        override fun onCardSwipedLeft(adapterPosition: Int, card: View, notify: Boolean) {
            dyingViews.add(card)
            dataSetObservable?.onChanged()
            if (notify) {
                kolodaListener?.onCardSwipedLeft(adapterPosition)
            }
        }

        override fun onCardSwipedRight(adapterPosition: Int, card: View, notify: Boolean) {
            dyingViews.add(card)
            dataSetObservable?.onChanged()
            if (notify) {
                kolodaListener?.onCardSwipedRight(adapterPosition)
            }
        }

        override fun onCardOffScreen(adapterPosition: Int, card: View) {
            dyingViews.remove(card)
            deckMap.remove(card)
            removeView(card)
        }

        override fun onCardSingleTap(adapterPosition: Int, card: View) {
            kolodaListener?.onCardSingleTap(adapterPosition)
        }

        override fun onCardDoubleTap(adapterPosition: Int, card: View) {
            kolodaListener?.onCardDoubleTap(adapterPosition)
        }

        override fun onCardLongPress(adapterPosition: Int, card: View) {
            kolodaListener?.onCardLongPress(adapterPosition)
        }

        override fun onCardMovedOnClickRight(adapterPosition: Int, card: View, notify: Boolean) {
            activeViews.remove(card)
            dyingViews.add(card)
            dataSetObservable?.onChanged()
            findPositionAfterClick()
            if (notify) {
                kolodaListener?.onClickRight(adapterPosition)
            }
        }

        override fun onCardMovedOnClickLeft(adapterPosition: Int, card: View, notify: Boolean) {
            activeViews.remove(card)
            dyingViews.add(card)
            dataSetObservable?.onChanged()
            findPositionAfterClick()
            if (notify) {
                kolodaListener?.onClickLeft(adapterPosition)
            }
        }
    }

    fun onClickRight() {
        val childCount = childCount
        val topCard = getChildAt(childCount - 1 - dyingViews.size)
        topCard?.let {
            activeViews.add(it)
            val cardOperator: CardOperator? = deckMap[it]
            cardOperator?.onClickRight()
            it.rotation = 10f
        }
    }

    fun onClickLeft() {
        val childCount = childCount
        val topCard = getChildAt(childCount - 1 - dyingViews.size)
        topCard?.let {
            activeViews.add(it)
            val cardOperator: CardOperator? = deckMap[it]
            cardOperator?.onClickLeft()
            it.rotation = -10f
        }
    }

    private fun findPositionAfterClick() {
        var childCount = Math.min(childCount, maxVisibleCards)
        (0 until childCount).map {
            val view = getChildAt(it)
            scaleView(view, 0f, childCount - it - 1)
            view?.translationY = (cardPositionOffsetY * (childCount - it - 1)).toFloat()
        }
    }
}

0 个答案:

没有答案