Files
min-offer-forum-issue/fixed-keyboard-accessory.html
DESKTOP-RQ919RC\Pc 4a1218e2bf no message
2025-10-14 20:19:41 +08:00

265 lines
8.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>固定定位的键盘辅助栏</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
padding: 20px;
padding-bottom: 60px; /* 预留辅助栏空间 */
background-color: #f5f5f7;
/* 关键移除可能影响fixed定位的属性 */
transform: none !important;
perspective: none !important;
}
/* 长内容区域,用于测试滑动 */
.long-content {
height: 2000px; /* 足够长以触发滚动 */
}
.container {
max-width: 600px;
margin: 0 auto;
}
h3 {
color: #1d1d1f;
margin-bottom: 30px;
text-align: center;
}
.input-group {
margin-bottom: 20px;
}
.input-field {
width: 100%;
padding: 14px 16px;
border: 1px solid #ddd;
border-radius: 12px;
font-size: 16px;
background-color: white;
transition: border-color 0.2s;
}
.input-field:focus {
outline: none;
border-color: #007aff;
box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2);
}
/* 键盘辅助栏核心样式(固定定位优化) */
.keyboard-accessory {
position: fixed; /* 固定在视口,不随滚动变化 */
left: 0;
right: 0; /* 替代width:100%,避免滚动条问题 */
height: 55px;
background-color: white;
border-top: 1px solid #eee;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
transition: transform 0.3s ease, bottom 0.3s ease;
transform: translateY(100%); /* 默认隐藏 */
z-index: 9999; /* 确保在所有内容之上 */
/* 关键:消除滚动时的抖动 */
will-change: transform, bottom;
backface-visibility: hidden;
}
.keyboard-accessory.show {
transform: translateY(0); /* 显示时移出隐藏状态 */
}
.accessory-btn {
padding: 8px 20px;
border: none;
border-radius: 20px;
font-size: 15px;
font-weight: 500;
cursor: pointer;
}
.cancel-btn {
color: #666;
background-color: #f5f5f5;
}
.clear-btn {
color: #333;
background-color: #eee;
}
.confirm-btn {
color: white;
background-color: #007aff;
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
body { background-color: #1c1c1e; }
h3 { color: #f5f5f7; }
.input-field {
background-color: #2c2c2e;
border-color: #3a3a3c;
color: white;
}
.keyboard-accessory {
background-color: #1c1c1e;
border-top-color: #3a3a3c;
}
}
</style>
</head>
<body>
<div class="container">
<h3>固定定位的键盘辅助栏</h3>
<div class="input-group">
<input
type="text"
class="input-field"
placeholder="点击输入,辅助栏不随滑动移动..."
>
</div>
<!-- 长内容区域,用于测试滑动效果 -->
<div class="long-content">
<p>滚动页面测试辅助栏是否固定...</p>
<p style="margin-top: 500px;">中间位置...</p>
<p style="margin-top: 1000px;">底部位置...</p>
</div>
</div>
<!-- 键盘辅助栏 -->
<div class="keyboard-accessory" id="keyboardAccessory">
<button class="accessory-btn cancel-btn" id="cancelBtn">取消</button>
<button class="accessory-btn clear-btn" id="clearBtn">清52除</button>
<button class="accessory-btn confirm-btn" id="confirmBtn">完成</button>
</div>
<script>
// 获取元素
const inputs = document.querySelectorAll('.input-field');
const accessory = document.getElementById('keyboardAccessory');
const cancelBtn = document.getElementById('cancelBtn');
const clearBtn = document.getElementById('clearBtn');
const confirmBtn = document.getElementById('confirmBtn');
let activeInput = null;
let isIOS = /iPhone|iPad|iPod/.test(navigator.userAgent);
// 键盘高度检测器
class KeyboardManager {
constructor() {
this.height = 0;
this.initialHeight = this.getVisualHeight();
this.isVisible = false;
this.init();
}
getVisualHeight() {
return window.visualViewport?.height || window.innerHeight;
}
init() {
if (window.visualViewport) {
window.visualViewport.addEventListener('resize', () => this.update());
}
window.addEventListener('resize', () => this.update());
}
update() {
const currentHeight = this.getVisualHeight();
const diff = this.initialHeight - currentHeight;
if (diff > 100 && !this.isVisible) {
this.height = diff;
this.isVisible = true;
this.emit('show', this.height);
} else if (diff <= 50 && this.isVisible) {
this.initialHeight = currentHeight;
this.isVisible = false;
this.emit('hide');
}
}
on(type, callback) {
this[type] = callback;
}
emit(type, data) {
if (this[type]) this[type](data);
}
}
const keyboard = new KeyboardManager();
// 键盘弹出时调整位置
keyboard.on('show', (height) => {
if (activeInput && isIOS) {
accessory.style.bottom = `${height}px`;
} else if (activeInput) {
accessory.style.bottom = '0';
}
});
keyboard.on('hide', () => {
accessory.style.bottom = '0';
});
// 输入框聚焦/失焦
inputs.forEach(input => {
input.addEventListener('focus', (e) => {
activeInput = e.target;
accessory.classList.add('show');
setTimeout(() => keyboard.update(), 300);
});
input.addEventListener('blur', () => {
setTimeout(() => {
if (!document.activeElement.classList.contains('input-field')) {
accessory.classList.remove('show');
activeInput = null;
}
}, 200);
});
});
// 按钮事件
cancelBtn.addEventListener('click', () => activeInput?.blur());
clearBtn.addEventListener('click', () => {
if (activeInput) {
activeInput.value = '';
activeInput.focus();
}
});
confirmBtn.addEventListener('click', () => {
if (activeInput) {
alert(`输入内容:${activeInput.value || '空'}`);
activeInput.blur();
}
});
// 禁止页面滚动时辅助栏偏移(可选)
window.addEventListener('scroll', () => {
if (accessory.classList.contains('show')) {
// 强制重绘,避免滚动时的视觉偏移
accessory.style.willChange = 'transform';
setTimeout(() => {
accessory.style.willChange = '';
}, 100);
}
});
</script>
</body>
</html>