[Tip] 액션바 오버플로우 메뉴 버튼이 보이지 않고, 하드웨어 메뉴 버튼을 눌렀을 때 메뉴가 아래 위치에 출력되는 것을 해결.
무슨 이야기냐 하면은...
우선 아래 두 개의 스샷을 보자.
왼쪽은 넥서스S , 오른쪽은 갤럭시 S2 다. (모두 4.1.1 버전이다. )
이 두 녀석처럼 하드웨어 버튼을 갖고 있을 경우 액션바(Actionbar) 상의 오른쪽에 오버플로우(Overflow) 메뉴 버튼을 띄워주지 않고, 하드웨어 버튼을 누를 경우 우측 사진처럼 아래에 메뉴창을 띄워준다. 전형적인 메뉴 버튼 달린 기기 스타일이다. (요즘 기기들은 하드웨어 메뉴 버튼이 사라지고 액션바 오버플로우 버튼이 그 자리를 대신한다.)
참, 중요한 사실은 그동안 3.x 이하 버전에서도 액션바를 제대로 지원하기 위하여 Support Library 를 사용 할때는 문제가 없었다. 하지만 최소 버전을 4.0 이상으로 설정하면서 SDK 내부의 기본 API 를 사용하게 되면서 발견하게 되었다. 물론 이렇게 동작하는 것이 맞다. ㅡ , ㅡ;; 안드로이드 디자인 가이드(관련 내용 링크 : 한글 번역, 원문)에도 하드웨어 메뉴 버튼이 달려 있을 경우 오버 플로우 메뉴가 아래에서 올라온다고 되어있다. ...왜 이렇게 만든거여...
다행히도 아주 기발한 해결책이 존재한다.
만약 하드웨어 메뉴 버튼이 존재할 경우에 다음과 같은 코드를 Activity 상에서 호출하면 true 값을 반환한다.
boolean isHardwareMenuButton = ViewConfiguration.get(this).hasPermanentMenuKey();
이 설정을 public method 를 통하여 직접 바꿀수는 없다. 하지만 ViewConfiguration 내에서 private 으로 선언된 static boolean 타입의 sHasPermanentMenuKey 필드를 리플렉션을 이용하여 직접 false 로 바꿔줌으로써 해결할 수 있다. 자바 짱짱맨.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { ViewConfiguration config = ViewConfiguration.get(this); Field menuKeyField = ViewConfiguration.class. getDeclaredField("sHasPermanentMenuKey"); if(menuKeyField != null) { menuKeyField.setAccessible(true); menuKeyField.setBoolean(config, false); } } catch (Exception ex) { // 무시한다. 3.x 이 예외가 발생한다. // 또, 타블릿 전용으로 만들어진 3.x 버전의 디바이스는 보통 하드웨어 버튼이 존재하지 않는다. } }
onCreate 이벤트 내부에서 사용하면 된다.
결과...
(좌측은 넥서스s 우측은 갤럭시 s2 )
물론 하드웨어 메뉴 버튼을 눌러도 오버 플로우 메뉴는 열린다.ㅎ
출처 및 참고 :