2012-05-18 1 views
9

저는 asp.net 웹 사이트를 가지고 있습니다. 저는 ipad에서 지원되도록 구축하고 있습니다. 입력 요소에 초점을두고 키보드가 튀어 나오면 위치 고정 헤더 div (일반적으로 페이지와 함께 스크롤 됨)는 키보드가 걸리는 양과 동일한 거리만큼 페이지를 팝업하고 입력 프로세스. 키보드를 다시 내려 놓으면 div가 제자리로 돌아가고 정상적으로 다시 작동합니다. iOS5에서 테스트 중이므로 position : fixed를 지원해야합니다.페이지에서 고정 위치 div가 고정됩니다. (iPad)

이 것이 알려진 문제입니까? 누군가 이것을 만나서 전에 다루었습니까? 나는 이것에 관해 무엇인가 발견 할 수 없다.

답변

15

iOS5/iOS6/iOS7에서 고정 위치가 깨졌습니다.

편집 3 : iOS8에서이 답변의 끝 부분에 가까운 링크를 참조하십시오.

a) 페이지가

또는

B를 확대하는 키보드)로 인해 입력 점점 초점 (아이 패드/아이폰에 표시) :

위치 : 어느 때 고정이 끊어집니다.

jsbin.com/icibaz/3에서 링크를 열고 확대하거나 입력 포커스를줌으로써 버그를 직접 볼 수 있습니다. edit the html은 직접 수정할 수 있습니다. 버그 (a)와 대한

노트 (B) :

입력이 포커스를 얻었을 때 top: 0px; left: 0px;와 고정 사업부는 (화면의 맨 위 또는 아래) 잘못된 위치에 표시됩니다
  1. 키보드 쇼.

  2. 이 문제는 화면의 입력 자동 조정 (window.pageYoffset 변경)과 관련이있는 것으로 보입니다.

  3. onScroll 이벤트에서 top:을 변경 (예 : 0px와 1px 사이에서 전환)하도록 강요하면 픽셀로 고정 div가 이동하는 것을 볼 수 있습니다. 그러나 그것은 잘못된 장소에 남아 있습니다.

  4. 제가 이전에 사용한 한 가지 해결책은 hide the fixed div when an input gets focus입니다. 다른 답변을 참조하십시오.

  5. 고정 된 div는 키보드가 열렸을 때의 페이지에서 동일한 절대 위치에 고정되어있는 것처럼 보입니다.

  6. 그래서 입력에 포커스가있을 때 div를 절대 위치 지정으로 변경 하시겠습니까? 편집 3 :이 솔루션을 사용하여 맨 아래에 주석을 표시하십시오. 또는 키보드를 열기 전에 pageXOffset/pageYOffset 값을 저장하고 onScroll 이벤트에서 해당 값과 현재 pageXOffset/pageYOffset 값 (키보드가 열리면 현재 값)의 차이를 계산하고 고정 된 div를 그 차이만큼 오프셋합니다.

  7. 페이지가 확대 된 경우 고정 위치 지정에 다른 문제가있는 것으로 보입니다. - here (좋은 정보는 수정 된 댓글에 대한 Android 지원 정보가 here)입니다.

편집 1 : (jsfiddle되지 않음) 사용 jsbin을 재현 jsbin의 전체 화면보기 (하지 편집 페이지)를 사용합니다. jsfiddle (및 jsbin 뷰 편집)은 iframe 내부에 코드를 삽입하여 고정 된 위치 지정 및 pageYOffset을 방해합니다.

편집 2 : iOS 6 및 iOS 7 모바일 Safari position:fixed;에는 여전히 동일한 문제가 있습니다.

편집 3 : (b)의 해결 방법은 입력에 포커스가있을 때 헤더를 절대 위치 지정으로 변경 한 다음 페이지 스크롤 이벤트 for example에서 헤더 상단을 설정하는 것입니다. 이 솔루션은

  • 입력이 집중되지 않으면 고정 된 위치 지정을 사용합니다 (window.onscroll에 끔찍한 지터가 있음).
  • 핀치 줌을 허용하지 않습니다 (위의 버그 (a)를 피하십시오).
  • 입력이 포커스를 얻으면 절대 위치 지정과 window.pageYOffset을 사용하므로 (헤더가 올바르게 배치됩니다).
  • 입력에 포커스가있는 동안 스크롤하면 style.top을 pageYOffset과 동일하게 설정하십시오 (헤더는 iOS8에서도 onscroll 이벤트 지연으로 인해 다소 지터가됩니다).
  • iOS8의 응용 프로그램에서 UIWebView를 사용하거나 < = iOS7을 사용하는 경우 입력에 포커스가있을 때 스크롤하면 스크롤이 끝날 때까지 onscroll이 실행되지 않기 때문에 헤더가 매우 불안정합니다.
  • 입력이 포커스를 잃으면 고정 위치 헤더로 돌아갑니다 (예 : input.onblur를 사용하지만 document.body.onfocus를 사용하는 경우가 많음).
  • 헤더가 너무 크면 입력이 가려 지거나 덮일 수 있습니다.
  • 키보드가 보이면 iOS 페이지/뷰포트 높이의 버그로 인해 바닥 글에 사용할 수 없습니다. 내 요구를 들어 http://output.jsbin.com/xujofoze/4/quiet
+0

가이, 나는이 아이폰 OS 버그 떠날 것입니다 판명를 지금은 문제지만 제안 사항이 유효하므로이 대답을 올바르게 표시 할 것입니다 – jas

+0

jas, iOS 버그 발행 URL에 대한 링크를 제공 할 수 있습니까? – robocat

+0

iOS6에서 수정 된 내용을 검토하지는 않았지만 하나 이상의 추가 버그가 추가되었습니다. http://igstudio.blogspot.com/2012/09/positionfixed-in-ios-6.html (나 또한 고정 div에 하드웨어 가속 합성을 강제하는 CSS 속성을 부여한 것으로 의심 될 수도 있습니다). – robocat

0

를 사용 http://jsbin.com/xujofoze/4/edit 및 뷰를 사용하여

  • 편집 예를 들면, 나는 쉽게, 절대 위치 헤더를 사용하여 스크롤하기 전에를 숨기고 마무리 스크롤 (내가 지원하는 동일한 코드를 필요로 할 때 그것을 보여 발견 iOS4 및 Android). 내 목적을 위해

    , 나는 touchstart 이벤트에 헤더를 숨기고, (/ 응답 성을 향상 깜빡임을 줄이기 위해 플러스 일부 타이머) touchend 또는 scroll 이벤트를 다시 보여줍니다. 그것은 깜박이지만 내가 발견 할 수있는 최상의 타협입니다. 하나는 touchmove 이벤트를 (jQuery를이 작업을 수행)를 사용하여 스크롤의 시작을 감지 할 수 있습니다,하지만 난 때문에 touchmove 나를 위해 잘 작동하지 않았다 발견 :

    1. 정기적으로 아이 패드가 스크롤하기 전에 다시 그리기를 할 실패 (즉, 스크롤을 시작하기 전에 top이 변경된 경우에도 절대 머리글이 고정 된 상태로 유지됩니다.

    2. 입력 요소가 포커스를 얻으면 iPad는 요소를 자동 중심에 배치하지만 scrollstart 이벤트는 발생하지 않습니다 (입력이 단지 click 인 경우 터치 이동이 없기 때문에).iOS5를 고정 헤더에 구현

    고정 절대 위치의 하이브리드 방식을 사용함으로써 개선 될 수있다 : 입력 포커스를 얻는다 iOS5를위한

    • 사용 고정 위치까지.

    • 입력이 포커스 (키보드 표시)가되면 iOS4 절대 위치 코드로 변경하십시오.

    • 키보드를 닫았을 때 고정 위치로 다시 변경하십시오. 키보드가 (예를 들어 키보드 숨기기 키를 사용)를 닫을 때 감지 할 수

    코드는 document 요소에 DOMFocusOut 이벤트를 등록하고 다음 코드 같은 것을 할 것입니다. 한 요소가 포커스를 얻고 다른 요소가 포커스를 잃을 때 사이에 DOMFocusOut 이벤트가 발생할 수 있기 때문에 시간 초과가 필요합니다.

    function document_DOMFocusOut() { 
        clearTimeout(touchBlurTimer); 
        touchBlurTimer = setTimeout(function() { 
         if (document.activeElement == document.body) { 
          handleKeyboardHide(); 
         } 
        }.bind(this), 400); 
    } 
    

    내 고정 된 헤더 코드는 뭔가 같은 :

    { 
        setup: function() { 
         observe(window, 'scroll', this, 'onWinScroll'); 
         observe(document, 'touchstart', this, 'onTouchStart'); 
         observe(document, 'touchend', this, 'onTouchEnd'); 
         if (isMobile) { 
          observe(document, 'DOMFocusOut', this, 'docBlurTouch'); 
         } else if (isIE) { 
         // see http://ajaxian.com/archives/fixing-loss-of-focus-on-ie for code to go into this.docBlurIe() 
          observe(document, 'focusout', this, 'docBlurIe'); 
         } else { 
          observe(isFirefox ? document : window, 'blur', this, 'docBlur'); 
         } 
        }, 
    
        onWinScroll: function() { 
         clearTimeout(this.scrollTimer); 
         this.scrolling = false; 
         this.rehomeAll(); 
        }, 
    
        rehomeAll: function() { 
         if ((isIOS5 && this.scrolling) || isIOS4 || isAndroid) { 
          this.useAbsolutePositioning(); 
         } else { 
          this.useFixedPositioning(); 
         } 
        }, 
    
        // Important side effect that this event registered on document on iOs. Without it event.touches.length is incorrect for any elements in the document using the touchstart event!!! 
        onTouchStart: function(event) { 
         clearTimeout(this.scrollTimer); 
         if (!this.scrolling && event.touches.length == 1) { 
          this.scrolling = true; 
          this.touchStartTime = inputOrOtherKeyboardShowingElement(event.target) ? 0 : (new Date).getTime(); 
          // Needs to be in touchStart so happens before iPad automatic scrolling to input, also not reliable using touchMove (although jQuery touch uses touchMove to unreliably detect scrolling). 
          this.rehomeAll(); 
         } 
        }, 
    
        onTouchEnd: function(event) { 
         clearTimeout(this.scrollTimer); 
         if (this.scrolling && !event.touches.length) { 
          var touchedDuration = (new Date).getTime() - this.touchStartTime; 
          // Need delay so iPad can scroll to the input before we reshow the header. 
          var showQuick = this.touchStartTime && touchedDuration < 400; 
          this.scrollTimer = setTimeout(function() { 
           if (this.scrolling) { 
            this.scrolling = false; 
            this.rehomeAll(); 
           } 
          }.bind(this), showQuick ? 0 : 400); 
         } 
        }, 
    
        // ... more code 
    } 
    

    의 jQuery 모바일 scrollstart 및 scrollstop 이벤트 지원

    var supportTouch = $.support.touch, 
        scrollEvent = "touchmove scroll", 
        touchStartEvent = supportTouch ? "touchstart" : "mousedown", 
        touchStopEvent = supportTouch ? "touchend" : "mouseup", 
        touchMoveEvent = supportTouch ? "touchmove" : "mousemove"; 
    
    function triggerCustomEvent(obj, eventType, event) { 
        var originalType = event.type; 
        event.type = eventType; 
        $.event.handle.call(obj, event); 
        event.type = originalType; 
    } 
    
    // also handles scrollstop 
    $.event.special.scrollstart = { 
    
        enabled: true, 
    
        setup: function() { 
    
         var thisObject = this, 
          $this = $(thisObject), 
          scrolling, 
          timer; 
    
         function trigger(event, state) { 
          scrolling = state; 
          triggerCustomEvent(thisObject, scrolling ? "scrollstart" : "scrollstop", event); 
         } 
    
         // iPhone triggers scroll after a small delay; use touchmove instead 
         $this.bind(scrollEvent, function(event) { 
    
          if (!$.event.special.scrollstart.enabled) { 
           return; 
          } 
    
          if (!scrolling) { 
           trigger(event, true); 
          } 
    
          clearTimeout(timer); 
          timer = setTimeout(function() { 
           trigger(event, false); 
          }, 50); 
         }); 
        } 
    }; 
    
  • 관련 문제