티스토리 뷰
1. 내가 하고 싶은 것
( app의 디자인을 조금 바꿨다 )
다음과 같은 상황에서,
아랫쪽 TabLayout의 Item에 따라 서로 다른 독립적인, 서로 자기 갈길 가는 Fragment를 구성하고 싶다.
이때 Fragment를 어떻게 구성하면 좋을지 고민중이다.
tab마다 다른 activity를 두어서 각자의 task stack을 구성해야 되는건지.......
fragment가 돌아가는 방식에 대해 자세히 찾아봐야 할 것 같다.
< Test project를 작성 >
: unit test를 위해 새로운 project를 하나 만들었다.
2. 첫번째 문제 : fragment 겹침 오류
tab별로 다른 fragment를 뿌리는 건 쉽게 성공했는데,
첫번째 fragment의 button을 누르면 다른 fragment로 가도록 할때 계속 다음과 같은 오류가 났다.
구글링 해보니 꽤 빈번하게 나타나는 오류인듯 했다.
비유를 하자면 이런 느낌이었다.
" 오늘 밤 202호에서 숙박하게 되었는데, 거기 이미 다른 사람이 숙박중인 상태 "
" fragment가 어떤 ViewGroup에 붙을때, 기존의 fragment의 View를 모두 remove해주지 않은 상태 "
3. 오류 해결 : 'container layout'에 붙이기
사실 해당 오류가 난 이유는 ViewPager에 직접 새로운 fragment를 붙여주려 했기 때문이었다.
ViewPager에 직접 붙인다는 것은?
->모든 tab에 대해 해당 fragment를 붙인다는 뜻과 같다.
지금와서 보니 내가 원하던 결과도 아니었고, 하나의 tab에 속한 Button만 없애줬으니 다른 tab에 있는 button들은 그대로 다 남아 있기 때문에 당연히 겹침 현상이 발생할 수 밖에 없는 노릇이었다.
당시에는 'btn view를 remove했는데 왜 겹친다고 하지...?'라며 고민했다.
그래서 container(첫번째 fragment의 ViewGroup)에다가 새로운 fragment를 add하는 것으로 문제를 해결했다.
< 참고로 다음과 같은 에러가 날 경우의 보편적 해결법 >
: 체크해야 할 사항들이 몇가지 있었다.
1) 수동으로 직접 remove 해주어야 한다고 한다.
(getParent()로 parent viewgroup을 가져온 후 removeAllViews()해줘서 깨끗하게 만든 후에 붙이면 된다.)
2) 새로 추가되는 fragment의 inflation 과정에서 false를 주어야 하는 것도 꼭 체크하자!
3) 새로 추가되는 fragment객체는 ViewPager container가 아니라, 첫번째 fragment view의 container에 붙여주면 해결되긴 한다.
4. 두번째 문제 : 겹침
그랬더니 오류는 안나는데 다음과 같이 아예 겹쳐서 나오더라.
5. 해결 : background 지정
시행착오 1) 기존 fragment의 view를 remove하고 새로운 fragment를 붙임.
: 이 경우 1 -> 2로 갈때는 아무 문제 없어 보이지만, 2의 상태에서 back key를 눌러 돌아올 경우
기존의 1번 view가 사라져 있었다. (지금 생각해보면 당연한 결과였다.)
시행착오 2) 그렇다면 background color를 주면 어떻게 겹치게 될까?
그랬더니 내가 원했던 대로 동작했다. (1 - 2 - 3 - (back)2 - (back)1 )
아마도 background를 아예 지정해주지 않아서 그냥 view를 있는 그대로 겹쳐서 뿌려준것 같다.
결론적으로 이 사실을 몰라서 많이 헤맸다 :
trans.addToBackStack(null);
위 코드는 fragment의 transaction 상태를 back stack에 넣는 코드다.
(한마디로 back key를 눌렀을때 동작할 수 있도록 한단계씩 상태 저장 해놓겠다는 것)
back stack에 넣으면, back key를 눌렀을때 stack에 들어가있는 fragment transaction을 차례대로 꺼내올 수 있다.
그런데,
fragment를 backstack에 집어넣는다고 해서, 해당 fragment 화면 자체를 회수해 가는건 아니었다.
그대로 남아있고, 계속 그 위에 덮어쓰는 것이다.
(그래서 ' fragment를 붙임 -> view를 remove -> fragment를 붙임 -> back key로 되돌아옴 '의 작업을 했을때, 기존의 view가 없어져 있었던 것이다. )
참고 사항 1)
여기서 한가지 짚고 넘어가야 할 것이 BackStack이라는 녀석이다.
처음에 이해하기를, Back키로 되돌아 갈 수 있는 Fragment 의 목록- 이라고 이해를 했었는데,
이건 Fragment를 View와 같은 개념으로 생각했던 것이고, 표면적으로 그대로 말해서
"beginTransition부터 commit까지의 전환" 자체를 저장하고 있는 녀석이다.
출처 : http://hyosang.kr/363
참고 사항 2)
Back stack은 support library류에서만 작동한다?
http://soulduse.tistory.com/23
6. 세번째 문제 : 독립적 tab 동작 불가
: 이제까지 구현한 결과로는 하나의 tab에 대해서는 완벽하다. 하지만 2개의 tab은 둘다 같은 back stack을 공유하기 때문에 독립적인 구현은 아니다.
7. 해결 : back stack control, back key listener, tab call back
: 독립적인 tab의 구현을 위해 생각해본 건 다음과 같다.
1.' back stack에서 내가 원하는 fragment transaction을 선별해서 빼올 수 있으면 되겠다! '
-> fragment를 add 하거나 replace할때 back stack에 넣고 tag name으로 원하는 fragment를 콕 집어서 빼오는 구현을 해봤으나, control이 그리 만만치 않아서 원하는대로 동작시키기 까다로웠기에 다른쪽으로 생각을 해봤다.
'
2. ' 내가 back key 자체를 수동으로 control할 수 있다면 좀더 쉽지 않을까?'
-> 그래서 back key를 직접 control할 수 있는 방법을 열심히 찾아다녔다. 한마디로 back stack에게 일을 전적으로 맡기는 것이 아니라, 내가 직접 개입해서 수동으로 구현하는 것!
이 방법은 간단한데 활용도가 높고, 확장성이 높기 때문에 따로 Program Log 카테고리에 따로 정리를 해놓겠다. 모든 Fragment들마다 parent activity의 back key 콜백을 받아오기 위한 대한 리스너 달아놓는 방법을 사용한다.
back key는 control할 수 있게 되었지만 여전히 하나의 stream을 쓰고있기 때문에 독립적인 동작은 불가능했다. 최종적으로 내가 어느 tab을 보고 있는지 알 수 있어야 했다.
3. '이제는 내가 보고 있는 tab에 대한 call back만 받아올 수 있다면 원하는 구현을 할 수 있을텐데..'
-> 이 부분도 사실 참 많은 고민을 했었다.
찾아보니까 여러가지 방법이 있는듯 했지만, 가장 심플한 방법으로 setUserVisibleHint()라는 call back으로 viewpager에서 내가 보고있는 tab에 대한 call back을 받아올 수 있었다.
다음과 같이 받아오는 그 시점에서 tab1과 tab2의 가장 최근 fragment에 listener를 set해줬다.
@Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
if(isVisibleToUser)
{
// listener set
if(getContext() != null)
{
((MainActivity) getContext()).setOnKeyBackPressedListener(firstTabCurListener);
}
}
super.setUserVisibleHint(isVisibleToUser);
}
8. 완성
: 결국 구현했다.
소스 : https://github.com/uareuni/Android_KbModules/tree/master/KbTabs
참고 )
fragment 설명 자세함 : http://unikys.tistory.com/318
기본적인 transaction : http://mydevromance.tistory.com/34
fragment 겹침 오류 해결법 : http://androidhuman.com/535
back stack에서 tag name으로 빼오기 : http://www.masterqna.com/android/66724/fragment-backstack-%EC%A7%88%EB%AC%B8%EC%9E%85%EB%8B%88%EB%8B%A4?show=66728#a66728
fragment back key 받아먹기 listener : http://raphaelh.tistory.com/26
ViewPager 현재 fragment 알아오기 : https://blog.update.sh/archives/15
'개발자 배배 > Android' 카테고리의 다른 글
[Android] Activity Customer Listener :: Call back (0) | 2017.02.21 |
---|---|
[Android] dimen :: dp를 선언해서 사용할때 (0) | 2017.02.17 |
[Android] layout_weight 사용시 주의 (0) | 2017.02.16 |
[Beacon] 6. Android UI :: kakao oven mockup (0) | 2017.02.14 |
[Android] Http 작업시 주의 :: Server 주소를 못찾을 때 (0) | 2017.02.13 |
- Total
- Today
- Yesterday
- nodejs
- 책 집필
- layout_weight
- kakao oven
- ranging
- server ip
- Android
- 안드로이드
- tabLayout
- call back 뺏아오기
- monitoring
- Beacon
- 비콘
- 카카오톡 연동
- 카카오톡
- eddystone
- KAKAO
- wegith
- SQLPro
- 수업교재
- fragment 겹침
- Retrofit
- 연동
- RECO beacon
- 행복의 상대성
- 카톡
- startService
- kakaotalk
- stopService
- call back
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |