2013-08-02 19 views
11

Robię badania na temat możliwości dynamicznego zmieniania interfejsu użytkownika na podstawie kierunku tekstu. Chociaż Google obsługuje języki RTL (patrz: Native RTL support in Android 4.2), ale nie obejmuje sytuacji, w której aplikacja zawiera mieszankę zawartości LTR i RTL.Jak uzyskać kierunek tekstu w systemie Android i dynamicznie zmieniać układ zgodnie z kierunkiem?

Rozwiązanie Google jest dobre, jeśli mamy aplikację wielojęzyczną i ma różne źródła danych statycznych (np. Pozycje menu) w różnych językach. Jednak nie znalazłem żadnego innego dokumentu dotyczącego dynamicznej zmiany układu w zależności od kierunku zawartości tekstu.

Poniższa ilustracja przedstawia aktualny projekt mojej aplikacji testowej. Lista pochodzi z Facebooka (lista moich znajomych) i zawiera angielskie i perskie nazwy.

enter image description here

Moje rozwiązanie jest o dwa układy (jeden dla LTR i jeden dla RTL) w adapterze i przypisanie każdemu oparciu o kierunku nazwie. Tak, napisałem następujące wiersze kodu:

@Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
     ViewHolder holder; 

      if(position % 2 == 0) 
       convertView = myInflater.inflate(R.layout.list_add_friends_row, null); 
      else 
       convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null); 

      holder = new ViewHolder(); 

      holder.llSection = (LinearLayout) convertView.findViewById(R.id.section); 
      holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName); 
      holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture); 
      holder.btnAdd = (Button) convertView.findViewById(R.id.btnAdd); 

      convertView.setTag(holder); 



     holder.btnAdd.setTag(position); 
     holder.tvUserName.setText(userList.get(position).getName()); 
     imageDownloader.displayImage(holder.ivPicture, userList.get(position).getPhotoUrl()); 

     ... 

     return convertView; 
    } 

i wynik brzmi:

enter image description here

I lustrzane wiersze na podstawie jeśli wiersz jest parzyste, czy nieparzyste. Teraz moje pytanie brzmi: jak lustrzany interfejs użytkownika oparty na nazwie. Myślę, że powinienem zmienić warunek klauzuli z if(position % 2 == 0) na coś takiego jak if(isNameLTR(FIRST_CHAR_OF_NAME)). Nie mam pojęcia, jak wdrożyć tę metodę.

Skąd mogę wiedzieć, że postać to LTR ot RTL? (Wydaje mi się, że Android zna pierwszą literę słowa, to RTL lub LTR, dlatego gdy szerokość tekstu jest zgodna z matką, wyrównuje tekst do prawej, jeśli znak jest RLT, a lewy, jeśli znak jest LTR).

Wszelkie sugestie lub komentarze będą mile widziane. Dzięki

Odpowiedz

22

Rozwiązanie było łatwiejsze, że myślałem :) Dzięki JAVA

Istnieje Bidi klasa. Ta klasa ma wartość getBaseLevel() method, która zwraca 0, jeśli tekst jest od lewej do prawej, w przeciwnym razie 1 (jeśli od prawej do lewej).

Tak, to jest mój kod:

@Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
     ViewHolder holder; 

     Bidi bidi = new Bidi(userList.get(position).getName(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); 
     if(bidi.getBaseLevel() == 0) 
      convertView = myInflater.inflate(R.layout.list_add_friends_row, null); 
     else 
      convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null); 

... 

i wynik brzmi:

enter image description here

=============

Aktualizacja:

Istnieje inna metoda, baseIsLeftToRight(), które mogą być lepiej wykorzystane w instrukcji if. Wynik był taki sam jak powyżej.

Bidi bidi = new Bidi(userList.get(position).getName(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); 
if(bidi.baseIsLeftToRight()) 
       convertView = myInflater.inflate(R.layout.list_add_friends_row, null); 
      else 
       convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null); 
0

Zastosowanie textAlignment z gravity, aby wszystkie teksty PRAWO lub LEWO

android:gravity="right" 
android:textAlignment="gravity" 
0

Jeśli tekst jest w TextView, to wszystko co musisz zrobić, to

android:textDirection="anyRtl" 

, aby wymusić RTL. Zobacz inne opcje dla swoich wymagań.

Może się zdarzyć, że tekst w mieszanym języku nie będzie wyświetlany w postaci TextView. Na przykład tekst może zostać przekazany w udziale Intent do Gmaila lub WhatsApp i tak dalej. W takich przypadkach należy użyć kombinacji następujących klas:

cytowany w dokumentacji, to są ...

klasie użytkowej [es] do formatowania tekstu do wyświetlenia w kontekście potencjalnie przeciwnych kierunków bez garbowania. Kierunek kontekstu jest ustalany podczas tworzenia formatyzatora, a kierunek tekstu może być oszacowany lub przekazany, gdy jest znany.

Tak na przykład, że masz String który ma kombinację angielskiej & arabski, i trzeba ten tekst, aby być

  • prawo-lewo (RTL).
  • zawsze wyrównany do prawej, nawet jeśli zdanie zaczyna się od angielskiego.
  • Angielski & Arabskie słowa we właściwej kolejności i bez garbowania.

to można to osiągnąć stosując metodę unicodeWrap() następująco:

String mixedLanguageText = ... // mixed-language text 

if(BidiFormatter.getInstance().isRtlContext()){ 
    Locale rtlLocale = ... // RTL locale 
    mixedLanguageText = BidiFormatter.getInstance(rtlLocale).unicodeWrap(mixedLanguageText, TextDirectionHeuristics.ANYRTL_LTR); 
} 

Byłoby to przekonwertować ciąg na RTL i wyrównać go w lewo, jeśli nawet jeden znak RTL-język był w ciągu i w innym wypadku powrót do LTR. Jeśli chcesz, aby łańcuch był RTL, nawet jeśli jest kompletny, na przykład angielski (język LTR), możesz użyć TextDirectionHeuristics.RTL zamiast TextDirectionHeuristics.ANYRTL_LTR.

Jest to właściwy sposób obsługi tekstu mieszanego w przypadku braku numeru TextView. Co ciekawe, jak wskazuje dokumentacja,

zauważyć również, że te heurystyki kierunek odpowiadać na te same rodzaje stałych przewidzianych w klasie View dla setTextDirection(), takich jak TEXT_DIRECTION_RTL.

Dalsze odniesienia:

1.Write text file mix between arabic and english.

2.Unicode Bidirectional Algorithm.