在DTCoreText 中添加自定义的文章头,自定义View

再DTCoreText 中添加自定义的文章头部,事实上原理很简单,需要改动DTCoreText 的代码即可。

   

DTAttributedTextView 事实上是一个ScrollView , 中间包含了一个 DTAttributedTextContentView , 实际上再里面添加一个 headerView 并添加到头部,调整 DTAttributedTextContentView 的相对坐标,记住当滚动的时候会重新刷新 DTAttributedTextContentView , 此时也需要根据你的headerView 做一些偏移,问题就可以得到完美的解决了。这里紧紧添加一些思路,代码的话,我针对自己的改动贴一下,因为需要快速做了一下实验,所以没有太注意写法,大家看到不对的就改呗。PS.对比与DTCoreText 源代码,就可知道我改了哪些地方了。

//
//  DTAttributedTextView.m
//  CoreTextExtensions
//
//  Created by Oliver Drobnik on 1/12/11.
//  Copyright 2011 Drobnik.com. All rights reserved.
//

#import "DTAttributedTextView.h"
#import "DTCoreText.h"
#import <QuartzCore/QuartzCore.h>

@interface DTAttributedTextView ()

- (void)setup;

@end



@implementation DTAttributedTextView
{
	DTAttributedTextContentView *_attributedTextContentView;
	UIView *_backgroundView;
	UIView *_headerView;

	// these are pass-through, i.e. store until the content view is created
	__unsafe_unretained id textDelegate;
	NSAttributedString *_attributedString;
	BOOL _shouldDrawLinks;
}

- (id)initWithFrame:(CGRect)frame
{
	self = [super initWithFrame:frame];
	
	if (self)
	{
		[self setup];
	}
	
	return self;
}

- (void)dealloc 
{
	_attributedTextContentView.delegate = nil;
	[_attributedTextContentView removeObserver:self forKeyPath:@"frame"];
}

- (void)layoutSubviews
{
	[super layoutSubviews];
	
	[self contentView];
	
	// layout custom subviews for visible area
	[_attributedTextContentView layoutSubviewsInRect: CGRectMake(self.bounds.origin.x, self.bounds.origin.y - self.headerView.bounds.size.height, self.bounds.size.width, self.bounds.size.height + self.headerView.bounds.size.height)];
}

- (void)awakeFromNib
{
	[self setup];
}

// default
- (void)setup
{
	if (!self.backgroundColor)
	{
		self.backgroundColor = [DTColor whiteColor];
		self.opaque = YES;
		return;
	}
	
	CGFloat alpha = [self.backgroundColor alphaComponent];
	
	if (alpha < 1.0)
	{
		self.opaque = NO;
	}
	else 
	{
		self.opaque = YES;
	}
	
	self.autoresizesSubviews = NO;
	self.clipsToBounds = YES;
}

// override class e.g. for mutable content view
- (Class)classForContentView
{
	return [DTAttributedTextContentView class];
}

#pragma mark External Methods
- (void)scrollToAnchorNamed:(NSString *)anchorName animated:(BOOL)animated
{
	NSRange range = [self.contentView.attributedString rangeOfAnchorNamed:anchorName];
	
	if (range.length != NSNotFound)
	{
		// get the line of the first index of the anchor range
		DTCoreTextLayoutLine *line = [self.contentView.layoutFrame lineContainingIndex:range.location];
		
		// make sure we don't scroll too far
		CGFloat maxScrollPos = self.contentSize.height - self.bounds.size.height + self.contentInset.bottom + self.contentInset.top;
		CGFloat scrollPos = MIN(line.frame.origin.y, maxScrollPos);
		
		// scroll
		[self setContentOffset:CGPointMake(0, scrollPos) animated:animated];
	}
}

#pragma mark Notifications
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
	if (object == _attributedTextContentView && [keyPath isEqualToString:@"frame"])
	{
		CGRect newFrame = [[change objectForKey:NSKeyValueChangeNewKey] CGRectValue];
		self.contentSize =CGSizeMake(newFrame.size.width, newFrame.size.height + self.headerView.frame.size.height) ;
	}
}

#pragma mark Properties
- (DTAttributedTextContentView *)contentView
{
	if (!_attributedTextContentView)
	{
		// subclasses can specify a DTAttributedTextContentView subclass instead
		Class classToUse = [self classForContentView];
		
		CGRect rectReal;
		if (self.headerView) {
			rectReal = CGRectMake(self.bounds.origin.x+8.0f, self.bounds.origin.y + self.headerView.frame.size.height , self.bounds.size.width-15.0f,self.bounds.size.height - self.headerView.frame.size.height);
		}
		else{
			rectReal = CGRectMake(self.bounds.origin.x+8.0f, self.bounds.origin.y , self.bounds.size.width-15.0f,self.bounds.size.height);
		}
		[self addSubview:self.headerView];
		
		CGRect frame = UIEdgeInsetsInsetRect(rectReal, self.contentInset);
		_attributedTextContentView = [[classToUse alloc] initWithFrame:frame];
		
		_attributedTextContentView.userInteractionEnabled = YES;
		_attributedTextContentView.backgroundColor = self.backgroundColor;
		_attributedTextContentView.shouldLayoutCustomSubviews = NO; // we call layout when scrolling
		
		// adjust opaqueness based on background color alpha
		CGFloat alpha = [self.backgroundColor alphaComponent];
		
		if (alpha < 1.0)
		{
			_attributedTextContentView.opaque = NO;
		}
		else
		{
			_attributedTextContentView.opaque = YES;
		}

		// set text delegate if it was set before instantiation of content view
		_attributedTextContentView.delegate = textDelegate;
		
		// pass on setting
		_attributedTextContentView.shouldDrawLinks = _shouldDrawLinks;
		
		// set text we previously got
		_attributedTextContentView.attributedString = _attributedString;
		
		CGSize neededSize = [_attributedTextContentView sizeThatFits:CGSizeZero];
		frame.size = neededSize;
		_attributedTextContentView.frame = frame;
		
		self.contentSize =CGSizeMake(neededSize.width, neededSize.height + self.headerView.frame.size.height)  ;
		
		
		// we want to know if the frame changes so that we can adjust the scrollview content size
		[_attributedTextContentView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
		
		[self addSubview:_attributedTextContentView];
	}		
	
	return _attributedTextContentView;
}

- (void)setBackgroundColor:(DTColor *)newColor
{
	if ([newColor alphaComponent]<1.0)
	{
		super.backgroundColor = newColor;
		_attributedTextContentView.backgroundColor = [DTColor clearColor];
		self.opaque = NO;
	}
	else 
	{
		super.backgroundColor = newColor;
		
		if (_attributedTextContentView.opaque)
		{
			_attributedTextContentView.backgroundColor = newColor;
		}
	}
}

- (UIView *)backgroundView
{
	if (!_backgroundView)
	{
		_backgroundView = [[UIView alloc] initWithFrame:self.bounds];
		_backgroundView.backgroundColor	= [DTColor whiteColor];
		
		// default is no interaction because background should have no interaction
		_backgroundView.userInteractionEnabled = NO;

		[self insertSubview:_backgroundView belowSubview:self.contentView];
		
		// make content transparent so that we see the background
		_attributedTextContentView.backgroundColor = [DTColor clearColor];
		_attributedTextContentView.opaque = NO;
	}		
	
	return _backgroundView;
}

- (void)setBackgroundView:(UIView *)backgroundView
{
	if (_backgroundView != backgroundView)
	{
		[_backgroundView removeFromSuperview];
		_backgroundView = backgroundView;
		
		if (_attributedTextContentView)
		{
			[self insertSubview:_backgroundView belowSubview:_attributedTextContentView];
		}
		else
		{
			[self addSubview:_backgroundView];
		}
		
		if (_backgroundView)
		{
			// make content transparent so that we see the background
			_attributedTextContentView.backgroundColor = [DTColor clearColor];
			_attributedTextContentView.opaque = NO;
		}
		else 
		{
			_attributedTextContentView.backgroundColor = [DTColor whiteColor];
			_attributedTextContentView.opaque = YES;
		}
	}
}

- (void)setAttributedString:(NSAttributedString *)string
{
	_attributedString = string;

	// might need layout for visible custom views
	[self setNeedsLayout];

	if (_attributedTextContentView)
	{
		// pass it along if contentView already exists
		_attributedTextContentView.attributedString = string;
	
		// adjust content size right away
		self.contentSize = CGSizeMake(_attributedTextContentView.frame.size.width, _attributedTextContentView.frame.size.height + self.headerView.frame.size.height);
		//_attributedTextContentView.frame.size;
	}
}

- (NSAttributedString *)attributedString
{
	return _attributedString;
}

- (void)setFrame:(CGRect)frame
{
	if (!CGRectEqualToRect(self.frame, frame))
	{
		if (self.frame.size.width != frame.size.width)
		{
			// height does not matter, that will be determined anyhow
			CGRect contentFrame = CGRectMake(0, 0, frame.size.width - self.contentInset.left - self.contentInset.right, 0);
			
			_attributedTextContentView.frame = contentFrame;
		}
		[super setFrame:frame];
	}
}

- (void)setTextDelegate:(id<DTAttributedTextContentViewDelegate>)aTextDelegate
{
	// store unsafe pointer to delegate because we might not have a contentView yet
	textDelegate = aTextDelegate;
	
	// set it if possible, otherwise it will be set in contentView lazy property
	_attributedTextContentView.delegate = aTextDelegate;
}

- (id<DTAttributedTextContentViewDelegate>)textDelegate
{
	return _attributedTextContentView.delegate;
}

- (void)setShouldDrawLinks:(BOOL)shouldDrawLinks
{
	_shouldDrawLinks = shouldDrawLinks;
	_attributedTextContentView.shouldDrawLinks = YES;
}

- (UIView *)headerView
{
	return _headerView;
}

- (void)setHeaderView:(UIView *)headerView
{
	if (_headerView != headerView)
	{
		[_headerView removeFromSuperview];
		_headerView = headerView;
		{
			[self addSubview:_headerView];
		}
	}
}

@synthesize attributedTextContentView = _attributedTextContentView;
@synthesize attributedString = _attributedString;
@synthesize textDelegate = _textDelegate;
//@synthesize headerView = _headerView;

@synthesize shouldDrawLinks = _shouldDrawLinks;

@end


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值