모바일웹 키보드 화면가림 - mobail-web kibodeu hwamyeongalim

이건 안드로이드 운영체제에서 되지 않습니다, 안드로이드 브라우저에서는 키보드가 열리면 window.visualViewport.height와 window.innerHeight가 함께 줄어듭니다.

오늘은 그런 걸 만들었습니다. 일전에 사용자가 HTMLTextAreaElement에 글을 작성할 때, 컨텐츠의 길이에 따라 <textarea>의 높이를 조절하는 Vue 지시자를 만든 적이 있는데, 우리가 만든 앱은 모바일 레이아웃에 바텀 고정인 내비게이션이 있어, 온스크린 키보드가 있으면 사용자 입력 창의 커서와 컨텐츠를 가리게 됩니다. 요구사항은 화면에 키보드가 열려있는 경우에는 바텀 내비게이션을 없애라.

안타깝게도 키보드 토글에 대한 Javascript 이벤트는 없습니다. (이 포스트를 쓰는 지금도 나는 믿을 수가 없습니다.) 다만 웹 브라우저들은 VisualViewport API를 제공하고, iOS에서는 키보드가 열리고 닫힐 때에 이 값이 변하므로 그것을 빌려 쓸 수 있을 것만 같습니다. 참고로 상단 툴바가 사라지고 나타날 때에도 이 비쥬얼 뷰포트의 크기가 변하지만, 그때에는 윈도우의 innerHeight와 visualViewport.height가 다르지 않습니다. 앗, 그렇습니까? 그러면

if ("VisualViewport" in window) {
  visualViewport.addEventListener("resize", handleResize);
  function handleResize(event) {
    const {height: visualViewportHeight} = event.target;
    const eventName =
      Math.ceil(visualViewportHeight) < window.innerHeight
        ? "keyboardopen"
        : "keyboardclose";
    emitEvent.call(event, eventName);
  }
  function emitEvent(name) {
    window.dispatchEvent(
      new CustomEvent(name, {
        detail: {
          originalEvent: this,
        },
      })
    );
  }
}

visualViewport의 높이가 window의 내부 높이보다 작을 때에 키보드가 열린 것이라 가정합시다.

  1. (주의) 온스크린 키보드(혹은 가상 키보드라 부르는)만이 비쥬얼 뷰포트의 높이를 더 작게 만드는 UI 요소라는 것을 장담할 수는 없습니다.

  2. (정보) visualViewport의 높이는 double이고, window의 높이는 integer이기 때문에, visualViewport의 높이에 올림 처리를 합니다.

resize 이벤트에는 적당한 값의 debounce 처리를 하여, 불필요한 중복 트리거링을 방지하는 게 좋겠죠? 그러면

if ("VisualViewport" in window) {
  const debouncedHandleResize = debounce(handleResize, 100);
  visualViewport.addEventListener("resize", debouncedHandleResize);
  function handleResize(event) {
    const {height: visualViewportHeight} = event.target;
    const eventName =
      Math.ceil(visualViewportHeight) < window.innerHeight
        ? "keyboardopen"
        : "keyboardclose";
    emitEvent.call(event, eventName);
  }
  function emitEvent(name) {
    window.dispatchEvent(
      new CustomEvent(name, {
        detail: {
          originalEvent: this,
        },
      })
    );
  }
  function debounce(fn, wait) {
    let cancelId = null;
    return function debounced(...args) {
      clearTimeout(cancelId);
      cancelId = setTimeout(fn.bind(this, ...args), wait);
    }
  }
}

100ms 정도 여지를 줍니다. 잘 동작하나요? 터치 디바이스가 아니면 대체로 필요없는 코드일 테니 맨 앞에 조건을 더 추가합니다.

const {matches} = window.matchMedia("(hover: none), (pointer: coarse)");
if (matches && "VisualViewport" in window) {
  // ...
}
  1. 주 입력 장치가 hover를 허용하지 않거나, 불편하게 허용(롱탭 등), 혹은 주 입력 장치가 대략적인 정확도를 제공하는 포인터일 것을 요구합니다.

  2. 터치 디바이스 여부를 판단하는 방법은 몇 가지가 더 있겠지만 이번 포스트의 주제가 아닙니다.

(문서의 끝)

웹개발자의 기지개

웹퍼블리싱/html5

[모바일웹] 모바일상에서 input 박스에서 focus 할때 가상키보드 화면에 안뜨도록

원패이퍼 2022. 7. 23. 10:44

모바일웹상에서 html5 태그 상에서

아래의 input 박스에 focus 클릭하면 가상키보드 화면 안나오게

<input type="text" name="test" inputmode="none">

/* =========================== */

[ 개발 환경 설정 ]

개발 툴 : Edit++

개발 언어 : html, css, js, jquery

모바일웹 키보드 화면가림 - mobail-web kibodeu hwamyeongalim

/* =========================== */

/* =========================== */

[소스 코드]

    <!-- 메타 태그 정의 실시 : 줌 효과 제거 -->
    <meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=0">


    <!-- Jquery CDN 로드 : 항상 최신 버전 사용 -->
    <script src="https://code.jquery.com/jquery-latest.min.js"></script>    



    <!-- 내부 JS 지정 -->
    <script>

    	/*
    	[JS 요약 설명]
    	1. window.onload : 웹 브라우저 로딩 완료 상태를 확인합니다
    	2. window.getComputedStyle.height : 특정 객체 height 값을 px 로 확인합니다 
    	3. $(객체).css : 특정 객체 css 값을 수정합니다
    	4. 참고 : 브라우저에서 input 포커스 및 키보드 활성 시 ui 화면이 밀리거나 줄어드는 현상을 막습니다
    	*/

   	
    	
    	/* [html 최초 로드 및 이벤트 상시 대기 실시] */
    	window.onload = function() {
    		console.log("");
    		console.log("[window onload] : [start]");
    		console.log("");   		

    		/* height 값 px 조정 실시 : 가상 키보드 활성 시 ui 밀림 방지 */
    		reSizeHeight();
    	};


    	/* [각 컨테이너 크기 높이 사이즈 px로 다시 설정] */
    	function reSizeHeight(){
    		console.log("");
    		console.log("[reSizeHeight] : [start]");
    		console.log("");


    		// body height 값 확인 및 px 로 설정
    		/* var containerBody_height = window.getComputedStyle(document.body).height; //px height 값 확인
    		document.body.style.height = containerBody_height; //px 값으로 height 지정
    		console.log("");
    		console.log("[reSizeHeight] : [containerBody_height] : " + containerBody_height);
    		console.log(""); */


    		// 특정 객체 id 값 사용해 height 값 확인 및 px 설정
    		var containerDiv_height = window.getComputedStyle(document.getElementById("containerDiv")).height; //px height 값 확인
    		document.getElementById("containerDiv").style.height = containerDiv_height; //px 값으로 height 지정
    		console.log("");
    		console.log("[reSizeHeight] : [containerDiv_height] : " + containerDiv_height);
    		console.log("");


    		// 객체 class 값 사용해 height 값 확인 및 px 설정
    		var containerClass_height = $(".containerClass").height();
    		containerClass_height = containerClass_height + "px"; //px height 값 확인
    		$(".containerClass").css("height", containerClass_height); //px 값으로 height 지정
    		console.log("");
    		console.log("[reSizeHeight] : [containerClass_height] : " + containerClass_height);
    		console.log("");


    		// display none 상태인 팝업창 height 값 확인 및 px 설정
    		var containerPopup_height = $("#containerPopup").height();
    		containerPopup_height = containerPopup_height + "px"; //px height 값 확인
    		$("#containerPopup").css("height", containerPopup_height); //px 값으로 height 지정
    		console.log("");
    		console.log("[reSizeHeight] : [containerPopup_height] : " + containerPopup_height);
    		console.log("");
    	};
    	
    </script>

/* =========================== */

/* =========================== */

[결과 출력]

모바일웹 키보드 화면가림 - mobail-web kibodeu hwamyeongalim

/* =========================== */

/* =========================== */

[요약 설명]

/*

[JS 요약 설명]

1. window.onload : 웹 브라우저 로딩 완료 상태를 확인합니다

2. window.getComputedStyle.height : 특정 객체 height 값을 px 로 확인합니다

3. $(객체).css : 특정 객체 css 값을 수정합니다

4. 참고 : 브라우저에서 input 포커스 및 키보드 활성 시 ui 화면이 밀리거나 줄어드는 현상을 막습니다

*/

/* =========================== */