我有一個關於BlackBerry VerticalScrollField和滾動的問題,它似乎鎖定或使UI不穩定。以下代碼是黑莓屏幕,左邊是內容世界(位於滾動字段中),右邊是跳轉欄,允許點擊內容。具有跳轉點的垂直滾動條 - setVerticalScroll鎖定UI
當單擊一個跳轉字母時,會調用setVerticalScroll方法,它會執行滾動,但會產生令用戶界面不穩定或不可用的副作用。滾動調用是在UI線程上完成的,因此它不清楚錯誤的來源。該應用正在6.0模擬器中測試。
我已經包含了可以複製到BB Eclipse中用於黑客/測試的類。
滾動的那踢部分可以向下面的代碼底部找到:
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run() {
scroller.setVerticalScroll(y, true);
}});
下面是完整的類:
package test;import java.util.Vector;
import net.rim.device.api.system.ApplicationManager; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.Font; import net.rim.device.api.ui.Graphics; import net.rim.device.api.ui.TouchEvent; import net.rim.device.api.ui.UiApplication; import net.rim.device.api.ui.component.LabelField; import net.rim.device.api.ui.component.Status; import net.rim.device.api.ui.container.HorizontalFieldManager; import net.rim.device.api.ui.container.MainScreen; import net.rim.device.api.ui.container.VerticalFieldManager;
public class Startup extends UiApplication { private int[] jump; static final String[] words = new String[]{ "auto", "apple", "bear", "car", "farm", "ferret", "gold", "green", "garden", "hedge", "happy", "igloo", "infrared", "jelly", "kangaroo", "lemon", "lion", "marble", "moon", "nine", "opera", "orange", "people", "puppy", "pear", "quince", "race", "run", "sunset", "token", "willow", "zebra" }; private final static String[] alphabet = new String[]{"A","B","C","D","E", "F","G","H","I","J","K","L","M","N","O","P","Q","R", "S","T","U","V","W","X","Y","Z","#"}; private VerticalFieldManager scroller;
public Startup() { UiApplication.getUiApplication().invokeLater(new Runnable() { public void run() { UiApplication.getUiApplication().pushScreen(new ScrollScreen()); } }); } public static void main(String[] args) { ApplicationManager app = ApplicationManager.getApplicationManager(); while (app.inStartup()) { try { Thread.sleep(200); } catch (Throwable e) {} } Startup startup = new Startup(); startup.enterEventDispatcher(); } /** * Screen with content in a scrollbar left and a letters on the right that * can be used to jump into the content. */ class ScrollScreen extends MainScreen { public ScrollScreen() { super(NO_HORIZONTAL_SCROLL | NO_VERTICAL_SCROLL); HorizontalFieldManager hfm = new HorizontalFieldManager(USE_ALL_HEIGHT | NO_VERTICAL_SCROLL | NO_HORIZONTAL_SCROLL){ protected void sublayout(int maxWidth, int maxHeight) { Field scroll = getField(0); Field alpha = getField(1); layoutChild(alpha, maxWidth, maxHeight); layoutChild(scroll, maxWidth-alpha.getWidth(), maxHeight); setPositionChild(scroll, 0, 0); setPositionChild(alpha, maxWidth-alpha.getWidth(), 0); setExtent(maxWidth, maxHeight); } }; hfm.add(createScrollContent()); hfm.add(createAlphabetJumpBar()); add(hfm); } private Field createScrollContent() { Vector vocabulary = new Vector(); for (int ii=0; ii<alphabet.length; ii++) vocabulary.addElement(alphabet[ii]); scroller = new VerticalFieldManager(VERTICAL_SCROLL | USE_ALL_WIDTH) { protected void sublayout(int maxWidth, int maxHeight) { // Record the jump offsets int y = 0; for (int ii=0; ii<getFieldCount(); ii++) { Field field = getField(ii); layoutChild(field, maxWidth, maxHeight); setPositionChild(field, 0, y); if (field instanceof WordField) { WordField object = (WordField)field;; char character = object.getWord().toLowerCase().charAt(0); int offset = ((int)character)-(int)alphabet[0].toLowerCase().charAt(0); if (offset < 0 || offset > jump.length) offset = jump.length-1; while (offset >= 0 && offset < jump.length && jump[offset] == 0) { jump[offset] = y; offset--; } } y += field.getHeight(); } int offset = jump.length-1; do { jump[offset] = y; offset--; } while (offset >= 0 && jump[offset] == 0); setExtent(maxWidth, maxHeight); setVirtualExtent(maxWidth, y+10); } }; jump = new int[alphabet.length]; Font largeFont = Font.getDefault().derive(Font.PLAIN, 46); for (int ii=0; ii<words.length; ii++) { WordField wordField = new WordField(words[ii]); wordField.setFont(largeFont); scroller.add(wordField); } return scroller; } private Field createAlphabetJumpBar() { VerticalFieldManager vfm = new VerticalFieldManager() { protected void sublayout(int maxWidth, int maxHeight) { int y = 0; int width = 0; double allowedAlphaHeight = (double)maxHeight/(double)getFieldCount(); for (int ii=0; ii<getFieldCount(); ii++) { WordField field = (WordField)getField(ii); layoutChild(field, maxWidth, (int)allowedAlphaHeight); setPositionChild(field, 0, y); y += field.getHeight(); double paddedY = Math.floor(allowedAlphaHeight*(ii+1)); if (y < paddedY) y = (int)paddedY; width = Math.max(width, field.getWidth()); } setExtent(width, maxHeight); } }; for (int ii=0; ii<alphabet.length; ii++) { vfm.add(new AlphaField(alphabet[ii]){ protected boolean touchEvent(TouchEvent message) { if (message.getEvent() == TouchEvent.UP) { int startOffset = (int)alphabet[0].charAt(0); int offset = ((int)getWord().charAt(0)) - startOffset; final int y = offset == 0 ? 0 : jump[offset - 1]; UiApplication.getUiApplication().invokeLater(new Runnable(){ public void run() { scroller.setVerticalScroll(y, true); }}); } return true; } }); } return vfm; } class WordField extends LabelField { private final String word; public WordField(String word) { super(word); this.word = word; } public String getWord() { return word; } } Font alphaFont = null; class AlphaField extends WordField { public AlphaField(String word) { super(word); } protected void layout(int width, int height) { if (alphaFont == null) alphaFont = Font.getDefault().derive(Font.PLAIN, height); setExtent(alphaFont.getAdvance(getWord()), alphaFont.getHeight()); } protected void paint(Graphics graphics) { graphics.setFont(alphaFont); graphics.drawText(getWord(), 0, 0); } } /** * For debugging. * @see net.rim.device.api.ui.Screen#keyChar(char, int, int) */ protected boolean keyChar(char c, int status, int time) { if ('o' == c) { // shows the jump offsets into the scroll field UiApplication.getUiApplication().invokeLater(new Runnable(){ public void run() { StringBuffer buf = new StringBuffer(); for (int ii=0; ii<jump.length; ii++) { buf.append(alphabet[ii]+"="+jump[ii]); if (ii<jump.length-1) buf.append(","); } Status.show("offsets="+buf.toString()); }}); } return super.keyChar(c, status, time); } }
}
更新代碼以使用睡眠的線程,獲取事件鎖定並滾動結束,結果相同。如果找不到問題的根源,我會嘗試使用焦點觸發滾動。謝謝你的提示! – Martin 2011-02-09 20:12:14