mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-13 18:00:17 +00:00
Add support for textContainerInset to ASTextNode (ala UITextView) (#2062)
* Add support for textContainerInset to ASTextNode (ala UITextView) * Better comment, parens to increase readability. Thanks @schneider! * Add textContainerInset snapshot test.
This commit is contained in:
parent
39cb188b9e
commit
2c9e51e8f7
@ -31,6 +31,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@property (nullable, nonatomic, copy) NSTextStorage * (^textStorageCreationBlock)(NSAttributedString *_Nullable attributedString);
|
||||
|
||||
/**
|
||||
@abstract Text margins for text laid out in the text node.
|
||||
@discussion defaults to UIEdgeInsetsZero.
|
||||
This property can be useful for handling text which does not fit within the view by default. An example: like UILabel,
|
||||
ASTextNode will clip the left and right of the string "judar" if it's rendered in an italicised font.
|
||||
*/
|
||||
@property (nonatomic, assign) UIEdgeInsets textContainerInset;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -48,6 +48,8 @@ struct ASTextNodeDrawParameter {
|
||||
UIColor *_cachedShadowUIColor;
|
||||
CGFloat _shadowOpacity;
|
||||
CGFloat _shadowRadius;
|
||||
|
||||
UIEdgeInsets _textContainerInset;
|
||||
|
||||
NSArray *_exclusionPaths;
|
||||
|
||||
@ -213,7 +215,15 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
|
||||
if (_renderer == nil) {
|
||||
CGSize constrainedSize = _constrainedSize.width != -INFINITY ? _constrainedSize : bounds.size;
|
||||
CGSize constrainedSize;
|
||||
if (_constrainedSize.width != -INFINITY) {
|
||||
constrainedSize = _constrainedSize;
|
||||
} else {
|
||||
constrainedSize = bounds.size;
|
||||
constrainedSize.width -= (_textContainerInset.left + _textContainerInset.right);
|
||||
constrainedSize.height -= (_textContainerInset.top + _textContainerInset.bottom);
|
||||
}
|
||||
|
||||
_renderer = [[ASTextKitRenderer alloc] initWithTextKitAttributes:[self _rendererAttributes]
|
||||
constrainedSize:constrainedSize];
|
||||
}
|
||||
@ -279,6 +289,24 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
#pragma mark - Layout and Sizing
|
||||
|
||||
- (void)setTextContainerInset:(UIEdgeInsets)textContainerInset
|
||||
{
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
|
||||
BOOL needsUpdate = !UIEdgeInsetsEqualToEdgeInsets(textContainerInset, _textContainerInset);
|
||||
if (needsUpdate) {
|
||||
_textContainerInset = textContainerInset;
|
||||
[self invalidateCalculatedLayout];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIEdgeInsets)textContainerInset
|
||||
{
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
return _textContainerInset;
|
||||
}
|
||||
|
||||
- (BOOL)_needInvalidateRendererForBoundsSize:(CGSize)boundsSize
|
||||
{
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
@ -291,6 +319,10 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
// a new one. However, there are common cases where the constrained size doesn't need to be the same as calculated.
|
||||
CGSize rendererConstrainedSize = _renderer.constrainedSize;
|
||||
|
||||
//inset bounds
|
||||
boundsSize.width -= _textContainerInset.left + _textContainerInset.right;
|
||||
boundsSize.height -= _textContainerInset.top + _textContainerInset.bottom;
|
||||
|
||||
if (CGSizeEqualToSize(boundsSize, rendererConstrainedSize)) {
|
||||
return NO;
|
||||
} else {
|
||||
@ -321,9 +353,14 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
if (layout != nil) {
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
if (CGSizeEqualToSize(_constrainedSize, layout.size) == NO) {
|
||||
_constrainedSize = layout.size;
|
||||
_renderer.constrainedSize = layout.size;
|
||||
CGSize layoutSize = layout.size;
|
||||
//Apply textContainerInset
|
||||
layoutSize.width -= (_textContainerInset.left + _textContainerInset.right);
|
||||
layoutSize.height -= (_textContainerInset.top + _textContainerInset.bottom);
|
||||
|
||||
if (CGSizeEqualToSize(_constrainedSize, layoutSize) == NO) {
|
||||
_constrainedSize = layoutSize;
|
||||
_renderer.constrainedSize = layoutSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -335,6 +372,10 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
|
||||
//remove textContainerInset
|
||||
constrainedSize.width -= (_textContainerInset.left + _textContainerInset.right);
|
||||
constrainedSize.height -= (_textContainerInset.top + _textContainerInset.bottom);
|
||||
|
||||
_constrainedSize = constrainedSize;
|
||||
|
||||
// Instead of invalidating the renderer, in case this is a new call with a different constrained size,
|
||||
@ -353,6 +394,11 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
self.descender *= _renderer.currentScaleFactor;
|
||||
}
|
||||
}
|
||||
|
||||
//add textContainerInset
|
||||
size.width += (_textContainerInset.left + _textContainerInset.right);
|
||||
size.height += (_textContainerInset.top + _textContainerInset.bottom);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -466,6 +512,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
CGContextSaveGState(context);
|
||||
|
||||
CGContextTranslateCTM(context, _textContainerInset.left, _textContainerInset.top);
|
||||
|
||||
ASTextKitRenderer *renderer = [self _rendererWithBounds:drawParameterBounds];
|
||||
UIEdgeInsets shadowPadding = [self shadowPaddingWithRenderer:renderer];
|
||||
CGPoint boundsOrigin = drawParameterBounds.origin;
|
||||
|
||||
35
AsyncDisplayKitTests/ASTextNodeSnapshotTests.m
Normal file
35
AsyncDisplayKitTests/ASTextNodeSnapshotTests.m
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// ASTextNodeSnapshotTests.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Garrett Moon on 8/12/16.
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#import "ASSnapshotTestCase.h"
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface ASTextNodeSnapshotTests : ASSnapshotTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASTextNodeSnapshotTests
|
||||
|
||||
- (void)testTextContainerInset
|
||||
{
|
||||
// trivial test case to ensure ASSnapshotTestCase works
|
||||
ASTextNode *textNode = [[ASTextNode alloc] init];
|
||||
textNode.attributedText = [[NSAttributedString alloc] initWithString:@"judar"
|
||||
attributes:@{NSFontAttributeName : [UIFont italicSystemFontOfSize:24]}];
|
||||
[textNode measureWithSizeRange:ASSizeRangeMake(CGSizeZero, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX))];
|
||||
textNode.frame = CGRectMake(0, 0, textNode.calculatedSize.width, textNode.calculatedSize.height);
|
||||
textNode.textContainerInset = UIEdgeInsetsMake(0, 2, 0, 2);
|
||||
|
||||
ASSnapshotVerifyNode(textNode, nil);
|
||||
}
|
||||
|
||||
@end
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Loading…
x
Reference in New Issue
Block a user