关于界面底侧或者左右侧出侧一条空白(statusbar的高度问题) 20 pixel blank at bottom of screen

本文探讨了在iOS开发中,UIViewController在不同情况下创建视图时遇到的状态栏适配问题及解决方案。当通过NIB文件创建视图控制器及其视图时,需注意视图控制器是否能自动调整视图框架来避免与状态栏重叠。文章提供了具体的代码示例和调整视图框架的方法。

G了半天,才找到点线索,原因:

Adding the root view to your UIWindow can be complicated since the window always underlaps the status bar. The frame of your root view must therefore be reset to [[UIScreen mainScreen] applicationFrame] to prevent it from underlapping the status bar as well. We normally don't have to worry about this because UIViewController modifies the frame for us... except when it doesn't. Here's the deal:

  • If you create your view controllerand its view in the same NIB, and younest the view underneath the viewcontroller, it will adjust the view's frame automatically.
  • If you create your view controller andits view in the same NIB, but youconnect the view to the viewcontroller through the controller'sview outlet rather than nesting it, the controller will not adjust the view's frame automatically.
  • If you create your view controller in one NIB, and you connect it to a view defined in a detached NIB by setting the view controller's "NIB Name" property in IB, it will adjust the view's frame automatically, but only if you also have "Resize view from NIB" checked.
  • If you create your view controller by calling -initWithNibName:bundle:, it will not adjust the view's frame automatically.
  • UITabBarController expects its view to be added as the root view of the window, and therefore always adjusts its own view's frame to match the application frame automatically. (As a result you'll notice a weird 20 pixel gap if you ever add a UITabBarController's view as a subview of anything other than the window.)

I guess Apple figured that -initWithNibName:bundle: wouldn't typically be used to create the window's root view, so it doesn't adjust the frame in your case. Resizing it manually as you have done is fine, and is in fact recommended in the View Controller Programming Guide for iPhone OS, but you should really use [[UIScreen mainScreen] applicationFrame] since the status bar isn't always 20 pixels tall (e.g. it's taller when you're on a phone call.)


解决办法:

CGRect rct = loginController.view.bounds;
    rct = [[UIScreen mainScreen] applicationFrame];
    [loginController setWantsFullScreenLayout:YES];
    rct.origin.y = 20;
    loginController.view.frame = rct;


参考链接:

http://stackoverflow.com/questions/2247647/offset-on-uiwindow-addsubview

http://stackoverflow.com/questions/2166718/the-old-display-shifts-down-after-modal-view-controller-issue



<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0, minimum-scale=1.0" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="format-detection" content="telephone=no" /> <title>逍遥网络</title> <!-- Favicon --> <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🎮</text></svg>"> <style> /* 重置 */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif; background: linear-gradient(45deg, #0f1a2b, #1a2e4d); color: white; min-height: 100vh; padding: 20px 15px 40px; line-height: 1.6; overflow: hidden; } /* 动态星空背景(纯CSS) */ body::before { content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(circle at 20% 30%, rgba(60, 100, 255, 0.1) 0%, transparent 30%), radial-gradient(circle at 80% 70%, rgba(255, 100, 150, 0.1) 0%, transparent 30%), radial-gradient(circle at 50% 10%, rgba(100, 200, 255, 0.08) 0%, transparent 25%); z-index: -2; } /* 毛玻璃遮罩层 */ body::after { content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(10, 20, 40, 0.6); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); z-index: -1; } h2 { text-align: center; color: #00d2ff; font-size: 30px; margin: 30px 0 10px; text-shadow: 0 0 5px rgba(0, 210, 255, 0.5), 0 0 15px rgba(0, 210, 255, 0.3); font-weight: 700; letter-spacing: 1px; animation: glow 2s infinite alternate; } @keyframes glow { from { text-shadow: 0 0 5px rgba(0, 210, 255, 0.5); } to { text-shadow: 0 0 15px rgba(0, 210, 255, 0.8), 0 0 20px rgba(0, 210, 255, 0.4); } } .subtitle { text-align: center; color: #aaa; font-size: 13px; margin-bottom: 30px; opacity: 0.8; } .form { max-width: 400px; margin: auto; background: rgba(30, 50, 80, 0.25); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); border-radius: 20px; padding: 24px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4), inset 0 0 10px rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.18); position: relative; overflow: hidden; } /* 表单部微光条 */ .form::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 2px; background: linear-gradient(90deg, transparent, #00d2ff, transparent); transform: scaleX(0.5); animation: shine 3s infinite alternate; } @keyframes shine { to { transform: scaleX(1); } } .service-link { display: block; margin: 0 0 16px; padding: 16px; text-decoration: none; border-radius: 14px; font-weight: 600; font-size: 16px; color: white; transition: all 0.3s cubic-bezier(0.2, 0, 0.2, 1); position: relative; overflow: hidden; background: rgba(255, 255, 255, 0.08); border-left: 5px solid transparent; transform: translateZ(0); } /* 根据 data-type 设置专属渐变背景 + 边框光晕 */ .service-link[data-type="local"] { --icon-color: #ff7676; background: linear-gradient(135deg, #1e3c7222, #2a529822); box-shadow: 0 0 6px rgba(255, 150, 150, 0.2); } .service-link[data-type="online-game"] { --icon-color: #64c8ff; background: linear-gradient(135deg, #0f202722, #203a4322, #2c536422); box-shadow: 0 0 6px rgba(100, 200, 255, 0.2); } .service-link[data-type="cdk"] { --icon-color: #ffd966; background: linear-gradient(135deg, #3a7bd522, #3a607322); box-shadow: 0 0 6px rgba(255, 200, 100, 0.2); } .service-link[data-type="test"] { --icon-color: #b066ff; background: linear-gradient(135deg, #5d26c122, #9a00d722); box-shadow: 0 0 6px rgba(180, 100, 255, 0.2); } .service-link[data-type="download"] { --icon-color: #00d2b4; background: linear-gradient(135deg, #00b4db22, #0083b022); box-shadow: 0 0 6px rgba(0, 200, 180, 0.2); } /* 悬停放大 + 阴影加深 + 投影外扩 */ .service-link:hover { transform: translateY(-3px) scale(1.03); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3), 0 0 15px var(--hover-color, rgba(255, 255, 255, 0.3)); } /* 按压反馈 */ .service-link:active { transform: scale(0.98); opacity: 0.8; } /* 自定义图标容器 */ .service-link .icon { width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; position: relative; margin-right: 12px; flex-shrink: 0; } /* 圆形背景光晕 */ .service-link .icon::before { content: ''; position: absolute; width: 100%; height: 100%; background: radial-gradient(circle, rgba(255, 255, 255, 0.2) 0%, transparent 70%); border-radius: 50%; z-index: 0; pointer-events: none; } /* 图标文字(使用 Unicode 字符或 SVG) */ .service-link .icon span { font-size: 20px; position: relative; z-index: 1; color: white; text-shadow: 0 0 4px rgba(255, 255, 255, 0.6); } /* 脉冲光圈动画(悬停时现) */ .service-link .icon::after { content: ''; position: absolute; width: 44px; height: 44px; border: 2px solid var(--icon-color); border-radius: 50%; opacity: 0; transform: scale(0.8); animation: pulse-ring 2s infinite; z-index: -1; pointer-events: none; } @keyframes pulse-ring { 0% { transform: scale(0.8); opacity: 0; } 50% { transform: scale(1.2); opacity: 0.6; } 100% { transform: scale(0.8); opacity: 0; } } /* 默认隐藏脉冲圈,悬停时显示 */ .service-link .icon::after { animation-play-state: paused; } .service-link:hover .icon::after { opacity: 1; animation-play-state: running; } .service-link span.name { vertical-align: middle; } .service-link .status { float: right; font-size: 11px; padding: 3px 8px; border-radius: 10px; background: rgba(0, 0, 0, 0.3); color: #ddd; margin-top: 6px; transition: all 0.3s ease; } .status.online { background: rgba(0, 180, 0, 0.5); color: #fff; box-shadow: 0 0 6px rgba(0, 200, 0, 0.3); } .status.offline { background: rgba(180, 0, 0, 0.5); color: #fff; box-shadow: 0 0 6px rgba(200, 0, 0, 0.3); } .status.loading { background: rgba(100, 100, 100, 0.4); color: #fff; animation: pulse 1.5s infinite; } @keyframes pulse { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } } </style> </head> <body> <h2>✨ 逍遥网络</h2> <p class="subtitle">一站式入口</p> <div class="form"> <a href="" class="service-link" data-port="" data-type="local" target="_blank" rel="noopener noreferrer"> <span class="icon"><span>🔧</span></span> <span class="name">游戏 活动</span> <span class="status loading">检查中...</span> </a> <a href="https://fafa.krific.cn" class="service-link" data-url="https://fafa.krific.cn" data-type="online-game" target="_blank" rel="noopener noreferrer"> <span class="icon"><span>🎮</span></span> <span class="name">游戏 商城</span> <span class="status loading">检查中...</span> </a> <a href="https://sdk.urptwx.cn" class="service-link" data-url="https://sdk.urptwx.cn" data-type="cdk" target="_blank" rel="noopener noreferrer"> <span class="icon"><span>⚙️</span></span> <span class="name">CDK 兑换</span> <span class="status loading">检查中...</span> </a> <a href="" class="service-link" data-port="" data-type="test" target="_blank" rel="noopener noreferrer"> <span class="icon"><span>🧪</span></span> <span class="name">新手 教程</span> <span class="status loading">检查中...</span> </a> <a href="" class="service-link" data-port="" data-type="download" target="_blank" rel="noopener noreferrer"> <span class="icon"><span>📊</span></span> <span class="name">安卓+IOS+PC 游戏下载</span> <span class="status loading">检查中...</span> </a> </div> <script> function checkLocal(port) { return new Promise((resolve) => { const img = new Image(); img.src = `http://127.0.0.1:${port}/favicon.ico?r=${Date.now()}`; img.onload = () => resolve(true); img.onerror = () => resolve(false); setTimeout(() => resolve(false), 3000); }); } async function checkOnline(url) { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); await fetch(url, { method: 'HEAD', mode: 'no-cors', signal: controller.signal }); clearTimeout(timeoutId); return true; } catch (err) { return false; } } document.querySelectorAll('.service-link').forEach(async (link) => { const statusSpan = link.querySelector('.status'); let isOnline = false; if (link.dataset.port) { isOnline = await checkLocal(link.dataset.port); } else if (link.dataset.url) { isOnline = await checkOnline(link.dataset.url); } statusSpan.classList.remove('loading'); statusSpan.textContent = isOnline ? '在线' : '离线'; statusSpan.classList.add(isOnline ? 'online' : 'offline'); }); </script> </body> </html> 在此基础上 优化 安卓 IOS PC 检测分辨率自动适配 完整写
10-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值