ios - uitextfield鍵盤 - 如何在UITextView中失去邊距/填充?




uitextfield width (12)

我的iOS應用程序中有一個UITextView ,它顯示大量的文本。 然後我通過使用UITextView的偏移量邊界參數來分頁這個文本。 我的問題是,填充的UITextView混淆了我的計算,因為它似乎是不同的,這取決於我使用的字體大小和字體。

因此,我提出了這樣的問題:是否有可能刪除圍繞UITextView內容的填充?

期待聽到你的回應!


2018年

這是iOS中最愚蠢的錯誤之一。

UITextViewFixed通常是一個合理的解決方案:

@IBDesignable class UITextViewFixed: UITextView {
    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }
    func setup() {
        textContainerInset = UIEdgeInsets.zero
        textContainer.lineFragmentPadding = 0
    }
}

不要忘記在Inspector中關閉scrollEnabled!

該解決方案在故事板以及運行時都能正常工作。

就是這樣,你完成了。

一般來說, 這應該是大多數情況下需要的

(即使您正在動態更改文本視圖的高度,例如用戶鍵入的內容,這通常只是您需要的。)

這是來自蘋果的破碎的UITextView ...

在幾乎所有情況下, UITextViewFixed都是可接受的修復方法:

(為了清晰起見,添加了黃色。)請注意,當然您必須

在Inspector中關閉scrollEnabled!

不要忘記關閉scrollEnabled! :)

還有一些問題

(1)在某些情況下 - 例如,有時當使用靈活的單元格高度表視圖在飛行中改變高度時,Apple會做出世界上最令人憤怒的事情: 它們在底部增加額外的空間 。 它必須是iOS中最瘋狂,最令人不快的事情之一。 這是一個“快速修復”添加,有時可以幫助這種瘋狂。

...
        textContainerInset = UIEdgeInsets.zero
        textContainer.lineFragmentPadding = 0

        // this is not ideal, but you can sometimes use this
        // to fix the "space at bottom" insanity
        var b = bounds
        let h = sizeThatFits(CGSize(
           width: bounds.size.width,
           height: CGFloat.greatestFiniteMagnitude)
       ).height
       b.size.height = h
       bounds = b
 ...

(2)有時候,為了修復另一個微妙的Apple混亂,你必須補充一點:

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
    super.setContentOffset(contentOffset, animated: false)
}

(3)可以說,我們應該補充:

contentInset = UIEdgeInsets.zero

就在.lineFragmentPadding = 0 。 但是...它不適用於當前的iOS! 在未來的操作系統版本中可能有必要添加該代碼。

UITextView在所有移動計算中都是最令人驚奇的事情之一,在iOS中完全被破壞。

最後,對於Text Field ,這裡有點類似的提示: https://.com/a/43099816/294884 : https://.com/a/43099816/294884


Storyboard或Interface Builder解決方案,使用用戶定義的運行時屬性。 更新。 contentInset = {{-10,-5},{0,0}}添加iOS7.1和iOS6.1屏幕截圖


對於Swift 4,Xcode 9

使用以下函數可以更改UITextView中文本的邊距/填充

public func UIEdgeInsetsMake(_ top:CGFloat,_ left:CGFloat,_ bottom:CGFloat,_ right:CGFloat) - > UIEdgeInsets

所以在這種情況下是

 self.textView?.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)

我肯定會避免涉及硬編碼值的任何答案,因為實際邊距可能會隨用戶字體大小設置等而改變。

這裡是@ user1687195的答案,在不修改textContainer.lineFragmentPadding情況下編寫(因為docs聲明這不是預期的用法)。

這適用於iOS 7及更高版本。

self.textView.textContainerInset = UIEdgeInsetsMake(
                                      0, 
                                      -self.textView.textContainer.lineFragmentPadding, 
                                      0, 
                                      -self.textView.textContainer.lineFragmentPadding);

這實際上是相同的結果,只是更清潔一點,它不會誤用lineFragmentPadding屬性。


你可以使用UITextView textContainerInset屬性:

textView.textContainerInset = UIEdgeInsetsMake(10,10,10,10);

(頂部,左側,底部,右側)


做插入解決方案我仍然有填充右側和底部。 此外文本對齊導致問題。 我發現的唯一可靠的方法是將文本視圖放入另一個視圖中,並將其限制在界限內。


對於iOS 10,以下行適用於頂部和底部填充刪除。

captionTextView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)

請注意,將其更改為右側的UIEdgeInset.zero不起作用


對於iOS 7.0,我發現contentInset技巧不再適用。 這是我用來擺脫iOS 7中的邊距/填充的代碼。

這將文本的左邊緣置於容器的左邊緣:

textView.textContainer.lineFragmentPadding = 0

這會導致文本的頂部與容器的頂部對齊

textView.textContainerInset = .zero

兩條線都需要完全刪除邊距/填充。


我發現了另一種方法,從UITextView的子視圖中獲取文本並在子類的layoutSubview方法中設置它:

- (void)layoutSubviews {
    [super layoutSubviews];

    const int textViewIndex = 1;
    UIView *textView = [self.subviews objectAtIndex:textViewIndex];
    textView.frame = CGRectMake(
                                 kStatusViewContentOffset,
                                 0.0f,
                                 self.bounds.size.width - (2.0f * kStatusViewContentOffset),
                                 self.bounds.size.height - kStatusViewContentOffset);
}

所有這些答案都解決了題目問題,但我想就OP問題中提出的問題提出一些解決方案。

文本內容的大小

計算UITextView本大小的一種快速方法是使用NSLayoutManager

UITextView *textView;
CGSize textSize = [textView usedRectForTextContainer:textView.textContainer].size;

這給出了可滾動內容的總數,可能比UITextView的框架大。 我發現這比textView.contentSize更準確,因為它實際上計算了文本佔用了多少空間。 例如,給定一個空的UITextView

textView.frame.size = (width=246, height=50)
textSize = (width=10, height=16.701999999999998)
textView.contentSize = (width=246, height=33)
textView.textContainerInset = (top=8, left=0, bottom=8, right=0)

線條高度

UIFont有一個屬性,可以快速讓您獲得給定字體的行高。 因此,您可以使用以下命令快速找到UITextView本的行高:

UITextView *textView;
CGFloat lineHeight = textView.font.lineHeight;

計算可見文本大小

確定實際可見的文本數量對於處理“分頁”效果非常重要。 UITextView有一個名為textContainerInset的屬性,它實際上是實際的UITextView.frame和文本本身之間的邊距。 要計算可見框架的實際高度,您可以執行以下計算:

UITextView *textView;
CGFloat textViewHeight = textView.frame.size.height;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textHeight = textViewHeight - textInsets.top - textInsets.bottom;

確定頁面大小

最後,現在您已經有了可見的文本大小和內容,您可以通過從textSize減去textHeight快速確定偏移量應該是多少:

// where n is the page number you want
CGFloat pageOffsetY = textSize - textHeight * (n - 1);
textView.contentOffset = CGPointMake(textView.contentOffset.x, pageOffsetY);

// examples
CGFloat page1Offset = 0;
CGFloat page2Offset = textSize - textHeight
CGFloat page3Offset = textSize - textHeight * 2

使用所有這些方法,我沒有碰到我的插頁,我能夠去掉插入符號或我想要的文本中的任何地方。


這是一個簡單的小擴展,它將從應用中的每個文本視圖中刪除Apple的默認邊距。

注意:界面生成器仍然會顯示舊的邊距,但是您的應用將按預期工作。

extension UITextView {

   open override func awakeFromNib() {
      super.awakeFromNib();
      removeMargins();
   }

   /** Removes the Apple textview margins. */
   public func removeMargins() {
      self.contentInset = UIEdgeInsetsMake(
         0, -textContainer.lineFragmentPadding,
         0, -textContainer.lineFragmentPadding);
   }
}

[firstNameTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];




uitextview