안드로이드 개발 질문/답변
(글 수 45,052)
Toast 같은 최상위 Window 를 생성하는 방법을 알고싶습니다.
안드로이드에서는 개발자가, Toast, StatusBar 같은 별도의 최상위 Window를 만들지 못하는것으로 알고있습니다.
API 도 Hidden 으로 막혀서 호출될 수 도 없구요.
혹시, 우회적인 방법으로 최상위 Window 를 만든 분 계신가요?
그리고, Toast 객체에 터치이벤트를 적용 할 수 있나요?
-------------------------------------------------------------------------------------------------
제가 의도했던 부분을 추가로 적겠습니다.
최상위 객체를 만듬으로서, Activity 가 Pause 되더라도, 최상객체는 여전히 화면에 보이게 하길 원합니다.
즉, Activity 가 Pause 될때.. 이전의 App 가 있었다면, 이전의 App 위에 최상객체가 나타나야 되겠구여,
만약 전에 띄웠던 App 이 없다면, 홈 이나 App 들이 보이는 화면위에 최상객체가 나타날 겁니다.
그리고 최상객체가 떠있는 상태에서 다른 App 을 클릭했을때, 다른 App 이 뜰테지만 여전히 그 위에는 최상객체가
나타날 겁니다.
즉, 다른 App 이 떠서, Activity 가 Pause 상태가 되더라도, 그애 구애받지 않는 최상위 객체를 만들고 싶습니다.
StatuBar 나 Toast 처럼요..
Toast Core 소스를 분석해보니, WindowManagerImpl 객체에 addView() 를 함으로서 최상위 Window 기능을
하는것으로 보여져, CustomClass 에도 WindowManagerImpl 을 사용해 보려 했지만 Hide 처리 되있어서,
가져다 쓸수 없었습니다.
그래서 차선책으로 Toast Core 소스를 커스터마이징 하거나 상속받아서 사용해 보려 했지만, 수정하는데에
한계가 있어서, 현재 작업이 정지된 상태입니다.
Hide 된 WindowManagerImpl 을 가져다 쓸수도 있다라고, 어떤 블로그에서 봐서요. 혹시 방법을 아시는 분이나
다른 기법으로 개발 성공하신 분들이 있다면, 조언 부탁드릴려고 합니다.
---------------------------------------------------------------------------------------------------
공지사항을 다 읽었음
2010.08.27 17:58:06
안녕하세요. 옵션메뉴 방법을 알려주셔서, 정말 감사드려요.
유용하게 쓸수 있는 방법이네요.
근데, 하나만 여쭤봐도 될까요??? 제가 위 코드를 테스트 해보니, Activity 에 종속적이서서, 해당 Activity 가 pause 되거나 destory 될때,
VIEW 도 같이 사라지드라구요. Toast 같은 경우 독립된 Window 에서 보여지기 때문에, Activity 가 pause 되더라도 사라지지 않을수 있구요(연속적인 show() 호출로...). Toast 처럼 Activity 가 pause 될때도 보여지도록 할 수 있을까요??
혹시, 위에서 말씀하신부분중에, "뷰가 사라지는 이벤트를 반드시 제대로 구성하셔야..." 라고 말씀하신게 Activity 와 연관된 의미인건가요??? 마지막에 써주신 2줄(사실상... 안눌릴겁니다.) 이 잘 이해가 안되서요...
또 질문드려서 죄송하구요, 다음에는.. 제가 도움주는 사람이 되도록 할게요..^^;
부탁드려요..
2010.08.27 18:37:12
저게 윈도우에 뷰를 추가하는 방식인데.... 저 중에 어떤 플래그가 영향을 주는지 몰라도...
저 뷰가 떠있는 동안에 다른 뷰는 이벤트를 받지 않습니다.
설사 뷰가 화면의 일부만 가린다 하더라도 말이죠.
저거 테스트 저도 안해봤는데 한번 해보세요..
실행후 3초 후에 띄우기로 하고 실행하자마자 홈으로 눌러보면 되죠...
근데 결국 윈도우를 액티비티에서 가져오는 모양새니까... 액티비티에 종속적인 것으로 보이긴 합니다.
윈도우 매니저를 getSystemService 던가.. 그걸 통해서 가져온다면 또 다른결과가 나오는지는 모르겠네요.
저 뷰가 떠있는 동안에 다른 뷰는 이벤트를 받지 않습니다.
설사 뷰가 화면의 일부만 가린다 하더라도 말이죠.
저거 테스트 저도 안해봤는데 한번 해보세요..
실행후 3초 후에 띄우기로 하고 실행하자마자 홈으로 눌러보면 되죠...
근데 결국 윈도우를 액티비티에서 가져오는 모양새니까... 액티비티에 종속적인 것으로 보이긴 합니다.
윈도우 매니저를 getSystemService 던가.. 그걸 통해서 가져온다면 또 다른결과가 나오는지는 모르겠네요.
2010.08.27 18:52:37
토스트 소스는 별게 없는데요... 제가 보여드린 소스와 흡사하네요....
WindowManagerImpl.getDefault(); 제가 보기엔 이게 핵심인데
가려져있는게 안타깝네요...
결국 토스트처럼 다 넘나들기 위해서는 윈도우 자체를 디폴트 윈도우로 가져와야 한다는 간접적인 결론인데요...
Activity 소스 보니까 getSystemService를 통해서 window manager 받아도 그넘이 그넘이네요 ㅡㅡㅋ
WindowManagerImpl.getDefault(); 제가 보기엔 이게 핵심인데
가려져있는게 안타깝네요...
결국 토스트처럼 다 넘나들기 위해서는 윈도우 자체를 디폴트 윈도우로 가져와야 한다는 간접적인 결론인데요...
Activity 소스 보니까 getSystemService를 통해서 window manager 받아도 그넘이 그넘이네요 ㅡㅡㅋ
2010.08.27 20:23:50
WindowManagerImpl을 가져다 쓰는 방법은 있네요... 리플랙션입니다.
근데 뭐 언제까지 통할지 알수 없는 방법이라서 추천은 못하겠네요. 일단 지금은 됩니다.
(옵티머스Z에서 테스트 했습니다.)
근데 뭐 언제까지 통할지 알수 없는 방법이라서 추천은 못하겠네요. 일단 지금은 됩니다.
(옵티머스Z에서 테스트 했습니다.)
try { Class clsWindow = Class.forName("android.view.WindowManagerImpl"); Method m = clsWindow.getMethod("getDefault", null); final WindowManager wm = (WindowManager)m.invoke(null, null); final TextView tv = new TextView(this); tv.setText("aaa"); final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; params.format = PixelFormat.TRANSLUCENT; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setTitle("Toast"); wm.addView(tv, params); mHandler.postDelayed(new Runnable() { public void run() { // TODO Auto-generated method stub wm.removeView(tv); } }, 3000); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); }
옵션 메뉴(메뉴 눌러서 나오는 뷰)정도의 뷰는 만들어서 추가할 수 있습니다.
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FILL_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT,
0,
mWindow.getDecorView().getHeight()-height,
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
WindowManager.LayoutParams.FLAG_DITHER| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
android.graphics.PixelFormat.TRANSLUCENT);
getWindw().getWindowManager().addView(view, lp);
원래 위에있는 layoutParams는 실제 옵션 메뉴에서 쓰는 것을 가져와서 좀 고친겁니다.
(그래봐야 wrap_content, fill_parent 정도...)
사실상 다이얼로그 수준이고 뷰가 사라지는 이벤트를 반드시 제대로 구성하셔야 테스트 할때 좋을겁니다.
뷰 안사라지면 뒤에 아무것도 안눌릴겁니다.