ViewPager addOnPageChangeListener 관련 문제

Posted by ITPangPang
2016. 10. 8. 01:58 안드로이드(android)/개발중 생긴일


ViewPager

addOnPageChangeListener

관련 문제



이번글은 그냥 정보글이라기 보다는 개인적으로 잊어버리지

    않기 위해 끄적여 봅니다.


ㆍ 오늘 개발중에 addOnpageChangeListener를 쓰다가

    잘 안풀리는 부분이 있었는데 대충대충 어찌저찌 막았던

    부분..



addOnPageChangeListener


ViewPager를 쓰다보면

위에 있는 addOnPageChangeListener

써야 할 경우가 생깁니다.


저게 무엇인가

코드로 모양만 잠시보자면

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {

}

@Override
public void onPageScrollStateChanged(int state) {

}
});


모양은 이렇게 생겼습니다.


대충 살짝 보면 느낌이 오시는분도

있겠지만


위에서 두가지만 보자면


먼저

 onPageScrolled(int position ~)

이 부분은 사용자가

손가락으로 Swipe를 하던지

아니면 setCurrentItem을 하던지

해서 페이지를 넘기는 과정에서

호출되는 부분입니다


한페이지 넘어갈때마다

한번 호출되는게 아니라

한페이지 넘어가는 순간에도

순간순간 호출이 됩니다

아래 나올 onPageSelected와 다른점입니다

드래그 할때마다 계속 호출됩니다.


그 다음

onPageSelected(int position ~)

이 놈은 페이지가 변경됬을때

한 번 호출됩니다.



하이고 어쨋든.

오늘 어떤 문제점이 있었는가

하면..


앱이 대충 이렇게 되있는데

그 중에 한 탭이


ViewPager를 이용해서

2페이지로 되있고


그 중에 2번째 페이지안에는

동적뷰페이져가 또 있습니다


즉 동적뷰페이져란 말은

페이지가 몇개가 될지 모릅니다

1개가 될지 100개가 될지..

(Page1에서 넘어오는 결과에 따라

생성되는 페이지가 다른.. 뭐 그런)


어쨋든 저 동적뷰페이져에

단어가 나오는데

페이지를 넘길때마다

페이지에 찍혀있는 단어를

TTS로 읽어주는 기능을

만들고 있었습니다.


그래서 뭐

@Override
public void onPageSelected(int position) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
tts.speak(position에 있는 단어, TextToSpeech.QUEUE_ADD, null, null);
}
else
{
tts.speak(position에 있는 단어, TextToSpeech.QUEUE_ADD, null);
}
}


이렇게 써줬죠

페이지가 변경될때마다

그 페이지에 찍혀있는

단어를 들려줘라!!


당연히 간단한 문제라고

생각하고 앱을 실행시켜봤는데


2가지 문제점이 발생하였습니다.


첫번째

position(0)

즉 1페이지 처음 넘어왔을때

호출이 안된다.


두번째

Fragment에서 나왔을때

이상하게  현재 position+1에

있는 단어가 갑자기 스피커로

나온다.


첫번째 문제는

테스트 하자마자 바로

어떤 문제인지 알았습니다.


onPageSelected는

뷰페이져의 변화가

있을때 호출되는데


첫번째 페이지에서는

그냥 생성만 됬을뿐

다른 변화가 없다보니

당연히 호출이 안됩니다


이를 해결하기 위해서

그냥 서치도 안해봤지만..


최초 한번 1페이지가

생성될때 첫번째 페이지에 있는

단어를 읽도록

따로 적어줬습니다


@Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
super.setUserVisibleHint(isVisibleToUser);
//사용자 눈에 화면이 보이는 순간 값들을 뿌려준다
if (isVisibleToUser)
{
new Handler().postDelayed(new Runnable()
{
@Override
public void run()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
tts.speak(첫번째 단어, TextToSpeech.QUEUE_ADD, null, null);
}
else
{
tts.speak(첫번째 단어, TextToSpeech.QUEUE_ADD, null);
}
}
},500);
}
}


setUserVisibleHint..

예전에 살짝 블로그에

올린 기억이 있긴 한데


Viewpager를 사용할때

자주 사용되는 부분입니다


뷰페이져는

해당 페이지 전, 후페이지를

미리 생성하고 있는

특성이 있는데


이렇게 되면

1페이지에서 변경한 내용이

2페이지로 넘어갔을때

적용이 안되는 현상이 있습니다


미리 그려놨기 때문이죠


그것을 방지하기 위해


위에 처럼

setUserVisibleHint를

사용하면


페이지가 사용자눈에

들어왔을때 그 동시에

뷰를 그릴수도 있고

원하는 이벤트를 줄 수도있습니다.


어쨋든 저런식으로

1페이지의 단어가 사용자

눈에 들어왔을때 그 단어를

바로 읽어주도록 위에 코드를

추가해서 해결하였습니다.


두번째

Fragment에서 나왔을때

이상하게  현재 position+1에

있는 단어가 갑자기 스피커로

나온다.


이 부분은

지금도 왜그런지

모르겠지만..


위에 사진을 다시 가져와보면


동적뷰페이져(Page2)에서

페이지마다 TTS가 잘 동작하여

발음이 잘 들리던 중에


이전버튼을 눌러 Page1으로

이동하거나 위에 탭을 눌러서

다른 Fragment로 이동했을때


이상하게도 영단어가 한 5초뒤에

디바이스 스피커로 흘러나오는겁니다.


그래서 로그를 찍어봤죠..

뭐 위에 현상 그대로

페이지에서 벗어나도

5초뒤에


public void onPageSelected(int position) {


이 놈이 자꾸 호출되는 겁니다.


그래서 뭐 어쨋든 해결은 해야되니까..

그냥 boolean값 하나 줘서

여기 페이지에 있을때만 동작해라!

@Override
public void onPageSelected(int position)
{
if(isPageState)//여기 페이지에 있을때만
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
tts.speak(position에 있는 단어, TextToSpeech.QUEUE_ADD, null, null);
} else {
tts.speak(position에 있는 단어, TextToSpeech.QUEUE_ADD, null);
}
}
}

이런식으로 바꿔주고


위에서 사용한

setUserVisibleHint를

사용해서

@Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
super.setUserVisibleHint(isVisibleToUser);
//사용자 눈에 화면이 보이는 순간 값들을 뿌려준다
if (isVisibleToUser)
{
isPageState = true;
}
else
{
isPageState = false;
}
}


이런식으로 짜주고

당연히 해결했다고

생각했습니다.


그리고

테스트 결과

Page2에서 발음을

열심히 잘 듣고


Page1으로 돌아가니

onPageSelected가 호출은 되나


if값(현재페이지에 있는가?)에

통과를 못하여 TTS가 동작하지

않았습니다


그래서 넘어갈려고 하던 순간!!

잊고 있던게 있었습니다.




Page2에서 Page1이 아닌

위에 상단 탭을 눌러서

Fragment를 Replace 시켰을때

또 다시 영어단어가 흘러나오게 됩니다..


아...

Fragment Replace시에

위에 setUserVisibleHint가

호출되지 않습니다


그래서 뭐 약간 멘붕 오긴했지만

다시 정신차리고 2번째

해결방법으로 처리했습니다


해결방법은

Page1, Page2의 부모인

해당탭 Fragment가 파괴될때

boolean값을 바꿔줬습니다.


@Override
public void onDestroyView() {
isPageState = false;
super.onDestroyView();
}


이런식으로 넣어주니

아주 잘 해결되었습니다.


뭐 버근지 뭔지 모르겠습니다.

왜 onPageSelected가 호출되는지..


아 참고로 

onPageScrolled는 호출안되고


onPageSelected 

이놈만 페이지전환후에

5초정도후에 호출이 됬습니다


어쨋든 중요한 부분은

아니므로 그냥 위와 같이

꼼수같은 방법으로

해결완료하였습니다.