【问题标题】:Blackberry Tablemodel gets messed up when scrolling黑莓表格模型在滚动时变得混乱
【发布时间】:2012-06-25 12:09:48
【问题描述】:

我想实现一个按字母顺序排序的可滚动列表。 作为参考,我使用了 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);
}
}

【问题讨论】:

    标签: blackberry tableview tablemodel


    【解决方案1】:

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

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

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

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

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

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

      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 库中的错误:(

    【讨论】:

    • 嗨@Nate。谢谢你的回复。我已经用你发布的 sn-p 进行了尝试,它正在工作(有提到的突出显示问题:-))。如果我能为 SortedTableModel 提出解决方案,我会告诉你的。
    • @spycob,是的,如果您决定使用这种自行滚动的排序方法来解决错误(?),只需使用您使用的代码发布一个新问题,然后说您需要帮助正确绘制焦点,以便分隔行也不会突出显示。
    • 我会这样做的。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2015-12-10
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    相关资源
    最近更新 更多