2012-10-16 16 views
8

I zostały próby rysunek to jedno z ostatnich kilku dni teraz, i nie miał powodzenia ...Android Spannable Linia Wysokość

uczę androida teraz, i obecnie stworzenie kalkulatora z historią jako moim projektem edukacyjnym. Mam TextView, który jest odpowiedzialny za wyświetlanie całej historii ... Używam cyfrowej czcionki, która wygląda jak czcionka kalkulatora, ale to dobrze wygląda tylko dla cyfr i dziesiętnych i przecinków. Chcę, żeby wszyscy operatorzy byli wyróżnieni i mieli inną czcionkę (Arial Narrow w tej chwili). Udało mi się sprawić, by działało to pięknie, używając ciągu spannable, w którym określam kolor czcionki, a także czcionkę, używając klasy CustomTypeFaceSpan, aby zastosować własne czcionki.

Problem ... Kiedy miksuję kroje pisma, wydaje się, że istnieje problem z wysokością linii, więc znalazłem this post, który demonstruje użycie innej niestandardowej zdefiniowanej klasy, aby zastosować wysokość linii do każdej dodanej linii tekstu spannable:

public class CustomLineHeightSpan implements LineHeightSpan{ 
    private final int height; 

    public CustomLineHeightSpan(int height){ 
     this.height = height; 
    } 

    @Override 
    public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v, FontMetricsInt fm) { 
     fm.bottom += height; 
     fm.descent += height; 
    } 

} 

To nie działa, a ja nie mogę zrozumieć dlaczego. Jeśli nie zastosuję różnych krojów, to zostanie wyświetlony zgodnie z oczekiwaniami, bez spacji powyżej pierwszej linii i około 5px odstępu między wierszami. Gdy stosuję alternatywne kroje pisma, istnieje odstęp od 10 do 15 pikseli nad pierwszą linią tekstu, a odstępy między wierszami są takie same od 10 do 15 pikseli.

Nie ma różnicy w rozmiarze czcionki, tylko krój czcionki. Czego mi brakuje. Zaimplementowałem CustomLineHeightSpan, która implementuje LineHeightSpan i zastępuje metodę chooseHeight. Nazywam to tak:

WordtoSpan.setSpan (nowy CustomLineHeightSpan (10), operatorPositions.get (ii), operatorPositions.get (ii) + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

Wygląda na to, że nie ma znaczenia, co wywołałem w CustomLineHeightSpan. Nic się nie zmienia ...

Ktoś ma pojęcie o tym, czego mi brakuje ... Jestem pewien, że to odpowiedź "nie mogę uwierzyć, że tęskniłem", ale nie mogę tego rozgryźć za chwilę.

Dzięki za pomoc chłopaki :-)

Odpowiedz

17

końcu znalazłem więcej w przykładzie głębokości stosowania LineHeightSpan ... Właściwie LineHeightSpan.WithDensity dokładniej ... Poniżej znajduje się fragment, który pomógł do rozwiązania problemu:

private static class Height implements LineHeightSpan.WithDensity { 
    private int mSize; 
    private static float sProportion = 0; 

    public Height(int size) { 
     mSize = size; 
    } 

    public void chooseHeight(CharSequence text, int start, int end, 
          int spanstartv, int v, 
          Paint.FontMetricsInt fm) { 
     // Should not get called, at least not by StaticLayout. 
     chooseHeight(text, start, end, spanstartv, v, fm, null); 
    } 

    public void chooseHeight(CharSequence text, int start, int end, 
          int spanstartv, int v, 
          Paint.FontMetricsInt fm, TextPaint paint) { 
     int size = mSize; 
     if (paint != null) { 
      size *= paint.density; 
     } 

     if (fm.bottom - fm.top < size) { 
      fm.top = fm.bottom - size; 
      fm.ascent = fm.ascent - size; 
     } else { 
      if (sProportion == 0) { 
       /* 
       * Calculate what fraction of the nominal ascent 
       * the height of a capital letter actually is, 
       * so that we won't reduce the ascent to less than 
       * that unless we absolutely have to. 
       */ 

       Paint p = new Paint(); 
       p.setTextSize(100); 
       Rect r = new Rect(); 
       p.getTextBounds("ABCDEFG", 0, 7, r); 

       sProportion = (r.top)/p.ascent(); 
      } 

      int need = (int) Math.ceil(-fm.top * sProportion); 

      if (size - fm.descent >= need) { 
       /* 
       * It is safe to shrink the ascent this much. 
       */ 

       fm.top = fm.bottom - size; 
       fm.ascent = fm.descent - size; 
      } else if (size >= need) { 
       /* 
       * We can't show all the descent, but we can at least 
       * show all the ascent. 
       */ 

       fm.top = fm.ascent = -need; 
       fm.bottom = fm.descent = fm.top + size; 
      } else { 
       /* 
       * Show as much of the ascent as we can, and no descent. 
       */ 

       fm.top = fm.ascent = -size; 
       fm.bottom = fm.descent = 0; 
      } 
     } 
    } 
} 

Zostało to zrobione z this example.

Co robi jest cytowany poniżej:

Siły linii tekstu być określona wysokość, kurczenie/rozciąganie wznoszenie się, jeśli to możliwe, lub zejście jeśli kurczy się wznosić dalej uczyni tekst nieczytelne.

Mam nadzieję, że to pomoże następną osobę :-)

+1

Jak wywołać tę metodę chooseHeight? – AndroidCrazy

+0

Android wywołuje tę metodę wewnętrznie. Wszystko, co musisz zrobić, to nadać swojemu Stringowi rozpiętość. Jeśli chcesz dowiedzieć się więcej, sprawdź klasę android.text.StaticLayout. Również tam są wywoływane metody dla innych przęseł. – thehayro

+3

Jeśli kiedykolwiek się spotkamy, jestem ci winien piwo (lub inny napój z wyboru) - to jest super nieudokumentowane i znalezienie go zajmuje szalony czas. – secureboot

Powiązane problemy