I'm trying to create a reusable textfield like view that shows the description above the textfield when there is text in the textfield. When I try the following constraints, I don't have any issue until I embed the stack view into a view. I need the view because I want to apply the styles to that view, and I want the description and the textfield/view content to be displayed enclosed by the styled view.
This is my xib:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="FormView" customModule="InToOut" customModuleProvider="target"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="394" height="233"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6MT-Kf-be6">
<rect key="frame" x="0.0" y="0.0" width="394" height="233"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="eXL-HZ-eBt">
<rect key="frame" x="0.0" y="0.0" width="394" height="233"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2m5-ox-32Z">
<rect key="frame" x="0.0" y="0.0" width="394" height="20.5"/>
<color key="backgroundColor" systemColor="systemYellowColor"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pvU-v7-kCR">
<rect key="frame" x="0.0" y="20.5" width="394" height="212.5"/>
<color key="backgroundColor" systemColor="systemOrangeColor"/>
<constraints>
<constraint firstAttribute="height" constant="212.5" id="Ra7-Fa-LuZ"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" systemColor="systemGreenColor"/>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemYellowColor"/>
<constraints>
<constraint firstItem="eXL-HZ-eBt" firstAttribute="top" secondItem="6MT-Kf-be6" secondAttribute="top" id="DrL-7d-1nd"/>
<constraint firstItem="eXL-HZ-eBt" firstAttribute="leading" secondItem="6MT-Kf-be6" secondAttribute="leading" id="Zra-Wo-zbi"/>
<constraint firstAttribute="bottom" secondItem="eXL-HZ-eBt" secondAttribute="bottom" id="rDg-kX-Cyw"/>
<constraint firstAttribute="trailing" secondItem="eXL-HZ-eBt" secondAttribute="trailing" id="uVW-rD-C8t"/>
</constraints>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="-21.739130434782609" y="344.53125"/>
</view>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemGreenColor">
<color red="0.20392156862745098" green="0.7803921568627451" blue="0.34901960784313724" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemOrangeColor">
<color red="1" green="0.58431372549019611" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemYellowColor">
<color red="1" green="0.80000000000000004" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>
Here is my xib's class:
import UIKit
class FormView: NibView {
}
Here is my definition of NibView
import UIKit
/// NibView is provided to reuse nib initialization code.
/// **Steps to use:**
/// 1. Create a swift file for your custom view, make your custom view a sub class of NibView like so
/// ```
/// class MyCustomView: NibView {
/// ```
/// 2. Create a corresponding xib file for your custom View: `⌘ n → View → Next`
/// 3. Open your xib, select the `file owner` under `PlaceHolders` in the second most left tab,
/// then once selected, click on the identity inspector, the 4th column in the right most tab, and type
/// the name of your custom view, it should autopopulate as you type. You do not need the view to be
/// a subclass of `MyCustomView` in the identity inspector, only the file Owner.
@IBDesignable class NibView: UIView {
var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup() {
backgroundColor = .clear
guard let nibView = loadNib() else {
assertionFailure("Could not load the nib")
return
}
view = nibView
inject(view: view)
}
}
extension UIView {
/// Inserts a subview and constrains it to fill this view (the superview) by default.
/// Using string formats supports older OS. This has an early exit if the
/// view is already injected. This also clears the subViews before injecting.
/// - Parameters:
/// - view: The view you are injecting
func inject(view: UIView) {
guard !subviews.contains(view) else { return }
if subviews.count > 0 { subviews.forEach { $0.removeFromSuperview() }}
view.frame = bounds
addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
[
topAnchor.constraint(equalTo: view.topAnchor),
leftAnchor.constraint(equalTo: view.leftAnchor),
rightAnchor.constraint(equalTo: view.rightAnchor),
bottomAnchor.constraint(equalTo: view.bottomAnchor)
].forEach {
$0.isActive = true
}
}
func loadNib() -> UIView? {
type(of: self).description().components(separatedBy: ".").last.flatMap {
UINib(nibName: $0, bundle: Bundle(for: type(of: self)))
.instantiate(withOwner: self, options: nil).first as? UIView
}
}
}
Looks like you have provided enough constraints for your UIStackView
that has id="eXL-HZ-eBt"
. There are four constraints - top
, leading
, bottom
& trailing
with this id.
However the new UIView
(with id="6MT-Kf-be6"
) that wraps the stack view does not have any constraints specified. Although it's size can be driven by stack view size (which is driven by it's contents/subviews), you still need to provide it top
& leading
constraints so Autolayout can compute where it's position should be on the screen.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.