[Android] 화면 터치 중 Swiping을 이용한 View 전환

화면 터치가 가능한 모바일 단말기에서 터치를 통한 UI의 조작은 매우 효과적입니다. 이러한 터치 기반의 UI의 활용에 대해 자연스러운 사용은 사용자에게 프로그램의 친밀도를 높여줍니다. 화면 터치에 대한 조작 중 Swiping은 사용자가 화면을 스치듯이 상하좌우로 쓸어넘기는 행위입니다. 이러한 Swiping 중 좌우에 대한 이벤트를 처리하기 위한 클래스는 다음과 같습니다.

package geoservice.nexgen

import android.content.Context
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View

abstract class OnSwipeTouchListener(context: Context?) : View.OnTouchListener {
    companion object {
        private const val SWIPE_DISTANCE_THRESHOLD = 100
        private const val SWIPE_VELOCITY_THRESHOLD = 100
    }

    private val gestureDetector: GestureDetector

    abstract fun onSwipeLeft()
    abstract fun onSwipeRight()

    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
        return gestureDetector.onTouchEvent(event)
    }

    private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
        override fun onDown(e: MotionEvent): Boolean {
            return true
        }

        override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
            val distanceX = e2.x - e1.x
            val distanceY = e2.y - e1.y
            if (Math.abs(distanceX) > Math.abs(distanceY) 
                    && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD 
                    && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                if (distanceX > 0) onSwipeRight() else onSwipeLeft()
                return true
            }
            return false
        }
    }

    init {
        gestureDetector = GestureDetector(context, GestureListener())
    }
}

위 클래스를 실제 View에 적용하는 코드의 예는 다음과 같습니다.

llListScroll.setOnTouchListener(object: OnSwipeTouchListener(context) {
    override fun onSwipeLeft() { btnNext.performClick() }
    override fun onSwipeRight() { btnPrevious.performClick() }
})

실제 위의 코드는 모바일 기반의 GIS 솔루션인 Mobile NexGen에 반영된 코드인데요. 위의 코드와 연관된 기능에 대한 시연 영상은 아래와 같습니다.

코틀린의 observable, vetoable 위임자

코틀린은 2011년 중순에 공개되어 지속적으로 발전되어 오다가 2019년에 구글 안드로이드 개발 주요 개발언어로 채택되면서 현대적인 프로그래밍 언어중 하나입니다. 이 글은 코틀린의 데이터 변수에 obserable과 vetoable 위임자를 지정하여 변수의 값이 변경될 경우 원하는 로직을 실행하거나 변수의 값의 변경시 특정 조건과 맞지 않으면 변경을 취소하는 내용을 대해 설명합니다.

먼저 obserable 위임자를 통한 변수값 변경시 처리입니다.

import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("초기값") {
        prop, old, new -> println("$old 값이 $new 값으로 변경됩니다.")
    }
}

fun main() {
    val user = User()
    user.name = "홍길동"
    user.name = "임꺽정"
}

실행 결과는 다음과 같습니다.

초기값 값이 홍길동 값으로 변경됩니다.
홍길동 값이 임꺽정 값으로 변경됩니다.

다음은 vetoable 위임자입니다. 값의 변경시 특정한 조건에 따라 변경을 취소할 수 있습니다.

import kotlin.properties.Delegates

class MoreBiggerInt(initValue: Int) {
    var value: Int by Delegates.vetoable(initValue) {
        property, oldValue, newValue -> {
        val result = newValue > oldValue
        if(result) {
            println("더 큰 값이므로 값을 변경합니다.")
        } else {
            println("작은 값이므로 변경을 취소합니다.")
        }
        result
    }()
    }
}

fun main() {
    val vv = MoreBiggerInt(10)

    vv.value = 20
    println("${vv.value}")

    vv.value = 5
    println("${vv.value}")
}

실행 결과는 다음과 같습니다.

더 큰 값이므로 값을 변경합니다.
20
작은 값이므로 변경을 취소합니다.
20