1

我想实现一个按字母顺序排序的可滚动列表。作为参考,我使用的是 Eclipse IDE 附带的 Tree Screen 示例。

我更改了数据模板以满足我的需要,它就像一个魅力,直到你想滚动。整个用户界面都搞砸了,我不知道该怎么办。我正在使用 JRE 7.1 和 Blackberry Simulator 9860 7.0(我还在真实设备上对其进行了测试)。

有人知道这是一个已知问题还是我错过了什么?

package lifeApp;

import net.rim.device.api.command.Command;
import net.rim.device.api.command.CommandHandler;
import net.rim.device.api.command.ReadOnlyCommandMetadata;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.component.table.DataTemplate;
import net.rim.device.api.ui.component.table.RegionStyles;
import net.rim.device.api.ui.component.table.SortedTableModel;
import net.rim.device.api.ui.component.table.TableController;
import net.rim.device.api.ui.component.table.TableModel;
import net.rim.device.api.ui.component.table.TableView;
import net.rim.device.api.ui.component.table.TemplateColumnProperties;
import net.rim.device.api.ui.component.table.TemplateRowProperties;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.decor.Border;
import net.rim.device.api.ui.decor.BorderFactory;
import net.rim.device.api.util.StringComparator;

public class ProductsScreen extends MainScreen
{
private SortedTableModel _tableModel;

private static final int ROW_HEIGHT = 40;

public ProductsScreen()
{
    super(Manager.NO_VERTICAL_SCROLL | Manager.HORIZONTAL_SCROLL);

    setTitle("Alle Produkte A-Z");

    add(new LabelField("BlackBerry Devices", LabelField.FIELD_HCENTER));
    add(new SeparatorField());

    _tableModel = new SortedTableModel(StringComparator.getInstance(true), 0);

    _tableModel.addRow(new Object[] {"A", "Produkt1"});
    _tableModel.addRow(new Object[] {"b", "Produkt2"});
    _tableModel.addRow(new Object[] {"c", "Produkt3"});
    _tableModel.addRow(new Object[] {"c", "Produkt4"});
    _tableModel.addRow(new Object[] {"b", "Produkt5"});
    _tableModel.addRow(new Object[] {"c", "Produkt6"});
    _tableModel.addRow(new Object[] {"c", "Produkt7"});
    _tableModel.addRow(new Object[] {"r", "Produkt8"});
    _tableModel.addRow(new Object[] {"t", "Produkt9"});
    _tableModel.addRow(new Object[] {"c", "Produkt10"});
    _tableModel.addRow(new Object[] {"b", "Produkt11"});
    _tableModel.addRow(new Object[] {"u", "Produkt12"});
    _tableModel.addRow(new Object[] {"v", "Produkt13"});
    _tableModel.addRow(new Object[] {"t", "Produkt14"});
    _tableModel.addRow(new Object[] {"c", "Produkt15"});
    _tableModel.addRow(new Object[] {"b", "Produkt16"});
    _tableModel.addRow(new Object[] {"u", "Produkt17"});
    _tableModel.addRow(new Object[] {"v", "Produkt18"});

    RegionStyles style = new RegionStyles(BorderFactory.createSimpleBorder(new XYEdges(1, 1, 1, 1), Border.STYLE_SOLID), null, null,
        null, RegionStyles.ALIGN_LEFT, RegionStyles.ALIGN_TOP);

    TableView tableView = new TableView(_tableModel);
    TableController tableController = new TableController(_tableModel, tableView);

    tableController.setFocusPolicy(TableController.ROW_FOCUS);

    tableController.setCommand(new Command(new CommandHandler()
    {
        public void execute(ReadOnlyCommandMetadata metadata, Object context)
        {
            Dialog.alert("Command Executed");
        }           
    }));

    tableView.setController(tableController);

    DataTemplate dataTemplate = new DataTemplate(tableView, 1, 1)
    {
        /**
         * @see DataTemplate#getDataFields(int)
         */
        public Field[] getDataFields(int modelRowIndex)
        {
            final Object[] data = (Object[]) ((TableModel) getView().getModel()).getRow(modelRowIndex);

            Field[] fields = new Field[1];
            fields[0] = new LabelField((String)data[1], Field.USE_ALL_WIDTH | Field.FOCUSABLE | DrawStyle.HCENTER);

            return fields;
        }
    };

    dataTemplate.createRegion(new XYRect(0, 0, 1, 1), style);  
    dataTemplate.setColumnProperties(0, new TemplateColumnProperties(100, TemplateColumnProperties.PERCENTAGE_WIDTH));
    dataTemplate.setRowProperties(0, new TemplateRowProperties(ROW_HEIGHT));

    tableView.setDataTemplate(dataTemplate);
    dataTemplate.useFixedHeight(true);

    add(tableView);
}
}
4

1 回答 1

1

好吧,我加载了 JDE 7.1 UI/TableAndListDemo示例应用程序,并在 JDE 9900 上运行它。

该示例(未经我修改)表现出与您发布的代码完全相同的古怪行为。

所以,不幸的是,我会说要么存在错误,要么没有产生如何使用相对较新的有效示例SortedTableModel(我找不到更好的示例)。

注意:如果您删除排序并简单地替换SortedTableModelTableModel,那么视觉损坏对我来说就消失了。当然,您失去了排序和分组的重要功能(表模型中的第 0 列)。

另一种选择是自己实现排序行为。对外部的数据进行排序TableModel是不可取的,但也不是太难。然后,您可以在重复模式中添加一个额外的行,作为当前显示单个字符(排序标准)的分隔符行的占位符。您还将数据模板更改为固定高度。

此外,在数据模板中,您将定义一个可以容纳分隔符行的区域。该区域是否显示任何内容取决于随后的数据行是否与最后一行具有相同的单个字符。所以,这就是代码的样子

  DataTemplate dataTemplate = new DataTemplate(tableView, 2, 1)    // 2 "rows", not 1
  {
     public Field[] getDataFields(int modelRowIndex)
     {
        final Object[] data = (Object[]) _tableModel.getRow(modelRowIndex);

        Field[] fields = new Field[2];
        String rowGroup = (String)data[0];
        // we're in a new group if this is the very first row, or if this row's
        //  data[0] value is different from the last row's data[0] value
        boolean isNewGroup = (modelRowIndex == 0) || 
              (rowGroup.compareTo((String) ((Object[])_tableModel.getRow(modelRowIndex - 1))[0]) != 0);
        if (isNewGroup) {
           // make a separator row
           fields[0] = new LabelField((String)data[0], 
                          Field.USE_ALL_WIDTH | Field.NON_FOCUSABLE);
        } else {
           // this is in the same group as the last product, so don't add anything here
           fields[0] = new NullField();
        }
        // now, add the actual product information
        fields[1] = new LabelField((String)data[1], 
                          Field.USE_ALL_WIDTH | Field.FOCUSABLE | DrawStyle.HCENTER);

        return fields;
     }
  };


  dataTemplate.createRegion(new XYRect(0, 0, 1, 1), style);    // group separator (maybe a null field)
  dataTemplate.createRegion(new XYRect(0, 1, 1, 1), style);    // actual rows with product information
  dataTemplate.setColumnProperties(0, new TemplateColumnProperties(100, TemplateColumnProperties.PERCENTAGE_WIDTH));
  dataTemplate.setRowProperties(0, new TemplateRowProperties(ROW_HEIGHT));   // separator
  dataTemplate.setRowProperties(1, new TemplateRowProperties(ROW_HEIGHT));   // product data
  dataTemplate.useFixedHeight(false);

在上面的代码中,我选择使分隔行与产品数据行具有相同的高度和样式。当然,如果你愿意,你可以改变它。

这仍然无法解决的一个问题是焦点绘制问题。当您突出显示分隔符行下方的第一行时,它会将焦点吸引到产品行及其上方的分隔符行上。

您可能需要实现一些自定义焦点绘图。我将把它留给下一个问题......不确定你是否想走这条路。希望我错了,但对我来说这有点像 RIM 库中的错误:(

于 2012-07-01T12:02:02.583 回答