ViewPager 완전정복 - addOnPageChangeListener에 대해서

Posted by ITPangPang
2016. 11. 5. 13:18 안드로이드(android)/ViewPager


ViewPager 완전정복

addOnPageChangeListener에 대해서



ㆍ 이번글에서는 addOnPageChaneListener에 대해서

    알아보도록 하겠습니다.


ㆍ 간단하게 addOnPageChangeListener가 뭐하는 놈인지

    알아보도록 하고 호출되는 부분마다 로그를 달아 

    맨땅에 헤딩하면서 테스트해보도록 하겠습니다.



addOnPageChangeListener를 언제 쓰나?

    

가장 중요한 부분이겠죠

어떤 상황에서 이걸 쓰나?


말 그대로 뷰페이져를

구성했는데


뷰페이져 내부에 존재하는

페이지의 변화가 생겼을때

호출되는 부분입니다.


Swipe를 하던, 버튼을

눌러서 다른 페이지로

이동시키던, 페이지가 움찔 하는순간

호출되는 메서드라고 생각하시면

됩니다.


어쨋든 이것을 활용하면


가장 익숙한

화면이 아닐까 생각됩니다.


빨간 박스에 있는 마커가 보이시죠?

addOnPageChangeListener를 사용해서

위와 같은 효과를 낼 수 있습니다

(이 부분도 나중에 만들어 볼 예정)


이 외에도 페이지의 과정을

나타내는 ProgressBar라던가

Seekbar를 ViewPager의

ChangeListener와 연결하여

변화가 있을때 진행상황을

파악할 수 있습니다.


또는

눈에 보이진 않더라도

뷰페이져에서 페이지

전환할 때마다 어떤 데이터를

서버에 보내야 할 때,


또는 전환할때마다

해당 페이지에 있는 데이터를

마지막 페이지에 보내야 하는 경우.


등등 사용해야 하는 상황은 다양합니다.



일단 써보자!


일단 프로젝트는

2(3)번째 글에서 사용했던

탭 꾸미기 프로젝트를

그대로 가져다가 사용해보도록

하겠습니다.

(탭 효과내면서 addOnPage~ 사용해보긴 했었죠)


이전글에서

미리 만들어둔 위의 화면을

사용해서

알아보도록 하겠습니다


코드를 보자면

vp = (ViewPager)findViewById(R.id.vp);
vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{

}

@Override
public void onPageSelected(int position)
{
int i = 0;
while(i<3)
{
if(position==i)
{
ll.findViewWithTag(i).setSelected(true);
}
else
{
ll.findViewWithTag(i).setSelected(false);
}
i++;
}
}

@Override
public void onPageScrollStateChanged(int state)
{

}
});


이 코드를 사용했었죠

onPageSelected(int position)

있는 부분은 탭 선택효과를 내는

코드였는데 일단 지워보도록 하고


각 메서드마다 로그를 다시 달아보도록

하겠습니다.

vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
Log.d("ITPANGPANG","onPageScrolled : "+position);
}

@Override
public void onPageSelected(int position)
{
Log.d("ITPANGPANG","onPageSelected : "+position);
}

@Override
public void onPageScrollStateChanged(int state)
{
Log.d("ITPANGPANG","onPageScrollStateChanged : "+state);
}
});


이렇게 달아보고 페이지에

변화를 주면서 찍힌 Log값

확인해보면 되겠죠?



자 먼저 탭을 눌러서

페이지를 이동시켜보겠습니다


뭔가 막 찍혔는데

자세히 보기전까지는

잘 모르겠죠?


하나하나 보겠습니다.


[1페이지] ->[2페이지] 이동


먼저

onPageScrollStateChanged

대하여 설명하자면


이 놈은 포지션(페이지 위치)과는

전혀 상관이 없습니다


위의 로그찍은걸 보면

매개변수값으로 state값을

받습니다.


그냥 페이지의 상태자체입니다

state는(0,1,2) 총 3가지 값이 존재합니다.


0 : SCROLL_STATE_IDLE

1 : SCROLL_STATE_DRAGGING

2 : SCROLL_STATE_SETTLING


IDLE = 뜻은 가동되지 않은

(즉 종료시점이라고 볼 수 있겠죠)


DRAGGING = 뜻 그대로 드래그 되고 있다

(Swipe 될 때 호출됩니다. 조금 있다가 확인)


SETTLING = 뜻은 고정(정해졌다)이라는 뜻이죠



위에 사진을 보면

0과 2만 찍힌 것을 알 수 있는데


사용자가 Swipe로 화면을 끄는것이 아니라서

1(DRAGGING)은 찍히지 않습니다.


0 -> 2 : 두번째 탭을 누르는 순간

탭은 확실히 2번째라고 결정났으니

(0을) 먼저 찍어주고

그 다음 가동이 종료되면

(남은 페이지 넘어가는효과(스크롤되는중)가 없는 순간)

2번을 찍어줍니다.


onPageSelected


역시나 Log찍은 코드를 보면

매개변수로 position을 받습니다.


즉, 선택된 페이지를 알려줍니다.

위에 사진을 다시 보면

onPageScrollStateChanged : 2

바로 다음에 onPageSelected : 1

가 찍힌 것을 확인 할 수 있습니다.


onPageSelected는

ScrollStateChanged = 2라고

결정난 후에야 호출됩니다.

2라는 뜻이 무조건 그 페이지가 선택되었다

고정(정해졌다)이라는 뜻이므로

그때서야 포지션에 맞게 로그를 찍어주는 것입니다.

(단 Swipe가 아닌 선택으로 넘겼을때) - 조금 있다가 설명


onPageScrolled


스크롤 효과가 나는 동안 계속해서

호출되는 부분입니다


position(0) = 첫번째 탭이었다가

position(1) = 두번째 탭으로 이동되는 순간

1로 변하는 것이죠.


다음 사진을 보면서 다시 정리해보겠습니다


[2페이지] - [3페이지]


3번탭을 눌러서 3페이지로 가는

과정을 쭉 말해보자면


[세번째 탭 선택]

Swipe가 아니기 때문에

누르는 순간 3번탭으로 가는것은

결정됩니다(변할리 없죠)


onPageScrollStateChanged(2)

이게 나오면 바로


onPageSelected

얘도 따라나옵니다.

3페이지 선택되었기 때문에

position : 2를 내뱉습니다

(단 Swipe가 아닌 선택으로 넘겼을때) - 조금 있다가 설명


onPageScrolled

3페이지로 넘어갔을때! 2를 찍어줍니다


onPageScrollStateChanged(0)

onPageScrolled(스크롤 효과)가 끝났다

싶으면 이제 가동되지 않는구나 판단하고

0을 찍어주면서 마무리 하게 됩니다


이번에는 Swipe(드래그)를 통해서

페이지를 이동시켜보겠습니다


뭔가 조금 더 요란스럽죠?

역시나 하나하나 보면서

알아봐야 될 것 같습니다.


[1페이지] ->[2페이지] 이동


살짝 Swipe 했는데도

Log가 한화면에 안찍혀서

두개를 일단 붙였습니다..


일단 보면 아까 위랑 비슷하긴 합니다.

대신 처음 시작할때


onPageScrollStateChanged(1)

로 시작하게 됩니다


DRAGGING이 시작되는 시점이죠

그리고


사용자가

손가락을 화면에서 대고있는순간

까지는 onPageScrollStateChanged

호출이 되지 않습니다.


그러다가 딱 손을 떼는순간!

페이지가 결정 나기 때문에


onPageScrollStateChanged(2)

가 찍히게 됩니다.


그리고 저절로 아까 본 과정과 같이

selected가 찍히고 마지막에

statedChanged(0)가 찍히면서

마무리 하게 되는거죠



[2페이지] ->[1페이지] 넘기려 시도(실패) ->[2페이지]


위 GIF 끝부분에서 보면 선택과 달리

Swipe로 통한 이동은 페이지 변화가

일어나지 않을 수가 있습니다.


2페이지에서 1페이지로

넘기는데 갑자기 실패해서

다시 2페이지로 돌아가는 과정이죠.


자 일단 슥~ 보면

가장 중요한 부분이 나옵니다.


onPageSelected를 찾아볼 수 없습니다

아시는분은 알겠지만 그 이유는

페이지의 변화!가 없었기 때문입니다.

onPageSelected는 페이지의 변화가 생겼을때

호출되는 메서드입니다.


나머지는

쭉 보면

역시나 똑같습니다


onPageScrollStateChanged(1)

= DRAGGING 시작


onPageScrolled(0) ->onPageScrolled(1)

= 이전과 다음페이지 갈때 살짝 다른데

position이 -될때는 미리 눈에 보이는(이전페이지)

 position값을 scrolled에 찍어주다가

최종적으로 페이지가 고정(결정)되고

가동이 중지되기 전에 결정된 페이지의값을

찍어주게 됩니다


onPageScrollStateChanged(2) -> onPageScrollStateChanged(0)

페이지가 결정되고 가동이 중단되는 순간

( 이 과정에서 selected, 페이지 변화가 없으니 호출이 안되고

가동중단(0) 직전에 바로 onPageScrolled(최종페이지)가 찍힙니다 )



이 정도면 어느정도

addOnPageChangedListener가 뭐하는놈인지

그리고 그 안에 존재하는 각각의 메서드들이

언제 호출되는지

기본정도는 파악했다고 생각됩니다


이것을 토대로 개발자들이 어느 메서드가

어떤 처리를 해줘야 할지 결정해주면 되겠죠?


ViewPager를 사용하면서 페이지 전환도


버튼처리로만 페이지 이동

Swipe만 페이지 이동

둘 다 허용


아니면 다음페이지로만 이동가능

(이전페이지 돌아가기 막기)


등등에 따라 어떻게 처리줘야 할지

그때그때 때에 따라 다릅니다.


다음 글은 아마...

addOnPageChangeListener 예제 또는.


- VerticalViewPager, HorizontalViewPager 

둘 중에 하나가 될 것 같습니다.


사실 위에서 처음 

보여줬던 marker를 해보고

싶긴 한데, 조금 코드가 복잡할 수도 있어서

예제를 하게 된다면 progress나 seekbar와

연결해서 사용하는 것에 대해 쓰게 될 것 같습니다


이것으로 끝!

(저도 공부하면서 쓰는 것이기 때문에

틀린 부분은 알려주시면 감사하겠습니다)