(Kotlin) FlashCard의 완성, Flip & Swipe Animation

이전 포스팅에서 Flip Animation을 적용했었죠!?

2019/08/15 - [안드로이드 개발/Kotlin으로 어플 만들기] - (Kotlin) Card Flip Animation으로 Flashcard 만들기

 

(Kotlin) Card Flip Animation으로 Flashcard 만들기

지난 포스팅에서 FlipView로 FlashCard 만드는 법을 알아봤는데요. 2019/08/12 - [안드로이드 개발/Kotlin으로 어플 만들기] - (Kotlin) Flip View(플립뷰)로 플래시카드 만들기 (Kotlin) Flip View(플립뷰)로 플..

hamzzibari.tistory.com

계획은 여기에 인피니티 사이클 뷰 페이저를 적용하려고 했으나,

어렵네요ㅠㅠ

 

그래서 다른 방법으로 적용해봤습니다.

애니매이션 질은 별로지만, 더 간단합니다. 

 

1. animator

지난번에 만들어 놓은 animator 폴더에 아래 xml을 만들어줍니다. 

1) swipe_left_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="600"
        android:fromXDelta="100%"
        android:toXDelta="0%" >
    </translate>
</set>

2) swipe_right_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="600"
        android:fromXDelta="-100%"
        android:toXDelta="0%" >
    </translate>
</set>

2. Kotlin

1) SwipeDetector.kt

SwipeDetector 클래스를 하나 만들어주세요.

class SwipeDetector : View.OnTouchListener {
    val HORIZONTAL_MIN_DISTANCE = 60
    val VERTICAL_MIN_DISTANCE = 80
    private var downX: Float = 0.toFloat()
    private var downY: Float = 0.toFloat()
    private var upX: Float = 0.toFloat()
    private var upY: Float = 0.toFloat()
    var action = Action.None
        private set

    enum class Action {
        LR, // Left to Right
        RL, // Right to Left
        TB, // Top to bottom
        BT, // Bottom to Top
        None // when no action was detected
    }

    fun swipeDetected(): Boolean {
        return action != Action.None
    }

    override fun onTouch(v: View, event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                downX = event.x
                downY = event.y
                action = Action.None
                return false // allow other events like Click to be processed
            }
            MotionEvent.ACTION_MOVE -> {
                upX = event.x
                upY = event.y

                val deltaX = downX - upX
                val deltaY = downY - upY

                // horizontal swipe detection
                if (Math.abs(deltaX) > HORIZONTAL_MIN_DISTANCE) {
                    // left or right
                    if (deltaX < 0) {
                        Log.i(logTag, "Swipe Left to Right")
                        action = Action.LR
                        return true
                    }
                    if (deltaX > 0) {
                        Log.i(logTag, "Swipe Right to Left")
                        action = Action.RL
                        return true
                    }
                } else
                // vertical swipe detection
                    if (Math.abs(deltaY) > VERTICAL_MIN_DISTANCE) {
                        // top or down
                        if (deltaY < 0) {
                            Log.i(logTag, "Swipe Top to Bottom")
                            action = Action.TB
                            return false
                        }
                        if (deltaY > 0) {
                            Log.i(logTag, "Swipe Bottom to Top")
                            action = Action.BT
                            return false
                        }
                    }
                return true
            }
        }
        return false
    }

    companion object {

        private val logTag = "SwipeDetector"
        private val MIN_DISTANCE = 100
    }
}

2) Study_Flip.kt

(1) 코드 수정

그리고 지난 번에 만든 코드에서 약간의 수정을 해주겠습니다.

우선,

if (savedInstanceState == null) {
            supportFragmentManager
                .beginTransaction()
                .add(R.id.study_flip_container, Study_Flip_Front())
                .commit()
        } else {
            isShowingBackLayout = supportFragmentManager.backStackEntryCount > 0
        }

        supportFragmentManager.addOnBackStackChangedListener(this);

이 부분을 getFrontFragment()를 만들어 옮겨줍니다.

(사실 이 작업은 안 해도 됩니다. 저는 반복해서 사용해야 해서 코드를 줄여주기 위한 목적입니다.)

private fun getFrontFragment(savedInstanceState: Bundle?) {
        if (savedInstanceState == null) {
            supportFragmentManager
                .beginTransaction()
                .replace(R.id.study_flip_container, Study_Flip_Front()
                .commit()
        } else {
            isShowingBackLayout = supportFragmentManager.backStackEntryCount > 0
        }
        supportFragmentManager.addOnBackStackChangedListener(this);
    }

(2) 코드 추가

onCreate부분에 아래 코드를 추가해주세요.

		//아까 옮겨준 코드를 연결해줍니다.
        getFrontFragment(savedInstanceState)

		//SwipeDetector.kt와 연결해줍니다.
        val swipeDetector = SwipeDetector()

		//이전코드에서는 RelativeLayout 이었죠? 저는 디자인을 바꾸다보니 바뀐거에요.
        val study_flip_container = findViewById(R.id.study_flip_container) as LinearLayout
        //온터치리스너(이게 없으면 작동안하네요)
        study_flip_container.setOnTouchListener(swipeDetector)
        //온클릭리스너(여기에서 TODO!)
        study_flip_container.setOnClickListener {
            //스와이프
            if (swipeDetector.swipeDetected()) {
                //스와이프 처리
                if (swipeDetector.action.equals(SwipeDetector.Action.LR)) {
                    //여기에 적용할 코드를 입력해주세요~
                } else if (swipeDetector.action.equals(SwipeDetector.Action.RL)) {
                   //여기에 적용할 코드를 입력해주세요~
                }
            }else {
                flipCard()
            }
        }

스와이프 시 입력한 코드가 실행되고, 스와이프를 하지 않고 터치만 하게 되면 flipCard()가 실행됩니다.

 

3. 결과물

결과물은 코드대로 만든거랑 다릅니다.

디자인 부분과 LIST를 불러오는 코드는 빼버렸거든요.

동작하는 기능은 같습니다!

 

끝.

댓글

Designed by JB FACTORY