入力欄と直近発言がキーボードとかぶる
入力欄と直近発言が画面下にあるようなチャットアプリにおいて、iOSのバーチャルキーボードが被って不都合が起きていた
解決方法
基本方針はwindow.scrollTo
ネットワークのレスポンスでログが増える
コンテンツが予測不能なタイミングで非同期に更新され、高さが変わる
React.useEffectはコンポーネントのレンダリング後に呼ばれる、これを使う
const [logs, setLogs] = useState(...)
レスポンスでsetLogsして再描画をトリガーする
useEffect(scrollToBottom, [logs])でレンダリング後にスクロール
これでこの経路は解決
テキストエリアが中身の文章量によってサイズを変える
onChangeでスクロールしても上手くいかなかった
なぜなら、このタイミングではまだレンダリングが終わっていないから
内容変更時に高さを調べて、更新する必要があればsetStateしている
この変更のトリガーでコンポーネントのレンダリングが走る
子コンポーネントのレンダリングの後にフックをする方法がわからなかった
setTimeout(scrollToBottom);する
これでレンダリング後になる保証はないかも
scrollToBottomの中身
code:ts
const scrollToBottom = () => {
const e = document.getElementById("bottom") as HTMLElement;
const y = e.offsetTop - document.documentElement.clientHeight + 300;
if (y > 0) {
window.scrollTo(0, y);
}
};
300はバーチャルキーボードの高さ。デバイスから取得する方法がわからなかった
参考資料(*1)によれば301で、手元での11ProMaxでの実験でもまあ問題なさそうだったからこうした
bottomは入力欄の下にhrを置いてる
参考資料
window.innerHeightで取得する場合、上にスクロールをしてアドレスバーが表示されているときと、下にスクロールしてアドレスバーが表示されていないときでは取得できる値が異なる。
document.documentElement.clientHeightで取得する場合はアドレスバーによる影響はなく、常に一定の値が取得できる。