1

長いテキストコンテンツがあり、または他の何かを使用して位置合わせを正当化して画面に表示したいと思います。現在、右/左/中央揃えはできますが、位置合わせを正当化するLabelFieldことはできません。

これを行うのに役立つカスタムコントロールはありますか?

4

1 に答える 1

2

これは単なるプロトタイプであるため、処理できないものがある可能性があります。しかし、それはあなたがやりたいことをするために使うことができる出発点であるべきです。重要なロジックのほとんどはpaint()メソッドにあります。

これを行うための組み込み(RIMライブラリ)の方法を私は知りません。

public class JustifiedLabelField extends LabelField {

   /** a cache of the label's words, to avoid having to recalculate every
       time paint() is called */
   private String[] _words;
   /** the dynamic field height */
   private int _height = 0;

   public JustifiedLabelField(Object text, long style){
      super(text, style);
      setText(text);
   }

   public void setText(Object text) {
      // update the words cache when text changes
      _words = split((String)text, " ");  // NOTE: this only supports String type!
      super.setText(text);
   }

   public int getPreferredHeight() {
      // I believe overriding this method is necessary because the 
      //  justification might produce a different total number of lines, 
      //  depending on the algorithm used
      return (_height > 0) ? _height : super.getPreferredHeight();
   }

   protected void paint(Graphics g) {
      Font font = g.getFont();
      int space = font.getAdvance(' ');
      int fontHeight = font.getHeight();
      int fieldWidth = getWidth();         
      int word = 0;
      int y = 0;
      while (word < _words.length) {
         // each iteration of this loop handles one line
         int wordsInLine = 0;
         int lineWordWidths = 0;
         // first loop over all words that fit on this line, to measure
         while (word < _words.length) {
            int wordWidth = font.getAdvance(_words[word]);
            if (lineWordWidths + wordWidth <= fieldWidth) {
               lineWordWidths += (wordWidth + space);
               word++;
               wordsInLine++;
            } else {
               break;
            }
         }

         // how much total space (gap) should be placed between every two words?
         int gapSpacing = 0;
         if (word == _words.length) {
            // don't justify at all on last line
            gapSpacing = space;
         } else if (wordsInLine != 1) {
            gapSpacing = (fieldWidth - (lineWordWidths - wordsInLine * space)) / (wordsInLine - 1);
         }

         int x = 0;
         // now actually draw the words, with added spacing
         for (int j = word - wordsInLine; j < word; j++) {
            int span = g.drawText(_words[j], x, y);
            x += span + gapSpacing;            
         }

         y += fontHeight;
      }
      _height = y;
   }
}

上記のコードはString split()メソッドを利用しています。ここで1つの可能な実装を見つけることができます。

次に、次のようなクラスを使用します。

   public LabelScreen() {
      super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);

      String loremIpsum = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam cursus. Morbi ut mi. Nullam enim leo, egestas id, condimentum at, laoreet mattis, massa. Sed eleifend nonummy diam. Praesent mauris ante, elementum et, bibendum at, posuere sit amet, nibh. Duis tincidunt lectus quis dui viverra vestibulum. Suspendisse vulputate aliquam dui. Nulla elementum dui ut augue. Aliquam vehicula mi at mauris. Maecenas placerat, nisl at consequat rhoncus, sem nunc gravida justo, quis eleifend arcu velit quis lacus. Morbi magna magna, tincidunt a, mattis non, imperdiet vitae, tellus. Sed odio est, auctor ac, sollicitudin in, consequat vitae, orci. Fusce id felis. Vivamus sollicitudin metus eget eros.";
      JustifiedLabelField label = new JustifiedLabelField(loremIpsum, Field.NON_FOCUSABLE);
      add(label);
   }

これを生成する:

ここに画像の説明を入力してください

制限事項

  • このフィールドのパディングなどを説明するために何もしません
  • LabelFieldsetText()だけでなく、他のタイプでまたはコンストラクターを呼び出すことができますString。私のクラスはをサポートしているだけStringですが、それを簡単に拡張できます。
  • 私のクラスは文字列をスペース(' ')でのみ分割します。他の文字の分割をサポートしたり、ダッシュを挿入して非常に長い単語を分割したりすることもできます。それはあなたにお任せします。
  • フィールド幅に収まらないほど長い単語など、エッジケースはテストしませんでした。私はこれを全画面幅のフィールドで、小から中サイズの単語でのみテストしました。
  • 使用した方法については、リンク先のページにあるEugenのコメントを参照してください。split()

ファローアップ

上に投稿したコードを少し改良して、ここにオンラインで投稿しました。新しいバージョンはパディングを処理する必要がありますが、このバージョンは処理しません。LabelFieldスーパークラスがフィールドに必要と考える行数を変更する文字列分割アルゴリズムを選択した場合も、垂直方向のサイズの問題を処理する必要があります。その他のコメントも。

于 2013-03-03T06:52:49.930 に答える