45
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UIWindowのwindowLevelについて あるいはソフトウェアキーボードより上にViewを表示する方法

Posted at

ソフトウェアキーボードより上にViewを表示したい!と思って方法を調べました。

iOSのソフトウェアキーボードはUIWindow

iOSのソフトウェアキーボードの正体は、keyWindowとは別のUIWindowです。
ということで、独自にUIWindowを生成して表示すれば、キーボードより上にViewを表示することができます。

詳しくはこちら。

UIWindowのサブクラスをわざわざ作る必要はありません。

let currentWindow = UIApplication.sharedApplication().keyWindow
let newWindow = UIWindow(frame:currentWindow.frame)
newWindow.windowLevel = UIWindowLevelNormal
newWindow.addSubview(hogeView)
newWindow.makeKeyAndVisible()
```

こんな感じでnewWindowを表示できます
windowを消したいときには、`resignKeyWindow()` を実行するのではなくnilを入れる

## windowLevelの話

さて`UIWindow` の表示順は設定された `windowLevel` で制御されます
UIWindowLevelはCGFloatのエイリアスです
`UIWindow.h` に定数として定義されているのは以下の3種類

- `UIWindowLevelNormal // = CGFloat(0)`
- `UIWindowLevelAlert // = CGFloat(2000)`
- `UIWindowLevelStatusBar // = CGFloat(1000)`

ここで問題です
キーボードより上にWindowを表示するためにはどのwindowLevelを設定すればいいでしょうか!?


答え
**全部ダメです**
マジかよ

## ためしにキーボードを表示した状態でWindowの構成を見てみましょう
検証環境はiOS9.1です

検証コード

```swift
UIApplication.sharedApplication().windows
```

結果

```
[<UIWindow: 0x148214bb0; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x148218980>; layer = <UIWindowLayer: 0x148215ea0>>,
 <UITextEffectsWindow: 0x146da70d0; frame = (0 0; 320 568); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x146da7450>>,
 <UIRemoteKeyboardWindow: 0x149391ce0; frame = (0 0; 320 568); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x149392270>>
]
```

3つめのUIRemoteKeyboardWindowがソフトウェアキーボード
[iOS開発におけるウィンドウUIWindowの知られざる活用方法とは #iOSCodeIQ MAGAZINE](https://codeiq.jp/magazine/2014/05/9493/)
によると過去のバージョンのiOSではUITextEffectsWindowで表示されていたこともあったようですが

なにはともあれこれらのwindowLevelを確認してみると

検証コード

```swift
UIApplication.sharedApplication().windows.map { $0.windowLevel }
```

結果

```
 [0.0, 1.0, 10000000.0]
```

10000000.0って何だよ…。

## 結論

独自のUIWindowをキーボードより上に表示したいなら10000000.0より大きい数をwindowLevelに設定しましょう
というか `UIApplication.sharedApplication().windows` をぶん回してそれより大きい数を設定しましょう

```swift
newWindow.windowLevel = UIApplication.sharedApplication().windows.reduce(0, combine: { max($0, $1.windowLevel) }) + 1
```

みたいに書けばいいんじゃないかな
45
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?