如何为 iOS 应用程序的 UILabel 设置左上对齐?
Posted
技术标签:
【中文标题】如何为 iOS 应用程序的 UILabel 设置左上对齐?【英文标题】:How to set top-left alignment for UILabel for iOS application? 【发布时间】:2011-11-03 18:14:17 【问题描述】:我在我的 nib 文件中添加了一个标签,然后它需要对该标签进行左上对齐。由于我在运行时提供文本,因此不确定有多少行。 因此,如果文本仅包含单行,则它显示为垂直居中对齐。该对齐方式与我前面的相应标签不匹配。
例如:
这看起来很奇怪:(
有什么方法可以让标签文本适合左上对齐?
【问题讨论】:
Vertically align text within a UILabel的可能重复 在这种情况下,使用Auto layout、height和bottom anchors中的约束特性。 【参考方案1】:这很容易做到。使用verticalAlignment
属性创建UILabel
子类并覆盖textRectForBounds:limitedToNumberOfLines
以返回顶部、中间或底部垂直对齐的正确边界。代码如下:
SOLabel.h
#import <UIKit/UIKit.h>
typedef enum
VerticalAlignmentTop = 0, // default
VerticalAlignmentMiddle,
VerticalAlignmentBottom,
VerticalAlignment;
@interface SOLabel : UILabel
@property (nonatomic, readwrite) VerticalAlignment verticalAlignment;
@end
SOLabel.m
@implementation SOLabel
-(id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (!self) return nil;
// set inital value via IVAR so the setter isn't called
_verticalAlignment = VerticalAlignmentTop;
return self;
-(VerticalAlignment) verticalAlignment
return _verticalAlignment;
-(void) setVerticalAlignment:(VerticalAlignment)value
_verticalAlignment = value;
[self setNeedsDisplay];
// align text block according to vertical alignment settings
-(CGRect)textRectForBounds:(CGRect)bounds
limitedToNumberOfLines:(NSInteger)numberOfLines
CGRect rect = [super textRectForBounds:bounds
limitedToNumberOfLines:numberOfLines];
CGRect result;
switch (_verticalAlignment)
case VerticalAlignmentTop:
result = CGRectMake(bounds.origin.x, bounds.origin.y,
rect.size.width, rect.size.height);
break;
case VerticalAlignmentMiddle:
result = CGRectMake(bounds.origin.x,
bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
rect.size.width, rect.size.height);
break;
case VerticalAlignmentBottom:
result = CGRectMake(bounds.origin.x,
bounds.origin.y + (bounds.size.height - rect.size.height),
rect.size.width, rect.size.height);
break;
default:
result = bounds;
break;
return result;
-(void)drawTextInRect:(CGRect)rect
CGRect r = [self textRectForBounds:rect
limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:r];
@end
【讨论】:
在运行此解决方案之前,我还在这里尝试了许多其他解决方案。它工作得很好!请记住,如果您在 StoryBoard 中执行此操作,请确保将 CustomClass 属性设置为 SOLabel(或您决定命名的任何名称)而不是 UILabel(在实用程序检查器中)。 这很有帮助,谢谢。它不适用于居中或右对齐的文本,但在textRectForBounds:limitedToNumberOfLines:
中使用 bounds.size.width
而不是 rect.size.width
似乎可以解决这个问题。
如果您在 ios 9 Xcode 7 中遇到 'Thread 1:EXC_BAD_ACCESS (Code 2, address=0x...)',只需移除 setter 和 getter -(VerticalAlignment) verticalAlignment;和 -(void) setVerticalAlignment:(VerticalAlignment) 值函数,因为变量是 @property。它是合成的并包含访问器。
我在方法中做了一些修改:“textRectForBounds” - result = CGRectMake(rect.origin.x, bounds.origin.y, rect.size.width, rect.size.height) ;使我的作品适用于 rightAlignment UILable。【参考方案2】:
我将链接到这个相当广泛且评价很高的问题/答案,而不是重新解释:
Vertically align text to top within a UILabel
简短的回答是否定的,Apple 并没有让这变得简单,但可以通过更改帧大小来实现。
【讨论】:
【参考方案3】:我在 StoryBoard 中找到了使用 AutoLayout 的解决方案。
1) 将行数设置为 0,将文本对齐方式设置为左。
2) 设置高度限制。
3) 高度约束应该是相关的 - 小于或等于
4)
override func viewWillLayoutSubviews()
sampleLabel.sizeToFit()
我得到的结果如下:
【讨论】:
像魅力一样工作,即使在 UITableViewCell 中重复使用。 你是把viewWillLayoutSubviews
放在控制器还是单元格文件中?如果是控制器,它如何从单元格中访问 UILabel?
第 4 步放在哪里?作为一个新用户,我很高兴能有一个纯粹的 UI 解决方案,然后代码不知从哪里冒出来,我们不知道该放在哪里
在 SampleClass.swift 或 SampleTableViewCell.swift 上
这应该是解决方案。完美运行,无需 hack 或子类化。【参考方案4】:
SOLabel 对我有用。
斯威夫特 3 和 5:
此版本已从原始版本更新,以支持 RTL 语言:
public class VerticalAlignLabel: UILabel
enum VerticalAlignment
case top
case middle
case bottom
var verticalAlignment : VerticalAlignment = .top
didSet
setNeedsDisplay()
override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect
let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft
switch verticalAlignment
case .top:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
else
switch verticalAlignment
case .top:
return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
override public func drawText(in rect: CGRect)
let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: r)
斯威夫特 1:
class UIVerticalAlignLabel: UILabel
enum VerticalAlignment : Int
case VerticalAlignmentTop = 0
case VerticalAlignmentMiddle = 1
case VerticalAlignmentBottom = 2
var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop
didSet
setNeedsDisplay()
required init(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect
let rect = super.textRectForBounds(bounds, limitedToNumberOfLines: limitedToNumberOfLines)
switch(verticalAlignment)
case .VerticalAlignmentTop:
return CGRectMake(bounds.origin.x, bounds.origin.y, rect.size.width, rect.size.height)
case .VerticalAlignmentMiddle:
return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height)
case .VerticalAlignmentBottom:
return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height), rect.size.width, rect.size.height)
default:
return bounds
override func drawTextInRect(rect: CGRect)
let r = self.textRectForBounds(rect, limitedToNumberOfLines: self.numberOfLines)
super.drawTextInRect(r)
【讨论】:
如果我尝试使用以下代码创建标签: var myLabel = VerticalAlignLabel() 我得到“调用中的参数 'coder' 缺少参数”。如何使用这个 VerticalAlignLabel 子类创建标签? 现在试试 Swift 版本 3 - 我有一个不需要的 init。【参考方案5】:就我而言,这是bottom space
约束问题。我已将其设置为= 16
。
当我将它设置为bottom to >= 16
时,这个问题就解决了。
此外,如果标签中有任何高度限制,则需要将其删除。
这是我在尺寸检查器中的标签约束视图:
【讨论】:
选择标签时没有约束选项。 最简单的修复 - 让约束和自动布局来处理它。谢谢! 这个答案为我指明了正确的方向,我有一个约束 thisLabel.centerY = parent.centerY 认为内容居中是关于 UILabel 内部的。相反,不,约束应该是 thisLabel.centerY 【参考方案6】:在你的代码中
label.text = @"some text";
[label sizeToFit];
请注意,如果您在表格单元格或其他使用不同数据回收的视图中使用它,您需要将原始框架存储在某处并在调用 sizeToFit 之前将其重置。
【讨论】:
我建议此时将其全部留给 Autolayout。这不再需要了。【参考方案7】:我为同样的问题找到了另一种解决方案。我使用UITextView
代替UILabel
并将editable()
函数切换为false
。
【讨论】:
@geekyaleks 为什么这是一个愚蠢的黑客?似乎是一个不错的解决方法,除了不能直接回答问题之外,还有其他问题吗? 这是不合适的,因为您没有为该作业使用适当的 UI 组件。对于像垂直对齐这样简单的事情,它不应该是妥协。需要为工作使用正确的组件。其他任何东西都是黑客......【参考方案8】:我也遇到了这个问题,但是我发现你设置 UILabel 的属性和方法的顺序很重要!
如果您在label.font = [UIFont fontWithName:@"Helvetica" size:14];
之前调用[label sizeToFit]
,则文本不会与顶部对齐,但如果您交换它们,它就会对齐!
我还注意到,首先设置文本也会有所不同。
希望这会有所帮助。
【讨论】:
太棒了。 sizeToFit() 应该在最后被调用。【参考方案9】:当您使用界面构建器时,请为您的标签设置约束(请务必同时设置高度和宽度)。然后在尺寸检查器中,检查标签的高度。在那里你会希望它读 >= 而不是 =。然后在该视图控制器的实现中,将行数设置为 0(也可以在 IB 中完成)并设置标签 [label sizeToFit];并且随着您的文本长度增加,标签将增加高度并将您的文本保持在左上角。
【讨论】:
【参考方案10】:如果您需要的是默认从左上角开始的不可编辑文本,您可以简单地使用文本视图而不是标签,然后将其状态设置为不可编辑,如下所示:
textview.isEditable = false
比弄乱标签更容易......
干杯!
【讨论】:
【参考方案11】:SoLabel 的解决方案有效,谢谢。
下面我添加了单点触控版本:
public class UICustomLabel : UILabel
private UITextVerticalAlignment _textVerticalAlignment;
public UICustomLabel()
TextVerticalAlignment = UITextVerticalAlignment.Top;
public UITextVerticalAlignment TextVerticalAlignment
get
return _textVerticalAlignment;
set
_textVerticalAlignment = value;
SetNeedsDisplay();
public override void DrawText(RectangleF rect)
var bound = TextRectForBounds(rect, Lines);
base.DrawText(bound);
public override RectangleF TextRectForBounds(RectangleF bounds, int numberOfLines)
var rect = base.TextRectForBounds(bounds, numberOfLines);
RectangleF resultRect;
switch (TextVerticalAlignment)
case UITextVerticalAlignment.Top:
resultRect = new RectangleF(bounds.X, bounds.Y, rect.Size.Width, rect.Size.Height);
break;
case UITextVerticalAlignment.Middle:
resultRect = new RectangleF(bounds.X,
bounds.Y + (bounds.Size.Height - rect.Size.Height)/2,
rect.Size.Width, rect.Size.Height);
break;
case UITextVerticalAlignment.Bottom:
resultRect = new RectangleF(bounds.X,
bounds.Y + (bounds.Size.Height - rect.Size.Height),
rect.Size.Width, rect.Size.Height);
break;
default:
resultRect = bounds;
break;
return resultRect;
public enum UITextVerticalAlignment
Top = 0, // default
Middle,
Bottom
【讨论】:
【参考方案12】:最简单最简单的方法是在 StackView 中嵌入 Label 并在 Storyboard like shown here 的 Attribute Inspector 中将 StackView 的 Axis 设置为 Horizontal,Alignment to Top。
【讨论】:
【参考方案13】:基于 totiG 的出色答案,我创建了一个 IBDesignable 类,它可以非常轻松地从 StoryBoard 自定义 UILabel 的垂直对齐方式。只需确保从 StoryBoard 身份检查器中将 UILabel 的类设置为“VerticalAlignLabel”。如果垂直对齐没有生效,请转到 Editor->Refresh All Views 这应该可以解决问题。
它是如何工作的: 正确设置 UILabel 的类后,情节提要应向您显示一个输入字段,该字段采用整数(对齐代码)。
更新:我添加了对居中标签的支持~Sev
为顶部对齐输入 0
输入 1 表示中间对齐
输入 2 进行底部对齐
@IBDesignable class VerticalAlignLabel: UILabel
@IBInspectable var alignmentCode: Int = 0
didSet
applyAlignmentCode()
func applyAlignmentCode()
switch alignmentCode
case 0:
verticalAlignment = .top
case 1:
verticalAlignment = .topcenter
case 2:
verticalAlignment = .middle
case 3:
verticalAlignment = .bottom
default:
break
override func awakeFromNib()
super.awakeFromNib()
self.applyAlignmentCode()
override func prepareForInterfaceBuilder()
super.prepareForInterfaceBuilder()
self.applyAlignmentCode()
enum VerticalAlignment
case top
case topcenter
case middle
case bottom
var verticalAlignment : VerticalAlignment = .top
didSet
setNeedsDisplay()
override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect
let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
if #available(iOS 9.0, *)
if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft
switch verticalAlignment
case .top:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .topcenter:
return CGRect(x: self.bounds.size.width - (rect.size.width / 2), y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
else
switch verticalAlignment
case .top:
return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .topcenter:
return CGRect(x: (self.bounds.size.width / 2 ) - (rect.size.width / 2), y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
else
// Fallback on earlier versions
return rect
override public func drawText(in rect: CGRect)
let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: r)
【讨论】:
【参考方案14】:你也可以把你的 UILabel 改为 UITextView,因为它们基本上做同样的事情,除了 UITextView 的优点是文本自动对齐到左上角
【讨论】:
【参考方案15】:@totiG 的回答是正确的,解决了我的问题。但是我在实现这种方法时发现了一个问题,在 5s 、 SE 等较小的设备中,这对我不起作用。我必须在override func layoutSubViews()
中设置label.sizeToFit()
override func layoutSubViews()
super.layoutSubViews()
// Do other works if needed
label.sizeToFit()
【讨论】:
【参考方案16】:使用 UITextView 而不是 UILabel。它也适用于 UITableViewCell 宽度自动行高
将 isScrollEnabled 和 isEditable 设置为 false。为 TextView 添加最小高度约束
One line text screenshot
Multiline text screenshot
final class TestVC: UIViewController
lazy var testTextLabel: UITextView =
$0.isScrollEnabled = false
$0.isEditable = false
$0.font = .systemFont(ofSize: 17, weight: .medium)
$0.textColor = .black
$0.layer.borderWidth = 1
$0.layer.borderColor = UIColor.black.cgColor
$0.layer.cornerRadius = 5
return $0
(UITextView())
override func viewDidLoad()
super.viewDidLoad()
view.backgroundColor = .white
testTextLabel.text = "Your text"
view.addSubview(testTextLabel)
testTextLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
testTextLabel.topAnchor.constraint(equalTo: testTextLabel.superview!.safeAreaLayoutGuide.topAnchor, constant: 12),
testTextLabel.leadingAnchor.constraint(equalTo: testTextLabel.superview!.leadingAnchor, constant: 12),
testTextLabel.widthAnchor.constraint(equalToConstant: 250),
testTextLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 70)
])
【讨论】:
【参考方案17】:我有这个问题,但我的标签在 UITableViewCell
,并且在基金中,解决问题的最简单方法是创建一个空的 UIView
并将标签设置在其中,并限制顶部和顶部仅左侧,on off curse 将行数设置为 0
【讨论】:
【参考方案18】:使用 textRect(forBounds:limitedToNumberOfLines:)
class TopAlignedLabel: UILabel
override func drawText(in rect: CGRect)
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
【讨论】:
【参考方案19】:对于 iOS 7,这就是我为我制作和工作的东西
@implementation UILabel (VerticalAlign)
- (void)alignTop
CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX);
NSDictionary *attributes = @NSFontAttributeName : self.font;
CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:attributes
context:nil];
int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight);
CGRect newFrame = self.frame;
newFrame.size.height = numberOfLines * self.font.lineHeight;
self.frame = newFrame;
- (void)alignBottom
CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX);
NSDictionary *attributes = @NSFontAttributeName : self.font;
CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:attributes
context:nil];
int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight);
int numberOfNewLined = (self.frame.size.height/self.font.lineHeight) - numberOfLines;
NSMutableString *newLines = [NSMutableString string];
for(int i=0; i< numberOfNewLined; i++)
[newLines appendString:@"\n"];
[newLines appendString:self.text];
self.text = [newLines mutableCopy];
【讨论】:
【参考方案20】:Swift 2.0::使用 UILabel 扩展
在一个空的 Swift 文件中创建常量枚举值。
// AppRef.swift
import UIKit
import Foundation
enum UILabelTextPositions : String
case VERTICAL_ALIGNMENT_TOP = "VerticalAlignmentTop"
case VERTICAL_ALIGNMENT_MIDDLE = "VerticalAlignmentMiddle"
case VERTICAL_ALIGNMENT_BOTTOM = "VerticalAlignmentBottom"
使用 UILabel 扩展:
创建一个空的 Swift 类并为其命名。添加以下内容。
// AppExtensions.swift
import Foundation
import UIKit
extension UILabel
func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) -> UILabel
let rect = sampleLabel!.textRectForBounds(bounds, limitedToNumberOfLines: 0)
switch positionIdentifier
case "VerticalAlignmentTop":
sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y, rect.size.width, rect.size.height)
break;
case "VerticalAlignmentMiddle":
sampleLabel!.frame = CGRectMake(bounds.origin.x+5,bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
rect.size.width, rect.size.height);
break;
case "VerticalAlignmentBottom":
sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y + (bounds.size.height - rect.size.height),rect.size.width, rect.size.height);
break;
default:
sampleLabel!.frame = bounds;
break;
return sampleLabel!
用法:
myMessageLabel.makeLabelTextPosition(messageLabel, positionIdentifier: UILabelTextPositions.VERTICAL_ALIGNMENT_TOP.rawValue)
【讨论】:
你能解释一下sampleLabel: UILabel?
需要什么吗?
在这个 func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) 上,你必须传递 UILabel 对象。【参考方案21】:
@totiG 的回答的 Swift 3 版本
class UIVerticalAlignLabel: UILabel
enum VerticalAlignment : Int
case VerticalAlignmentTop = 0
case VerticalAlignmentMiddle = 1
case VerticalAlignmentBottom = 2
@IBInspectable var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop
didSet
setNeedsDisplay()
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect
let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
switch(verticalAlignment)
case .VerticalAlignmentTop:
return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .VerticalAlignmentMiddle:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .VerticalAlignmentBottom:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
override func drawText(in rect: CGRect)
let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: r)
【讨论】:
【参考方案22】:斯威夫特 5
很简单,属性的顺序就是一切。
titleLabel.frame = CGRect(x: 20, y: 20, width: 374, height: 291.2)
titleLabel.backgroundColor = UIColor.clear //set a light color to see the frame
titleLabel.textAlignment = .left
titleLabel.lineBreakMode = .byTruncatingTail
titleLabel.numberOfLines = 4
titleLabel.font = UIFont(name: "HelveticaNeue-Bold", size: 35)
titleLabel.text = "Example"
titleLabel.sizeToFit()
self.view.addSubview(titleLabel)
【讨论】:
【参考方案23】:我可以通过在视图中嵌入标签来修复它。效果很好!
【讨论】:
【参考方案24】:需要在layoutSubviews中设置:
override func layoutSubviews()
super.layoutSubviews()
yourLabel.sizeToFit()
//yourLabel.center.x = someView.center.x // optionally if exists
【讨论】:
【参考方案25】:如何为 iOS 应用程序的 UILabel 设置左上对齐?标签设置内容模式为“左上”对我有用,非常感谢:
【讨论】:
对我完全没有任何作用。从直觉上看,这似乎应该是解决方案,这就是为什么我在它不起作用时求助于谷歌(或者似乎是千方百计,就此而言)。以上是关于如何为 iOS 应用程序的 UILabel 设置左上对齐?的主要内容,如果未能解决你的问题,请参考以下文章