2016-12-24 39 views
5

Mam jeden UITextView, który pozwala pisać wiele wierszy tekstu.Umożliwia zaznaczanie kursora w dowolnym miejscu w UITextView

Jak mogę pozwolić użytkownikom wybierać litery pomiędzy słowami bez dłuższego naciskania?

Obecnie, przy użyciu ekranu dotykowego, aby wybrać znaki między słowem kursor albo idzie na początku lub na końcu wyrazu:

Przykład: klikając na „c” przesuwa kursor na koniec słowa

cursor at end

przykład: kliknięcie na 'A' przesuwa kursor na początek słowa

cursor at start

Pożądany kursor zachowanie: Wybór nigdzie w tekście enter image description here

Cechą umożliwiając zaznaczenie tekstu w dowolnym miejscu (bez długiego prasy + lupy) znajduje się w wielu aplikacjach edytor kodu dla iOS, takich jak Coda i Pythonista.

+1

Czy to nie jest problem sprzętowy? Lub przynajmniej problem systemowy. W końcu na iPadzie jest sposób na "przesuwanie" punktu wstawiania tam, gdzie chcesz. Ale na iPhone'ie. Więc to nie zależy od ciebie. – matt

+0

@matt Próbowałem tylko niektórych aplikacji do edytora kodu dla iPhone'a, niektóre z nich pozwalają na wstawienie punktu w dowolnym punkcie, ale nie jestem pewien, jak to osiągnęli. Na przykład w jednej z aplikacji, z tym tekstem 'System.out.println ("hello") ', użytkownik może wybrać dowolne miejsce w' UITextView', aby zmienić argument. – user2560886

+0

edytory wyboru poziomu postaci (Coda i Pythonista?) Mogą nie używać UITextView. Można utworzyć niestandardowy widok edytora tekstów (zapoznaj się z dokumentem "Podręcznik programowania dla iOS"). – 9dan

Odpowiedz

3

To nie jest trudne wyzwanie.

Wstępnie powiem, że problem z tym podejściem jest spójny. Pamiętaj, że twoi użytkownicy używają palców, a nie stilii. Palec ma dużą powierzchnię, a trafienie w precyzyjną strefę pikseli jest dość trudne, szczególnie w przypadku małego tekstu. Sugerowałbym grę nie w symulatorze, gdzie masz precyzyjne urządzenie wskazujące, ale na urządzeniu.

Pierwszym wyzwaniem jest wyłączenie domyślnego zachowania się kranu lub UITextView. Nie jest to trudne zadanie - możesz albo "zaatakować" problem na poziomie touchesBegan:withEvent:, gdzie musisz zrozumieć, czym są te dotknięcia (dotknięcie pojedynczego przycisku w porównaniu z przesunięciem w porównaniu z długim naciśnięciem) lub na poziomie narzędzia do rozpoznawania gestów, gdzie wyłączyć wyłączne rozpoznawanie gestów w widoku tekstowym, które wyraźnie obsługują ruch kursora w przypadku dotknięcia (w porównaniu z innymi typami dotyku). Zrobiłem to drugie dla różnych projektów i jest to możliwe. Możesz także spróbować podejść bez wyłączania domyślnego zachowania, ale wtedy kursor może migać. Testuj i decyduj.

Teraz, aby osiągnąć to, czego potrzebujesz. W jakiś sposób uzyskaj punkt kontaktu (korzystając z interfejsu API UIResponder lub rozpoznawania gestów). Pamiętaj, że widok tekstowy jest widokiem przewijania, który zawiera duży widok, do którego wciąga się treść. Konwertuj ten punkt dotyku, z układu współrzędnych widoku tekstowego, do układu współrzędnych widoku wewnętrznego, korzystając z interfejsu API convertPoint:. Kiedy już, że można użyć menedżera układu widoku tekstowego, aby uzyskać indeks znaków w momencie dotyku:

NSUInteger chIdx = [self characterIndexForPoint:touchPoint inTextContainer:self.textContainer fractionOfDistanceBetweenInsertionPoints:NULL]; 

Można użyć tego indeksu, aby ustawić kursor w widoku tekstu za pomocą właściwości selectedRange.

+0

Czy wiesz, jak dodać trochę luzu do lokalizacji używanej dla 'characterIndexForPoint', np. rejestrowanie stuknięć plus/minus 1px jako stuknięcie w znak – user2560886

+0

Będziesz musiał to zrobić heurystycznie, używając 'boundingRectForGlyphRange: inTextContainer:'. Zauważ, że jest to obszar zasięgu glifu, podczas gdy twój kursor znajduje się w zakresie znaków (i tak w NSString). –

+0

Problem, który napotykam, polega na tym, że jeśli wybór znaku jest nieco powyżej/powyżej linii, 'characterIndexForPoint' zwraca zły indeks, odpowiadający znakom na początku/końcu linii, zamiast" najbliższy "znak w linii. kierunek osi y Nie jestem pewien w jaki sposób 'boundingRectForGlyphRange' pasuje do mojego kodu. Czy chodzi o przepływ, który masz na myśli: 1) uzyskaj zakres glifów dla linii tekstu w UITextView' 2) uzyskaj granice rect dla zakresu glifów 3) rozwiń granice rect o +/- 1 px 4) Użyj 'characterIndexForPoint', aby uzyskać indeks z obwiednią rect? – user2560886