fix(fe): 评论页键盘避让改用 bindkeyboardheightchange 移动固定输入条
列表完全不动(adjust-position=false + 页面 overflow:hidden),只有底部 fixed 输入条按键盘高度抬 bottom,聚焦期间不碰输入框其它属性,避免原生 textarea 抖失焦。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ Page({
|
|||||||
replyTo: {},
|
replyTo: {},
|
||||||
cmFocus: false,
|
cmFocus: false,
|
||||||
sendingComment: false,
|
sendingComment: false,
|
||||||
|
kbHeight: 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
onLoad(query) {
|
onLoad(query) {
|
||||||
@@ -77,11 +78,15 @@ Page({
|
|||||||
this.setData({ replyTo: {} });
|
this.setData({ replyTo: {} });
|
||||||
},
|
},
|
||||||
|
|
||||||
// 关键:聚焦期间 JS 绝不 setData 碰输入条(连 cmFocus:false 都不设),
|
// 键盘高度变化:微信为「自定义输入条跟随键盘」提供的事件。只改输入条的 bottom(inline),
|
||||||
// 否则原生 textarea 会被抖失焦、键盘弹一下就自己收。cmFocus 只在失焦时复位,
|
// 评论列表完全不动。注意:聚焦期间除了这个 bottom,绝不 setData 碰输入框本身
|
||||||
// 这样下次点回复 false→true 还能重新拉起键盘。键盘避让全交给原生 adjust-position。
|
// (不设 cmFocus:false、不改它的布局),否则原生 textarea 会被抖失焦、键盘弹一下就收。
|
||||||
|
onKbChange(e) {
|
||||||
|
this.setData({ kbHeight: (e.detail && e.detail.height) || 0 });
|
||||||
|
},
|
||||||
onCommentBlur() {
|
onCommentBlur() {
|
||||||
this.setData({ cmFocus: false });
|
// 失焦:收起键盘时把输入条放回底部;cmFocus 复位好让下次回复能重新拉键盘
|
||||||
|
this.setData({ cmFocus: false, kbHeight: 0 });
|
||||||
},
|
},
|
||||||
|
|
||||||
// 配图:评论只允许 1 张
|
// 配图:评论只允许 1 张
|
||||||
|
|||||||
@@ -55,10 +55,10 @@
|
|||||||
|
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<!-- 底部输入条:普通流式排在 flex 列最底部(不 fixed)。页面整体 overflow:hidden 不能滚,
|
<!-- 底部输入条:固定定位,靠 bindkeyboardheightchange 拿到键盘高度后把自己的 bottom 抬到
|
||||||
聚焦时原生 adjust-position 会把整屏均匀上移让输入条避开键盘 —— 不会像 fixed 那样把
|
键盘上方。评论列表完全不动(adjust-position=false,页面不滚)。这是微信为「自定义输入条
|
||||||
页面过度上滚出大片空白,也不需要任何 JS 碰输入条(碰了就抖失焦)。 -->
|
跟随键盘」专门提供的事件,移动的是 bottom 值、不 reflow 输入框内部,所以不会抖失焦。 -->
|
||||||
<view class="cm-bar">
|
<view class="cm-bar" style="bottom:{{kbHeight}}px">
|
||||||
<view wx:if="{{replyTo.name}}" class="cm-replying">
|
<view wx:if="{{replyTo.name}}" class="cm-replying">
|
||||||
回复 {{replyTo.name}}
|
回复 {{replyTo.name}}
|
||||||
<view class="cm-cancel" catchtap="onCancelReply"><pt-icon name="close" size="{{24}}"></pt-icon></view>
|
<view class="cm-cancel" catchtap="onCancelReply"><pt-icon name="close" size="{{24}}"></pt-icon></view>
|
||||||
@@ -72,9 +72,9 @@
|
|||||||
<view class="cm-bar-row">
|
<view class="cm-bar-row">
|
||||||
<textarea class="cm-ta" placeholder="{{replyTo.name ? '回复 @' + replyTo.name + '…' : '说点什么…'}}"
|
<textarea class="cm-ta" placeholder="{{replyTo.name ? '回复 @' + replyTo.name + '…' : '说点什么…'}}"
|
||||||
placeholder-class="placeholder" value="{{commentText}}" bindinput="onCommentInput"
|
placeholder-class="placeholder" value="{{commentText}}" bindinput="onCommentInput"
|
||||||
focus="{{cmFocus}}" bindblur="onCommentBlur"
|
focus="{{cmFocus}}" bindblur="onCommentBlur" bindkeyboardheightchange="onKbChange"
|
||||||
maxlength="500" auto-height="{{true}}" show-confirm-bar="{{false}}"
|
maxlength="500" auto-height="{{true}}" show-confirm-bar="{{false}}"
|
||||||
adjust-position="{{true}}" cursor-spacing="16"></textarea>
|
adjust-position="{{false}}" cursor-spacing="16"></textarea>
|
||||||
<view class="cm-pic {{commentImages.length ? 'disabled' : ''}}" catchtap="onPickCommentImages"><pt-icon name="photo" size="{{44}}"></pt-icon></view>
|
<view class="cm-pic {{commentImages.length ? 'disabled' : ''}}" catchtap="onPickCommentImages"><pt-icon name="photo" size="{{44}}"></pt-icon></view>
|
||||||
<view class="cm-send {{commentText && !sendingComment ? 'on' : ''}}" catchtap="onSendComment">{{sendingComment ? '审核中…' : '发送'}}</view>
|
<view class="cm-send {{commentText && !sendingComment ? 'on' : ''}}" catchtap="onSendComment">{{sendingComment ? '审核中…' : '发送'}}</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/* flex 列 + 整页 overflow:hidden:页面本身不滚,列表在内层 scroll-view 里滚。
|
/* flex 列 + 整页 overflow:hidden:页面本身不滚(adjust-position=false 时列表纹丝不动),
|
||||||
这样聚焦时 adjust-position 只能均匀上移整屏,不会过度上滚露出大空白 */
|
列表在内层 scroll-view 里滚,底部输入条 fixed 覆在最下面 */
|
||||||
page{display:flex;flex-direction:column;height:100vh;overflow:hidden;background:var(--bg)}
|
page{display:flex;flex-direction:column;height:100vh;overflow:hidden;background:var(--bg)}
|
||||||
|
|
||||||
.cm-scroll{flex:1;min-height:0;padding:0 var(--sp-5)}
|
/* 底部留白 = 输入条高度,最后几条评论不被固定输入条盖住 */
|
||||||
|
.cm-scroll{flex:1;min-height:0;padding:0 var(--sp-5) 200rpx}
|
||||||
.cm-count-head{
|
.cm-count-head{
|
||||||
padding:var(--sp-3) 0;font-size:var(--fs-md);font-weight:var(--fw-b);
|
padding:var(--sp-3) 0;font-size:var(--fs-md);font-weight:var(--fw-b);
|
||||||
color:var(--text);border-bottom:1rpx solid var(--line);
|
color:var(--text);border-bottom:1rpx solid var(--line);
|
||||||
@@ -44,10 +45,12 @@ page{display:flex;flex-direction:column;height:100vh;overflow:hidden;background:
|
|||||||
color:var(--primary-ink);background:var(--primary-soft);padding:2rpx var(--sp-1);border-radius:var(--r-full);
|
color:var(--primary-ink);background:var(--primary-soft);padding:2rpx var(--sp-1);border-radius:var(--r-full);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 底部输入条:flex 列里最后一行,不 fixed。整屏靠 adjust-position 均匀上移避让键盘 */
|
/* 底部输入条:固定在底部,键盘弹起时 inline 的 bottom 会被抬到键盘上方(列表不动) */
|
||||||
.cm-bar{
|
.cm-bar{
|
||||||
flex:none;background:#fff;border-top:1rpx solid var(--line);
|
position:fixed;left:0;right:0;bottom:0;z-index:50;
|
||||||
|
background:#fff;border-top:1rpx solid var(--line);
|
||||||
padding:var(--sp-3) var(--sp-5) calc(16rpx + env(safe-area-inset-bottom));
|
padding:var(--sp-3) var(--sp-5) calc(16rpx + env(safe-area-inset-bottom));
|
||||||
|
transition:bottom .15s ease;
|
||||||
}
|
}
|
||||||
.cm-replying{
|
.cm-replying{
|
||||||
display:inline-flex;align-items:center;gap:var(--sp-2);margin-bottom:var(--sp-2);
|
display:inline-flex;align-items:center;gap:var(--sp-2);margin-bottom:var(--sp-2);
|
||||||
|
|||||||
Reference in New Issue
Block a user