UITextView починається знизу або в середині тексту


75

Я доберусь до цього. У мене на UItextViewдумку, що коли потрібно прокрутити, щоб побачити весь текст (коли в textView присутній багато тексту), textView іноді починається в середині тексту, а інший раз внизу тексту.

введіть тут опис зображення

Редагування не ввімкнено в textView. Мені потрібен спосіб змусити textView запускатись зверху кожного разу. Я бачив кілька запитань, подібних до цього, де інші люди використовували зміщення вмісту, але я насправді не знаю, як це працює, чи може це застосуватись тут.

Спасибі за вашу допомогу.


Ви використовуєте UINavigationBar як заголовок там, або його власний подання?
Mrunal

@Mrunal Я не впевнений, що ви маєте на увазі, але це ви запитуєте про колір - це звичайна панель навігації від push-сегменту, просто забарвлена ​​в додатку.
Alex Wulff,

2
Ви встановлюєте текст у viewDidLoad? виконати dispatch_async в головній черзі вирішить проблему.
Чарлі Ву,

Відповіді:


169

Це зробило для мене фокус!

Завдання C:

[self.textView scrollRangeToVisible:NSMakeRange(0, 0)];

Стрімкий:

self.textView.scrollRangeToVisible(NSMakeRange(0, 0))

Swift 2 (альтернативне рішення)

Додайте цей метод заміни до ViewController

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    textView.setContentOffset(CGPointZero, animated: false)
}

Swift 3 і 4 (редагування синтаксису)

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()

  textView.contentOffset = .zero
}

9
Чудово працює! Я досі не розумію, навіщо нам це робити. Чому він не запускається автоматично з 0,0?
mikemike396

6
Я думаю, що оскільки це призначено для області введення користувачем, під час введення тексту курсор розміщується в кінці тексту, і якщо ви залишите екран, ви хочете продовжувати друкувати з того місця, куди ви пішли, коли повернетесь.
user2700551 02

2
Я вважаю, що scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NOпрацює краще, оскільки це дозволяє уникнути початкового візуалізації, викликаного неявною анімацією.
devios1,

Це точно не працює для мене. Відповідь, надана @zeeple, працює, але якщо ми все-таки використали відповідь, текстовий перегляд прокручується до будь-якої дії, виконаної у поданні. Буду вдячний за допомогу.
mshrestha

Привіт Манджул, я не бачу такої ж поведінки у своєму впровадженні. Я можу торкнутися подання, трохи поворухнути тощо, і він не прокручується автоматично до початку.
zeeple

54

Всі відповіді вище не працювали для мене. Однак секрет виявляється в тому, щоб реалізувати ваше рішення в перевизначенні viewDidLayoutSubviews, як у:

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()

  welcomeText.contentOffset = .zero
}

HTH :)


2
Можливо, тому, що я використовую перо, це єдине, що працювало у мене.
Родріго Пінто

3
@RodrigoPedroso Використовуючи раскадровку, і це єдине, що спрацювало і на мене
Патрік

1
Те саме тут, це єдине рішення, яке спрацювало для мене. Мій перегляд тексту знаходиться в перо для запису. Не знаю, чи це щось змінює.
Форма

Я використовую раскадровку. Чи може це бути пов’язано з версією iOS?
Мігель Рібейро

Я спробував це, viewDidLayoutSubviews()і я побачив, як textView прокручується, коли ViewController завантажується, незважаючи на те, що анімація встановлена ​​на false. Я вирішив це, поставивши setContentOffsetв viewWillAppearw / animation значення false.
Адріан,

14

У Swift 2

Ви можете використовувати це, щоб textView розпочався зверху:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    myTextView.setContentOffset(CGPointZero, animated: false)
}

Підтверджено роботу в Xcode 7.2 із Swift 2


1
У мене чудово працювало в Xcode 7.3 (7D175) / iOS 9.3
JSmyth

13

Спробуйте це нижче коду -

if ( [self respondsToSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:)]){
     self.automaticallyAdjustsScrollViewInsets = NO;         
}

Або ви також можете встановити цю властивість за допомогою StoryBoard -

Виберіть ViewController, а потім виберіть інспектор атрибутів, який зараз не позначено Adjust Scroll View Insets.


Я не бачу, де в Інспекторі атрибутів існує коригування вставки перегляду прокрутки.
zeeple

@zeeple Це властивість ViewController, яка відображатиметься під заголовком ViewController в інспекторі атрибутів після вибору ViewController у розкадровці. Будь ласка, перевірте правильно. Сподіваюсь, ви знайдете.
keshav vishwkarma

8

Для Swift> 2.2 у мене були проблеми з iOS 8 та iOS 9, використовуючи вищезазначені методи, оскільки немає єдиної відповіді, яка б працювала, тому ось що я зробив, щоб це працювало для обох.

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if #available(iOS 9.0, *) {
        textView.scrollEnabled = false
    }

    self.textView.scrollRangeToVisible(NSMakeRange(0, 0))
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    if #available(iOS 9.0, *) {
        textView.scrollEnabled = true
    }
}

Ого. Я не можу повірити, що це було моє питання. Яка користь від того, щоб робити це так?
Самі

6

Оновіть властивість UINavigationBar translucentдо NO:

self.navigationController.navigationBar.translucent = NO;

Це дозволить виправити вигляд, який не буде оформлено під панеллю навігації та рядком стану.

Якщо вам потрібно показати та приховати панель навігації, скористайтеся наведеним нижче кодом у вашому viewDidLoad

 if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific

Сподіваюся, це допомагає.


1
Не пощастило і цьому ... подання тексту все ще прокручується донизу. Чи може це мати щось спільне із властивістю automaticallyAdjustsScrollViewInsets? Оскільки я маю текстовий перегляд, розміщений під навігаційною панеллю з увімкненою функцією, тому панель навігації не затьмарює текстовий перегляд. Дякую за відповідь.
Alex Wulff,

Спробуйте автоматично коментувати рядокAdjustsScrollViewInsets і перевірте.
Mrunal

5

Xcode 7.2 7c68; IOS 9.1

Мій, ViewControllerщо містить UITextView, складний і сильно змінився під час проекту (версія IDE також змінювалась, можливо, 2-3 рази).

Я спробував усі вищезазначені рішення, якщо ви зіткнетеся з тією ж проблемою, будьте терплячими .

Існує три можливі „секретні коди” для вирішення:

  1. textView.scrollEnabled = false //then set text textView.scrollEnabled = true
  2. textView.scrollRangeToVisible(NSMakeRange(0, 0))
  3. textView.setContentOffset(CGPointZero, animated: false)

І є два місця, де ви можете розмістити ці коди:

  1. viewDidLoad()
  2. viewDidLayoutSubviews()

Поєднавши їх, ви отримаєте 3 * 2 = 6 рішень, правильна комбінація залежить від того, наскільки ви складні ViewController(повірте, після видалення лише подання вищеtextView , мені потрібно знайти нову комбінацію).

І я виявив, що:

Коли ви вводите "секретні коди" у вміст viewDidLayoutSubviews(), але textView.text = someStringsв viewDidLoad()ньогоtextView "іноді" буде "трястись". Отже, поставте їх там же.

Останнє слово: спробуйте ВСІ комбінації, ось так я вирішую цю дурну помилку більше трьох разів протягом двох місяців.


встановлення для текстового перегляду scrollEnabled значення false і потім true - це те, що мені вдалося. І мені не довелося розміщувати його у viewDidLoad або ViewDidLayoutSubviews. Я помістив scrollEnabled = false безпосередньо перед тим, як ми встановили текст, а потім помістив scrollEnable = true в обробник завершення для анімації, завдяки якій з'являється texView
Анна Гаррісон,

5

З великою кількістю тестувань я знайшов, що повинен додати нижче функцію viewWillLayoutSubviews (), щоб переконатися, що UITextView відображається з самого початку:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()            
    textViewTerms.scrollRangeToVisible(NSMakeRange(0, 0))
}

4

UITextViewпрокрутка здається проблемою для багатьох людей. Опираючись на відповіді тут (особливо це ) та документацію розробника Apple, використовуючи власну дотепність, ось рішення, яке мені підходить. Ви можете змінити код відповідно до своїх потреб.

Я використовую такий випадок: те саме UITextViewвикористовується для різних цілей, відображаючи різний вміст за різних обставин. Що я хочу, так це те, що коли вміст змінюється, старе положення прокрутки відновлюється або часом прокручується до кінця. Я не хочу надто багато анімації, коли це робиться. Особливо я не хочу, щоб подання оживляло, як і весь текст був новим. Це рішення спочатку відновлює стару позицію прокрутки без анімації, а потім прокручує до кінця анімований, якщо це потрібно.

Що вам потрібно зробити (або я повинен сказати, що можу зробити), це розширити UITextView наступним чином:

extension UITextView {
  func setText(text: String, storedOffset: CGPoint, scrollToEnd: Bool) {
    self.text = text
    let delayInSeconds = 0.001
    let popTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
    dispatch_after(popTime, dispatch_get_main_queue(), {
      self.setContentOffset(storedOffset, animated: false)
      if scrollToEnd && !text.isEmpty {
        let popTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue(), {
          self.scrollRangeToVisible(NSMakeRange(text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) - 1, 0))
        })
      }
    })
  }
}

Це оновлює текст, а потім використовує збережене значення UITextView.contentOffsetвластивості (або будь-що, що ви передаєте як параметр), і встановлює зміщення подання відповідно. За бажанням після цього він прокручується до кінця нового, потенційно зміненого вмісту.

Я новачок у програмуванні iOS, і я не знаю, чому це працює настільки добре, що це робить, якщо хтось має якусь інформацію про це, було б приємно знати. Також підхід може бути не ідеальним, тому я також відкритий для вдосконалення ідей.

І звичайно завдяки NixonsBack за розміщення відповіді за посиланням вище.

Мій перший допис :), ура!


Це саме те, що мені потрібно було вирішити цю проблему. Дякую!
BlueGuy


3

Наступний код повинен дати вам бажаний ефект.

[self.scrollView setContentOffset:CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];

Вам потрібно буде замінити "self.scrollView" на ім'я вашого виду прокрутки. Цей код слід вставити після того, як ви встановили текст подання прокрутки.


Я спробував розмістити їх [self.scrollView setContentOffset:CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];у кількох місцях: після чого я встановив код програмно, у viewDidLoad та у viewWillAppear, але без удачі. Я думав, що це пов’язано з моєю панеллю навігації?
Alex Wulff,

2

Це спрацювало для мене:

 override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    textView.scrollRectToVisible(CGRect(origin: CGPointZero, size: CGSizeMake(1.0, 1.0)), animated: false)

}

2

Це працювало для мене з Xcode 8.3.3:

-(void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [self.txtQuestion scrollRangeToVisible:NSMakeRange(0, 0)];
}

2

Створити вихід для вашого UITextViewв ViewController.swiftфайлі. У ViewDidLoadрозділі помістіть наступне:

Стрімкий:

self.textView.contentOffset.y = 0

Я намагався:

self.textView.scrollRangeToVisible(NSMakeRange(0, 0))

1

Я переклав відповідь Zeeple на MonoTouch / Xamarin (C #).

public override void ViewDidLayoutSubviews()
{
    base.ViewDidLayoutSubviews();
    myForm.SetContentOffset(new CoreGraphics.CGPoint(0,0), animated: false);
}

0

Мені довелося застосувати тут дві відповіді, щоб моє подання працювало так, як я хочу:

Від Хуана Девіда Круза Серрано:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    textView.setContentOffset(CGPoint.zero, animated: false)
}

А від Мурата Ясара:

automaticallyAdjustsScrollViewInsets = false

Це дало UITextView, який завантажується з прокруткою в самому верху і де вставки не змінюються після початку прокрутки. Дуже дивно, що це не поведінка за замовчуванням.


0

Щоб змусити textViewкожен раз запускати зверху, використовуйте такий код:

Swift 4.2:

override func viewDidLayoutSubviews() {
    textView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
}

Objective-C:

- (void)viewDidLayoutSubviews {
    [self.yourTextView setContentOffset:CGPointZero animated:NO];
}

0

Свіфт 4.2 і Свіфт 5

встановити зміщення вмісту як до, так і після встановлення тексту. (на головній темі)

let animation = false //or whatever you want
self.mainTextView.setContentOffset(.zero, animated: animation)
self.mainTextView.attributedText = YOUR_ATTRIBUTED_TEXT
self.mainTextView.setContentOffset(.zero, animated: animation)

-1

У моєму випадку я завантажував textView у спеціальну комірку табличного подання. Нижче наведено те, що я зробив для того, щоб текст у текстовому перегляді завантажувався у верхній частині тексту в моєму текстовому перегляді в моїй користувацькій комірці.

1.) У раскадровці встановіть текстовий режим ScrollEnabled = false, знявши прапорець біля кнопки.

2.) Ви встановлюєте для isScrollEnabled значення true у текстовому перегляді після завантаження подання. Я встановив свою з невеликою затримкою, як показано нижче:

override func awakeFromNib() {
    super.awakeFromNib()

let when = DispatchTime.now() + 1
      DispatchQueue.main.asyncAfter(deadline: when){
        self.textView.isScrollEnabled = true
     }

}

Незалежно від того, потрапляєте ви в мою ситуацію чи ні, спробуйте встановити для scrollEnabled значення false, а потім, коли подання завантажиться, встановіть для scrollEnabled значення true.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.