웹뷰에서 스크롤을 감지하여 모션레이아웃을 실행해야하는 상황이 생기면서 검색을 해보면서 해결했던 것을 기록하고자 합니다.
리스너는 총 세가지를 만듭니다.
먼저 웹뷰를 상속받은 커스텀 뷰를 만들어줍니다.
class CustomWebView @JvmOverloads constructor(
context: Context,attrs:AttributeSet?=null,defStyleAttr:Int = 0
):WebView(context,attrs, defStyleAttr)
interface CustomWebViewListener{
fun bottomEndReached(isEnd:Boolean)
fun onScrollDown()
fun onScrollUp()
}
private var bottomReached = false
private var listener:CustomWebViewListener?=null
fun setScrollListener(mListener: CustomWebViewListener){
try{
listener = mListener
}catch (e:ClassCastException){
e.printStackTrace()
throw ClassCastException()
}
}
인터페이스를 만들고 리스너 세터,그리고 클래스 변수로 선언해줍니다.
그리고 onScrollChanged를 override해줍니다.
override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
if(this.computeVerticalScrollRange() <= (this.computeVerticalScrollOffset() +
this.computeVerticalScrollExtent() + this.paddingOffset)) {
if(!bottomReached) {
bottomReached = true
listener?.bottomEndReached(true)
}
} else {
if(bottomReached) {
bottomReached = false
listener?.bottomEndReached(false)
}
}
super.onScrollChanged(l, t, oldl, oldt)
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
when(event?.action){
MotionEvent.ACTION_DOWN -> {
oldY = event.y
}
MotionEvent.ACTION_MOVE ->{
if(event.y > oldY){
listener?.onScrollDown()
}
if(event.y < oldY){
listener?.onScrollUp()
}
}
}
return super.onTouchEvent(event)
}
onTouchEvent를 override해줍니다.
클래스 변수인 oldY를 현재 Y랑 비교하여 리스너를 실행해줍니다.
binding.wv.setScrollListener(object:CustomWebViewListener{
override fun bottomEndReached(isEnd: Boolean) {
binding.btn.btn.isEnabled = isEnd
}
override fun onScrollDown() {
Timber.d("on Scroll down")
binding.root.transitionToStart()
}
override fun onScrollUp() {
binding.root.transitionToEnd()
}
} )
액티비티나 프래그먼트에서 익명 객체로 리스너를 생성해주면 정상적으로 동작하게 됩니다.
추가적으로 모션레이아웃을 xml이 아닌 코드에서 실행하려면 transitionToStart or end를 실행해주면 됩니다.