Blackberry: почему drawListRow () вызывается с разными y для ListField и KeywordFilterField - PullRequest
3 голосов
/ 17 мая 2011

Я пытаюсь переместить приложение из использования KeywordFilterField в ListField, и я несколько часов пытаюсь выяснить, почему метод drawListRow () вызывается с разными y значения - в зависимости от того, какой из этих двух списков ListField я использую:

Если getRowHeight () возвращает 40, тогда значения y будут -

Для KeywordFilterField являются: 0;40;80;120;... (то есть, как и ожидалось)

Но для Список полей Я вижу: 9;49;89;129;... (то есть по какой-то причине смещено на 9 )

Откуда исходит 9?Есть ли в ListField или ListFieldCallback метод, который я мог бы вызвать, чтобы получить это значение?Я просто пытаюсь нарисовать светло-серую линию между элементами списка.

listfield

Ниже мой тестовый код и border.png (используется как граница BasicEditField) прикреплен:

border.png

package mypackage;

import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*; 
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;


public class MyList extends UiApplication {
    public static void main(String args[]) {
        MyList app = new MyList();
        app.enterEventDispatcher();
    }

    public MyList() {
        pushScreen(new MyScreen());
    }
} 

class MyScreen extends MainScreen {
    static final int EXTRA_ROWS = 2;

    MyItemList myItems = new MyItemList();
    ListField myList = new ListField(EXTRA_ROWS);

    Border myBorder = BorderFactory.createBitmapBorder(
        new XYEdges(12, 12, 12, 12),
        Bitmap.getBitmapResource("border.png"));

    Background myBg = BackgroundFactory.createSolidBackground(0x111111);
    StringProvider myProvider = new StringProvider("Search");

    BasicEditField myFind = new BasicEditField(USE_ALL_WIDTH) {
        protected void paint(Graphics g) {
            if (getTextLength() == 0) {
                g.setColor(Color.LIGHTGRAY);
                g.drawText(myProvider.toString(), 0, 0);
            }

            g.setColor(Color.BLACK);
            super.paint(g);
        }
    };

    public MyScreen() {
        getMainManager().setBackground(myBg);

        myFind.setBorder(myBorder);
        setTitle(myFind);

        myItems.doAdd(new MyItem(1, "Eins"));
        myItems.doAdd(new MyItem(2, "Zwei"));
        myItems.doAdd(new MyItem(3, "Drei"));
        myItems.doAdd(new MyItem(4, "Vier"));

        myList.setCallback(new MyListFieldCallback());
        add(myList);
    }

    private class MyListFieldCallback implements ListFieldCallback {

        public void drawListRow(ListField list, Graphics g, int index, int y, int width) {
            System.err.println("XXX index=" + index+ ", y=" + y + ", width=" + width);

            g.setColor(Color.WHITE);

            if (index < EXTRA_ROWS) {
                Font i = getFont().derive(Font.ITALIC);
                g.setFont(i);
                g.drawText("Add Item", 0, y);
                return;
            } 

            if (index >= EXTRA_ROWS) {
                MyItem item = (MyItem) myItems.getAt(index - EXTRA_ROWS);
                g.drawText(item.toString(), 0, y);

                g.setColor(0x333333);
                // XXX why do I need to subtract 9 here?
                g.drawLine(0, y-9, width, y-9);

                return;
            }

            g.drawText(list.getEmptyString(), 0, y);
        }

        public Object get(ListField list, int index) { 
            return myItems.getAt(index); 
        }

        public int getPreferredWidth(ListField list) { 
            return Display.getWidth(); 
        }

        public int indexOfList(ListField list, String prefix, int start) { 
            return 0; 
        }
    }

    class MyItemList extends SortedReadableList {
        public MyItemList() {
            super(new MyItem.MyComparator());        
        } 

        protected void doAdd(Object obj) {
            super.doAdd(obj);
            myList.setSize(size() + EXTRA_ROWS);  
        }

        protected boolean doRemove(Object obj) {
            myList.setSize(size() - 1 + EXTRA_ROWS);
            return super.doRemove(obj);        
        }
    }
}

class MyItem {
    int _num;
    String _name;

    public MyItem(int num, String name) {
        _num = num;
        _name = name;
    }

    public String toString() {
        return _num + ": " + _name;
    }

    static class MyComparator implements Comparator {
        public int compare(Object obj1, Object obj2) {
            MyItem item1 = (MyItem) obj1;
            MyItem item2 = (MyItem) obj2;

            return item1.toString().compareTo(item2.toString());
        }
    }

    static class MyProvider implements KeywordProvider {
        public String[] getKeywords(Object obj) {
            MyItem item = (MyItem) obj;
            return new String[]{ Integer.toString(item._num), item._name };
        }
    }
}

Полученный результат:

[    64,890] XXX index=0, y=9, width=360
[    64,890] XXX index=1, y=49, width=360
[    64,898] XXX index=2, y=89, width=360
[    64,898] XXX index=3, y=129, width=360
[    64,906] XXX index=4, y=169, width=360
[    64,906] XXX index=5, y=209, width=360

ОБНОВЛЕНИЕ в ответ на jprofitt

Когда я попробую ваше предложение (я использую красный цвет для вашего текста и линий):

    if (index >= EXTRA_ROWS) {
        MyItem item = (MyItem) myItems.getAt(index - EXTRA_ROWS);
        g.drawText(item.toString(), 0, y);

        g.setColor(Color.RED);                
        g.drawText("XXX", 0, y + (list.getRowHeight() - list.getFont().getHeight())/2);

        g.setColor(0x333333);
        // XXX why do I need to subtract 9 here?
        g.drawLine(0, y-9, width, y-9);

        g.setColor(Color.RED);
        g.drawLine(0, y, width, y);
        return;
    }

Тогда это на самом деле не работает - потому что синяя линия фокуса не совпадает с вашими предлагаемыми (красными) линиями.Он совпадает с моими (серыми) линиями, что означает, что вам действительно нужно вычесть -9 по некоторым причинам:

not aligned

Спасибо!Alex

Ответы [ 2 ]

2 голосов
/ 26 мая 2011

Да, это странное поведение.Я думаю, что это что-то особенное OS 6.Похоже, в OS 6 ListField стало настолько умным, что он передает координату Y, уже подготовленную для непосредственного использования при рисовании текста, поэтому вам не нужно выполнять ручной расчет (обычно я вычисляю Y для рисования текста так, как предлагает jprofitt),Поэтому, предполагая, что мои предположения верны, я изменил код следующим образом:

if (index >= EXTRA_ROWS) {
    MyItem item = (MyItem) myItems.getAt(index - EXTRA_ROWS);
    g.drawText(item.toString(), 0, y);

    g.setColor(0x333333);
    // XXX why do I need to subtract 9 here?

    // use the offset instead
    int offset = (myList.getRowHeight() - getFont().getHeight()) >> 1;

    g.drawLine(0, y - offset, width, y - offset);

    return;
}

, и он отлично работает (проверено на всех размерах шрифта, доступных в настройках устройства).

2 голосов
/ 19 мая 2011

Хорошо, я верю, что понял это. Что происходит, так это то, что высота строки больше высоты шрифта. Поэтому, когда вы рисуете текст прямо в точке y, вы рисуете его сверху, выровненным по фактической строке. В моем случае высота строки равнялась 40, а высота шрифта - 20. Половина этой разницы заключается в том, куда входил ваш y - 9. Если вы измените вызовы drawText () на него, он должен работать без необходимости вычитать что-либо при рисовании строка:

g.drawText(theString, 0, y + (list.getRowHeight() - list.getFont().getHeight())/2);

Вы можете кэшировать высоту шрифта и высоту строки, чтобы вам не приходилось выполнять вычисления в paint () для эффективности.

...