IT_Programming/JavaScript

[펌] 안드로이드 레이어 이벤트 투과 문제

JJun ™ 2015. 1. 23. 10:43



 출처: http://jindo.dev.naver.com/blog/2015/01/733


오늘 다룰 내용은 초창기 android stock browser에서 발생했던 버그에 대한 이야기이다.

결론부터 이야기를 하면,  Android 4.0 이하를 지원할 필요가 없는 개발자라면  이 글을 스킵해도 좋다.

하지만, 자신이 개발해야 할 서비스의 지원범위가 Android 4.0이하를 지원해야만 하는 상황이라면,
꼭! 읽어보기 바란다. 정말로, 필자가 X삽질해서 얻은 금쪽같은 workaround이다. ^^;;


 

문제 : “레이어를 누르면 뒤 링크가 눌러져요”

사용자는 레이어를 선택했지만, 브라우저가 반응하는 것은 레이어의 뒷면에 있는 엘리먼트를 선택한 것과 같이 반응하였다.

아래 그림을 보면 보다 이해가 쉬울것이다.


그림 – 안드로이드 이벤트 투과 버그

 

실제 사용자는 증권 이벤트 레이어를 선택했지만, 이벤트 레이어 뒤편에 있는 목록의 내용이 선택되어,

하이라이트 되고, 심지어 클릭까지 되었다.

이러한 버그는 Android 4.0이하에서 발생하였다. Android 2.x는 모두 위 버그가 발생했으나, Android 4.0 버전은 제조사나 단말기에 따라 발생하는 상황이 조금은 차이가 있었다. 하이라이트만 보이고, 클릭이 안되는 경우, 또는 클릭만 되는 경우, 등 다양한 버그가 발생하였다.

다행히, 안드로이드 4.1부터는 이 버그가 해결이 되어, Android 4.1이상을 지원하는 사이트일 경우, 이 문제에 대해 고민할 필요가 없다.

하지만, 네이버와 같이 다양한 사용자를 대상으로 서비스를 제공 하는 곳에서는 Android 2.x~4.0 까지의 사용자도 무시 못할정도로 많기 때문에 이 부분에 대한 버그처리를 해야한다.

 

문제 해결 방법 (Workaround)

띄우고자하는 레이어 밑으로 회색 바탕의 딤드 레이어를 사용하는 방법이다.

여기서 중요한 점은 딤드 레이더를 position:absolute로 화면에 딱 맞게 만들게 되면 동일한 문제가 발생한다.

workaround는다음 2가지 조건을 만족해야한다.

1. 딤드레이어 css

position:absolute가 아닌 position:relative로 구성하고, 화면 영역 보다 2배 이상 큰 크기의 딤드 레이어를 만들어서 margin-top으로 위치를 이동하는 방법이다.

2. 초기 로딩시 딤드레이어가 화면에 노출되어야한다.

이 코드는 초기 딤드레이어 노출시 시각적으로 인식되지 않도록 딤드레이어의 background-color를 노출시, rbga(0,0,0,0)으로 지정하고, window.onload시에는 다시 background-color를 원하는 색상으로 바꾸어준다. 이때, 중요한 것은 setTimeout(func,0)으로 랜더링 작업을 끊어줘야 문제가 해결된다.

 

최종 코드

workaround를 적용한 코드는 다음과 같다.

 

 [HTML]


 <!DOCTYPE html>

 <html>

 <head>

   <meta charset="utf-8">

   <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no,target-densitydpi=medium-dpi">

   <title>안드로이드 2.x대 투과 문제</title>

 </head>

 <body>

    <div><br><br><br>

      전 레이어 뒤에 있는 컨텐츠입니다.<br><br>

      <a href="http://m.naver.com">move to Naver.</a><br>

      <a href="http://m.naver.com">move to Naver.</a><br>

      <a href="http://m.naver.com">네이버로 이동합니다.</a><br>

      <a href="http://m.naver.com">네이버로 이동합니다.</a><br>

      <a href="http://m.naver.com">네이버로 이동합니다.</a><br>

      <a href="http://m.naver.com">네이버로 이동합니다.</a><br>

      <a href="http://m.naver.com">move to Naver.</a><br>

      <a href="http://m.naver.com">move to Naver.</a><br><br>

      <button onclick="show();">show layer</button>

    </div>

    <div class="dimm"></div>

    <div class="layer"> 전 레이어입니다. <button onclick="hide();">hide layer</button>

    </div>


 <script>

   var elLayer = document.querySelector('.layer'),

   elDimm = document.querySelector('.dimm');


   function hide() {

     elLayer.style.display = 'none';

     elDimm.style.display = 'none';

   }


   function show() {

     elDimm.style.display = 'block';

     elLayer.style.display = 'block';

   }


   window.onload = function() {

       setTimeout(function() {

           hide();

           elDimm.style.backgroundColor = "#000";

       },0);

   }


 </script>


 </body>

 </html>


 

 [CSS]

 

body {

  position:relative;

  height:500px;

  margin:0;

  padding:0;

  background-color: rgba(227, 236, 226, 1);

}

.layer {

  position:absolute;


  background-color: rgb(225, 199, 199);

  display:none;

  top:20px;

  left:20px;

  border : 1px solid red;

  height : 360px;

  width : 80%;

  padding : 10px;

  color : red;

  z-index : 10001;

}

.dimm {

  position:relative;

  width:100%;

  height:7000px;

  margin-top : -5000px;

  background-color: rgba(0,0,0,0);

  opacity :0.5;

  z-index : 10000;

}




Demo : http://jsbin.com/nimob/5 

실제 서비스에 적용된 화면은 다음과 같다.


그림 – workaround가 적용된 네이버 서비스