Maintaining scroll position only works when not near the bottom of messages div

前端 未结 3 1782
故里飘歌
故里飘歌 2021-02-20 16:32

I\'m trying to mimic other mobile chatting apps where when you select the send-message textbox and it opens the virtual keyboard, the bottom-most message is still i

3条回答
  •  遇见更好的自我
    2021-02-20 17:22

    I have finally found a solution that actually works. Although it may not be ideal, it actually works in all cases. Here is the code:

    bottomScroller(document.querySelector(".messages"));
    
    bottomScroller = scroller => {
      let pxFromBottom = 0;
    
      let calcPxFromBottom = () => pxFromBottom = scroller.scrollHeight - (scroller.scrollTop + scroller.clientHeight);
    
      setInterval(calcPxFromBottom, 500);
    
      window.addEventListener('resize', () => { 
        scroller.scrollTop = scroller.scrollHeight - pxFromBottom - scroller.clientHeight;
      });
    }
    

    Some epiphanies I had along the way:

    1. When closing the virtual keyboard, a scroll event occurs instantly before the resize event. This seems to only happen when closing the keyboard, not opening it. This is the reason you cannot use the scroll event to set pxFromBottom, because if you are near the bottom it will set itself to 0 in the scroll event right before the resize event, messing up the calculation.

    2. Another reason why all the solutions had difficulty near the bottom of the messages div is a bit tricky to understand. For example, in my resize solution I just add or subtract 250 (mobile keyboard height) to scrollTop when opening or closing the virtual keyboard. This works perfectly except near the bottom. Why? Because let's say you are 50 pixels from the bottom and close the keyboard. It will subtract 250 from scrollTop (the keyboard height), but it should only subtract 50! So it will always reset to the wrong fixed position when closing the keyboard near the bottom.

    3. I also believe you cannot use onFocus and onBlur events for this solution, because those only occur when initially selecting the textbox to open the keyboard. You are perfectly able to open and close the mobile keyboard without activating these events, and as such, they are not able to used here.

    I believe the above points are important to developing a solution, because they are non-obvious at first, but prevent a robust solution from developing.

    I don't like this solution (interval is a bit inefficient and prone to race conditions), but I cannot find anything better that always works.

提交回复
热议问题