Ich habe versucht, eine benutzerdefinierte Tastatur in iOS 8 zu erstellen, die die Standardtastatur ersetzt. Ich habe wirklich gesucht und konnte nicht herausfinden, ob es möglich ist, eine Tastatur mit mehr Höhe als die Standard-iOS-Tastatur zu erstellen. Ich habe UIInputView ersetzt, konnte jedoch die für mich verfügbare Höhe nicht ändern.
Dies ist mein Code für Xcode 6.0 GM. Beide Ausrichtungen werden unterstützt.
Update: Dank @SoftDesigner können wir die Warnung constraint conflict
jetzt beseitigen.
Warnung : XIB und Storyboard werden nicht getestet. Es wurde von einigen Leuten berichtet, dass dies NICHT mit XIB funktioniert.
KeyboardViewController.h
#import <UIKit/UIKit.h>
@interface KeyboardViewController : UIInputViewController
@property (nonatomic) CGFloat portraitHeight;
@property (nonatomic) CGFloat landscapeHeight;
@property (nonatomic) BOOL isLandscape;
@property (nonatomic) NSLayoutConstraint *heightConstraint;
@property (nonatomic) UIButton *nextKeyboardButton;
@end
KeyboardViewController.m
#import "KeyboardViewController.h"
@interface KeyboardViewController ()
@end
@implementation KeyboardViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Perform custom initialization work here
self.portraitHeight = 256;
self.landscapeHeight = 203;
}
return self;
}
- (void)updateViewConstraints {
[super updateViewConstraints];
// Add custom view sizing constraints here
if (self.view.frame.size.width == 0 || self.view.frame.size.height == 0)
return;
[self.inputView removeConstraint:self.heightConstraint];
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
CGFloat screenH = screenSize.height;
CGFloat screenW = screenSize.width;
BOOL isLandscape = !(self.view.frame.size.width ==
(screenW*(screenW<screenH))+(screenH*(screenW>screenH)));
NSLog(isLandscape ? @"Screen: Landscape" : @"Screen: Potriaint");
self.isLandscape = isLandscape;
if (isLandscape) {
self.heightConstraint.constant = self.landscapeHeight;
[self.inputView addConstraint:self.heightConstraint];
} else {
self.heightConstraint.constant = self.portraitHeight;
[self.inputView addConstraint:self.heightConstraint];
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Perform custom UI setup here
self.nextKeyboardButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.nextKeyboardButton setTitle:NSLocalizedString(@"Next Keyboard", @"Title for 'Next Keyboard' button") forState:UIControlStateNormal];
[self.nextKeyboardButton sizeToFit];
self.nextKeyboardButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.nextKeyboardButton addTarget:self action:@selector(advanceToNextInputMode) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.nextKeyboardButton];
NSLayoutConstraint *nextKeyboardButtonLeftSideConstraint = [NSLayoutConstraint constraintWithItem:self.nextKeyboardButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0];
NSLayoutConstraint *nextKeyboardButtonBottomConstraint = [NSLayoutConstraint constraintWithItem:self.nextKeyboardButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0];
[self.view addConstraints:@[nextKeyboardButtonLeftSideConstraint, nextKeyboardButtonBottomConstraint]];
self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.inputView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:self.portraitHeight];
self.heightConstraint.priority = UILayoutPriorityRequired - 1; // This will eliminate the constraint conflict warning.
}
- (void)textWillChange:(id<UITextInput>)textInput {
// The app is about to change the document's contents. Perform any preparation here.
}
- (void)textDidChange:(id<UITextInput>)textInput {
}
@end
Swift 1.0 Version:
class KeyboardViewController: UIInputViewController {
@IBOutlet var nextKeyboardButton: UIButton!
let portraitHeight:CGFloat = 256.0
let landscapeHeight:CGFloat = 203.0
var heightConstraint: NSLayoutConstraint?
override func updateViewConstraints() {
super.updateViewConstraints()
// Add custom view sizing constraints here
if (self.view.frame.size.width == 0 || self.view.frame.size.height == 0) {
return
}
inputView.removeConstraint(heightConstraint!)
let screenSize = UIScreen.mainScreen().bounds.size
let screenH = screenSize.height;
let screenW = screenSize.width;
let isLandscape = !(self.view.frame.size.width == screenW * ((screenW < screenH) ? 1 : 0) + screenH * ((screenW > screenH) ? 1 : 0))
NSLog(isLandscape ? "Screen: Landscape" : "Screen: Potriaint");
if (isLandscape) {
heightConstraint!.constant = landscapeHeight;
inputView.addConstraint(heightConstraint!)
} else {
heightConstraint!.constant = self.portraitHeight;
inputView.addConstraint(heightConstraint!)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Perform custom UI setup here
self.nextKeyboardButton = UIButton.buttonWithType(.System) as UIButton
self.nextKeyboardButton.setTitle(NSLocalizedString("Next Keyboard", comment: "Title for 'Next Keyboard' button"), forState: .Normal)
self.nextKeyboardButton.sizeToFit()
self.nextKeyboardButton.setTranslatesAutoresizingMaskIntoConstraints(false)
self.nextKeyboardButton.addTarget(self, action: "advanceToNextInputMode", forControlEvents: .TouchUpInside)
self.view.addSubview(self.nextKeyboardButton)
var nextKeyboardButtonLeftSideConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 0.0)
var nextKeyboardButtonBottomConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
self.view.addConstraints([nextKeyboardButtonLeftSideConstraint, nextKeyboardButtonBottomConstraint])
heightConstraint = NSLayoutConstraint(item: self.inputView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: portraitHeight)
heightConstraint!.priority = 999.0
}
override func textWillChange(textInput: UITextInput) {
// The app is about to change the document's contents. Perform any preparation here.
}
override func textDidChange(textInput: UITextInput) {
// The app has just changed the document's contents, the document context has been updated.
var textColor: UIColor
var proxy = self.textDocumentProxy as UITextDocumentProxy
if proxy.keyboardAppearance == UIKeyboardAppearance.Dark {
textColor = UIColor.whiteColor()
} else {
textColor = UIColor.blackColor()
}
self.nextKeyboardButton.setTitleColor(textColor, forState: .Normal)
}
}
Apple hat kürzlich seine App-Programmieranleitung aktualisiert, um die Höhe der benutzerdefinierten Tastaturerweiterung zu ändern:
CGFloat _expandedHeight = 500;
NSLayoutConstraint *_heightConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant: _expandedHeight];
[self.view addConstraint: _heightConstraint];
Dies ist die minimale Lösung, die ich gefunden habe, um die Höhe korrekt zu aktualisieren. Es scheint zwei Schlüsselkomponenten zu geben:
translatesAutoresizingMaskIntoConstraints
, die auf false
gesetzt ist, muss der Ansichtshierarchie hinzugefügt werden.viewWillAppear
hinzugefügt werden.Ich sehe immer noch einen Unable to simultaneously satisfy constraints
-Fehler im Protokoll, aber es scheint trotzdem zu funktionieren. Ich sehe auch immer noch einen Sprung, bei dem die Höhe anfänglich auf ihren Standardwert eingestellt ist und dann auf den eingestellten Wert springt. Ich habe bisher noch keine Lösung gefunden.
import UIKit
class KeyboardViewController: UIInputViewController {
var heightConstraint: NSLayoutConstraint!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.inputView.addConstraint(self.heightConstraint)
}
override func viewDidLoad() {
super.viewDidLoad()
let dummyView = UILabel(frame:CGRectZero)
dummyView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(dummyView);
let height : CGFloat = 400
self.heightConstraint = NSLayoutConstraint( item:self.inputView, attribute:.Height, relatedBy:.Equal, toItem:nil, attribute:.NotAnAttribute, multiplier:0.0, constant:height)
}
}
Update für Swift 4:
import UIKit
class KeyboardViewController: UIInputViewController
{
private weak var _heightConstraint: NSLayoutConstraint?
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
guard nil == _heightConstraint else { return }
// We must add a subview with an `instrinsicContentSize` that uses autolayout to force the height constraint to be recognized.
//
let emptyView = UILabel(frame: .zero)
emptyView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(emptyView);
let heightConstraint = NSLayoutConstraint(item: view,
attribute: .height,
relatedBy: .equal,
toItem: nil,
attribute: .notAnAttribute,
multiplier: 0.0,
constant: 240)
heightConstraint.priority = .required - 1
view.addConstraint(heightConstraint)
_heightConstraint = heightConstraint
}
}
Die akzeptierte Antwort funktionierte nicht für iOS 9. Ich kombinierte Teile davon und einige andere Vorschläge zusammen mit Apples Code im App Extension-Programmierhandbuch .
Diese Lösung funktioniert hervorragend, da die Änderung der Höhe nicht bis viewDidAppear
verzögert wird. Bei einer Drehung können Sie die Höhe ändern, falls dies aufgrund der Bildschirmgröße gewünscht wird. Verifiziert, dass dies in iOS 8 und 9 funktioniert.
Einige wichtige Hinweise:
~ Mindestens ein Element in der inputView
muss Auto Layout .__ verwenden.
~ Die Höhenbeschränkung kann erst nach viewWillAppear
.__ aktiviert werden.
~ Die priority
der Höhenbeschränkung muss verringert werden, um unerfüllbare Beschränkungen zu vermeiden
~ updateViewConstraints
ist ein guter Ort, um die gewünschte Höhe einzustellen
Tipps:
~ Beim Testen des Simulators fand ich es sehr flockig und würde sich unerwartet verhalten. Wenn dies der Fall ist, setzen Sie den Simulator zurück und führen Sie ihn erneut aus. Oder Sie können die Tastatur einfach deaktivieren und erneut hinzufügen.
Hinweis:
~ Dies funktioniert derzeit nicht in iOS 10 Beta. Die Höhe wird korrekt geändert, wenn sie angezeigt wird. Wenn Sie das Gerät jedoch drehen, ändert sich die Höhe nicht. Dies liegt daran, dass updateViewConstraints
beim Drehen nicht ausgelöst wird. Bitte reichen Sie einen Fehlerbericht gegen iOS 10 ein. Um das Problem zu umgehen, können Sie stattdessen die constant
-Änderung in viewDidLayoutSubviews
auslösen.
var nextKeyboardButton: UIButton!
var heightConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
self.nextKeyboardButton = UIButton(type: .System)
self.nextKeyboardButton.setTitle(NSLocalizedString("Next Keyboard", comment: "Title for 'Next Keyboard' button"), forState: .Normal)
self.nextKeyboardButton.sizeToFit()
self.nextKeyboardButton.translatesAutoresizingMaskIntoConstraints = false
self.nextKeyboardButton.addTarget(self, action: "advanceToNextInputMode", forControlEvents: .TouchUpInside)
self.view.addSubview(self.nextKeyboardButton)
let nextKeyboardButtonLeftSideConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1, constant: 0)
let nextKeyboardButtonBottomConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1, constant: 0)
NSLayoutConstraint.activateConstraints([nextKeyboardButtonLeftSideConstraint, nextKeyboardButtonBottomConstraint])
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.heightConstraint = NSLayoutConstraint(item:self.inputView!, attribute:.Height, relatedBy:.Equal, toItem:nil, attribute:.NotAnAttribute, multiplier:0, constant:0)
self.heightConstraint!.priority = 999
self.heightConstraint!.active = true
}
override func updateViewConstraints() {
super.updateViewConstraints()
guard self.heightConstraint != nil && self.view.frame.size.width != 0 && self.view.frame.size.height != 0 else { return }
let portraitHeight: CGFloat = 400
let landscapeHeight: CGFloat = 200
let screenSize = UIScreen.mainScreen().bounds.size
let newHeight = screenSize.width > screenSize.height ? landscapeHeight : portraitHeight
if (self.heightConstraint!.constant != newHeight) {
self.heightConstraint!.constant = newHeight
}
}
Andere Antworten berücksichtigen widersprüchliche Einschränkungen und die Gerätedrehung nicht. Diese Antwort vermeidet Fehler wie "Konnte Bedingungen nicht gleichzeitig erfüllen" und die daraus resultierenden Probleme. Es ist zum Teil auf Verhaltensweisen angewiesen, die sich in zukünftigen Versionen von iOS ändern können, scheint jedoch die einzige Möglichkeit zu sein, dieses Problem unter iOS 8 zu lösen.
Fügen Sie in Ihrer UIInputViewController
-Unterklasse diese Methoden hinzu:
- (void)updateViewConstraints {
[super updateViewConstraints];
// Update height when appearing
[self updateViewHeightConstraintIfNeeded];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
// Update height when rotating
[self updateViewHeightConstraintIfNeeded];
}
- (void)updateViewHeightConstraintIfNeeded {
CGFloat preferedHeight = 216; // Portrait
if ( [UIScreen mainScreen].bounds.size.width
> [UIScreen mainScreen].bounds.size.height ) {
// Landscape
preferedHeight = 162;
}
NSLayoutConstraint *constraint = [self findViewHeightConstraint];
if ( preferedHeight != constraint.constant ) {
if ( constraint ) {
constraint.constant = preferedHeight;
} else {
// This is not run on current versions of iOS, but we add it to
// make sure the constraint exits
constraint = [NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0
constant:preferedHeight];
[self.view.superview addConstraint:constraint];
}
}
}
- (NSLayoutConstraint*)findViewHeightConstraint {
NSArray *constraints = self.view.superview.constraints;
for ( NSLayoutConstraint *constraint in constraints ) {
if ( constraint.firstItem == self.view
&& constraint.firstAttribute == NSLayoutAttributeHeight )
return constraint;
}
return nil;
}
Ich hatte ähnliche Probleme mit der Größenanpassung einer benutzerdefinierten Tastatur von iOS 8 bis iOS 10. Ich glaube, die richtige Lösung besteht darin, dass die Eingabeansicht eine korrekte intrinsicContentSize
bereitstellt und diesen Wert ändert (und ungültig macht!), Wenn Sie die Höhe der Ansicht ändern möchten. Beispielcode:
class CustomInputView: UIInputView {
var intrinsicHeight: CGFloat = 200 {
didSet {
self.invalidateIntrinsicContentSize()
}
}
init() {
super.init(frame: CGRect(), inputViewStyle: .keyboard)
self.translatesAutoresizingMaskIntoConstraints = false
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.translatesAutoresizingMaskIntoConstraints = false
}
override var intrinsicContentSize: CGSize {
return CGSize(width: UIViewNoIntrinsicMetric, height: self.intrinsicHeight)
}
}
class ViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
textView.becomeFirstResponder()
let inputView = CustomInputView()
// To make the view's size more clear.
inputView.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0.5, alpha: 1)
textView.inputView = inputView
// To demonstrate a change to the view's intrinsic height.
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(2)) {
inputView.intrinsicHeight = 400
}
}
}
Fügen Sie dies in ViewDidAppear ein:
NSLayoutConstraint *heightConstraint =
[NSLayoutConstraint constraintWithItem: self.view
attribute: NSLayoutAttributeHeight
relatedBy: NSLayoutRelationEqual
toItem: nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier: 0.0
constant: 300];
[self.view addConstraint: heightConstraint];
Funktioniert in iOS 8.1
Ich habe auch ein Keyboard gemacht und mich mit dem Höhenproblem herumgekämpft. Ich habe alle genannten Lösungen und auch die Programmierleitfaden-Lösung für App-Erweiterungen ausprobiert, konnte sie aber nicht beheben. Meine Tastatur hat eine sehr komplexe Ansichtshierarchie. Nach Schwierigkeiten habe ich eine Lösung gefunden, die vollständig für mich funktioniert. Es ist eine Art Hack, aber ich habe alle Szenarien auch mit der Rotation des Geräts getestet und es ist perfekt. Ich dachte, es wird jemandem helfen, also setze ich meinen Code hier ..
// Keep this code inside the UIInputViewController
@implementation KeyBoardViewController
@property (strong, nonatomic) NSLayoutConstraint *heightConstraint;
// This method will first get the height constraint created by (Run time system or OS) then deactivate it and add our own custom height constraint.
(void)addHeightConstraint {
for (NSLayoutConstraint* ct in self.view.superview.constraints) {
if (ct.firstAttribute == NSLayoutAttributeHeight) {
[NSLayoutConstraint deactivateConstraints:@[ct]];
}
}
if (!_heightConstraint) {
_heightConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant: 300];
[_heightConstraint setPriority:UILayoutPriorityDefaultHigh];
[self.view addConstraint:_heightConstraint];
}else {
_heightConstraint.constant = 300;
}
if (_heightConstraint && !_heightConstraint.isActive) {
[NSLayoutConstraint activateConstraints:@[_heightConstraint]];
}
[self.view layoutIfNeeded];
}
(void)viewWillLayoutSubviews {
[self addHeightConstraint];
}
Ich erstelle diese Funktion, gut für mich . Add preparHeightConstraint () und heightConstraint und in Ihren updateViewConstraints und viewWillAppear call prepareHeightConstraint ()
private var heightConstraint: NSLayoutConstraint!
/**
Prepare the height Constraint when create or change orientation keyboard
*/
private func prepareHeightConstraint() {
guard self.heightConstraint != nil else {
let dummyView = UILabel(frame:CGRectZero)
dummyView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(dummyView)
self.heightConstraint = NSLayoutConstraint( item:self.view, attribute:.Height, relatedBy:.Equal, toItem:nil, attribute:.NotAnAttribute, multiplier:0.0, constant: /* Here your height */)
// /* Here your height */ Here is when your create your keyboard
self.heightConstraint.priority = 750
self.view.addConstraint(self.heightConstraint!)
return
}
// Update when change orientation etc..
self.heightConstraint.constant = /* Here your height */
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// When keyboard is create
self.prepareHeightConstraint()
}
override func updateViewConstraints() {
super.updateViewConstraints()
guard let viewKeyboard = self.inputView where viewKeyboard.frame.size.width != 0 && viewKeyboard.frame.size.width != 0 {
return
}
//Update change orientation, update just the constant
self.prepareHeightConstraint()
}
- (void)updateViewConstraints {
[super updateViewConstraints];
// Add custom view sizing constraints here
CGFloat _expandedHeight = 500;
NSLayoutConstraint *_heightConstraint =
[NSLayoutConstraint constraintWithItem: self.view
attribute: NSLayoutAttributeHeight
relatedBy: NSLayoutRelationEqual
toItem: nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier: 0.0
constant: _expandedHeight];
[self.view addConstraint: _heightConstraint];
}
-(void)viewDidAppear:(BOOL)animated
{
[self updateViewConstraints];
}
Es funktioniert für mich
Für eine reibungslosere Animation bei der Änderungsorientierung füge ich Folgendes hinzu:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
CGFloat width = [UIScreen mainScreen].bounds.size.width;
self.view.window.frame = CGRectMake(0, 0, width, heigth);
}
Wenn die akzeptierte Antwort nicht funktioniert, verwenden Sie way.all. Alle Codes ändern sich nur in updateViewConstraintsReference .
- (void)updateViewConstraints {
[super updateViewConstraints];
if (self.view.frame.size.width == 0 || self.view.frame.size.height == 0)
return;
[self.inputView removeConstraint:self.heightConstraint];
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
CGFloat screenH = screenSize.height;
CGFloat screenW = screenSize.width;
BOOL isLandscape = !(self.view.frame.size.width ==
(screenW*(screenW<screenH))+(screenH*(screenW>screenH)));
NSLog(isLandscape ? @"Screen: Landscape" : @"Screen: Potriaint");
if (isLandscape)
{
self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.inputView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant: self.landscapeHeight];
[self.inputView addConstraint:self.heightConstraint];
} else {
self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.inputView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant: self.portraitHeight];
[self.inputView addConstraint:self.heightConstraint];
}
}
Schließlich habe ich es bekommen, fügen Sie diesen Code-Block zu Ihrer UIInputViewController
-Unterklasse hinzu:
override func viewDidAppear(animated: Bool) {
let desiredHeight:CGFloat = 300.0 // or anything you want
let heightConstraint = NSLayoutConstraint(item: view, attribute:NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
multiplier: 1.0,
constant: desiredHeight)
view.addConstraint(heightConstraint)
}
Es wird perfekt funktionieren. IOS 8.3
Dies ist eine sehr alte Frage, aber ich wollte nur mitteilen, dass ich herausgefunden habe, dass UIInputViewController
die Größe in Abhängigkeit von den hinzugefügten Unteransichten ändert. Wenn Sie also eine Ansicht wie diese zu Ihrem Ansichtscontroller hinzufügen:
let myView: UIView(frame: .zero)
myView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
myView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
myView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
myView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
wenn view
die Ansicht des Eingabeansichts-Controllers ist und dann eine Höhenbeschränkung angibt, berücksichtigt der Eingabeansichts-Controller diese Höhe, ohne Einschränkungen zu überschreiten.
Dies ist perfekt, da Sie eine Stapelansicht hinzufügen können, zu der Sie Ansichten hinzufügen können, die eine intrinsische Inhaltsgröße bieten. In diesem Fall müssen Sie keine Höhenbeschränkung angeben, da die Größe der Stapelansicht in Abhängigkeit von den hinzugefügten Ansichten implizit geändert wird.
Dies ist, was ich für iOS9 und Storyboard gemacht habe.
Ich habe @ skyline75489 (großer Dank) verwendet und die Antwort geändert.
@property (nonatomic) CGFloat portraitHeight;
@property (nonatomic) CGFloat landscapeHeight;
@property (nonatomic) BOOL isLandscape;
@property (nonatomic) NSLayoutConstraint *heightConstraint;
@property (nonatomic) BOOL viewWillAppearExecuted;
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
// Perform custom initialization work here
self.portraitHeight = 256;
self.landscapeHeight = 203;
}
return self;
}
- (void)updateViewConstraints {
[super updateViewConstraints];
if (_viewWillAppearExecuted)
[self adjustHeight];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.view addConstraint:self.heightConstraint];
_viewWillAppearExecuted = YES;
}
#pragma mark - Setters/Getters
- (NSLayoutConstraint *)heightConstraint
{
if (!_heightConstraint) {
_heightConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:self.portraitHeight];
_heightConstraint.priority = UILayoutPriorityRequired - 1;
}
return _heightConstraint;
}
#pragma mark - Methods
- (void)adjustHeight
{
if (self.view.frame.size.width == 0 || self.view.frame.size.height == 0)
return;
[self.view removeConstraint:self.heightConstraint];
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
CGFloat screenH = screenSize.height;
CGFloat screenW = screenSize.width;
BOOL isLandscape = !(self.view.frame.size.width ==
(screenW*(screenW<screenH))+(screenH*(screenW>screenH)));
self.isLandscape = isLandscape;
if (isLandscape) {
self.heightConstraint.constant = self.landscapeHeight;
[self.view addConstraint:self.heightConstraint];
} else {
self.heightConstraint.constant = self.portraitHeight;
[self.view addConstraint:self.heightConstraint];
}
}
In IOS 10 (Swift 4) musste ich die obigen Antworten aus drei Gründen kombinieren:
updateViewConstraints
wird nicht aufgerufen, wenn Sie das iPhone drehenheightConstraint
wird eine Einschränkung erzeugt, die vom Layout ignoriert wirdintrinsicContentSize
funktionierte nur unter Umständen, die ich nicht verstand
@objc public class CustomInputView: UIInputView {
var intrinsicHeight: CGFloat = 296.0 {
didSet {
self.invalidateIntrinsicContentSize()
}
}
@objc public init() {
super.init(frame: CGRect(), inputViewStyle: .keyboard)
self.translatesAutoresizingMaskIntoConstraints = false
}
@objc public required init?(coder: NSCoder) {
super.init(coder: coder)
self.translatesAutoresizingMaskIntoConstraints = false
}
@objc public override var intrinsicContentSize: CGSize {
let screenSize = UIScreen.main.bounds.size
let newHeight :CGFloat = screenSize.width > screenSize.height ? 230.0 : intrinsicHeight
return CGSize(width: UIViewNoIntrinsicMetric, height: newHeight)
}
}
@objc public class KeyboardViewController: UIInputViewController {
let portraitHeight:CGFloat = 296.0
let landscapeHeight:CGFloat = 230.0
var heightConstraint: NSLayoutConstraint?
func updateHeightConstraint(to size: CGSize){
var heightConstant=portraitHeight
if size.width>400 {
heightConstant=landscapeHeight
}
if heightConstant != heightConstraint!.constant {
inputView?.removeConstraint(heightConstraint!)
heightConstraint!.constant = heightConstant;
inputView?.addConstraint(heightConstraint!)
}
}
override public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
updateHeightConstraint(to: size)
}
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
updateHeightConstraint(to: UIScreen.main.bounds.size)
}
override public func viewDidLoad() {
super.viewDidLoad()
heightConstraint = NSLayoutConstraint(item: self.inputView as Any, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1.0, constant: portraitHeight)
heightConstraint!.priority = UILayoutPriority(rawValue: 999.0)
heightConstraint!.isActive=true;
}
//... code to insert, delete,..
}
in viewDidAppear
musste ich updateHeightConstraint
aufrufen, da die viewWillTransition
nicht aufgerufen wurde, als ich die UIInputViewController
änderte.
Ich brauchte nicht self.nextKeyboardButton.translatesAutoresizingMaskIntoConstraints = false
Es ist nicht möglich. Aus den Dokumenten
Darüber hinaus ist es nicht möglich, das Key-Artwork oberhalb der obersten Zeile anzuzeigen, wie dies bei der Systemtastatur auf dem iPhone der Fall ist, wenn Sie auf eine Taste in der obersten Zeile tippen.`
Wenn es möglich wäre, könnten wir leicht etwas über der obersten Reihe zeichnen.
Bearbeiten:
Es scheint, als hätte Apple dieses Problem behoben. Bitte sehen Sie sich die akzeptierte Antwort an