2009-04-29 51 views
13

有沒有辦法顯示「加載」屏幕與動畫在黑莓?黑莓 - 加載/等待屏幕與動畫

選項:

  • PME動畫內容
  • 多線程+圖像集+定時器/計數器
  • 標準輪輞API
  • 一些其它方式

任何的這?

謝謝!

+1

你可以在這裏使用彈出屏幕視圖的例子。 http://supportforums.blackberry.com/t5/Java-Development/Sample-quot-Please-Wait-quot-screen-part-1/ta-p/493808我用這個解決了我的問題。 – BSKANIA 2012-04-27 10:47:33

回答

35

費爾明安東尼+1。你給我的答案的一部分
我的最終解決方案:

1,創建或生成(free Ajax loading gif generator)的動畫,並將其添加到項目

2。創建ResponseCallback接口(見Coderholic - Blackberry WebBitmapField)接收線程執行結果:

public interface ResponseCallback { 
    public void callback(String data); 
} 

3.創建一個類來處理你的後臺線程的工作。在我的情況下,它是HTTP請求:

public class HttpConnector 
{ 
    static public void HttpGetStream(final String fileToGet, 
    final ResponseCallback msgs) { 
    Thread t = new Thread(new Runnable() { 
     public void run() { 
     HttpConnection hc = null; 
    DataInputStream din = null; 
    try { 
     hc = (HttpConnection) Connector.open("http://" + fileToGet); 
     hc.setRequestMethod(HttpsConnection.GET); 
     din = hc.openDataInputStream(); 
     ByteVector bv = new ByteVector(); 
     int i = din.read(); 
     while (-1 != i) { 
     bv.addElement((byte) i); 
     i = din.read(); 
     } 
     final String response = new String(bv.toArray(), "UTF-8"); 
     UiApplication.getUiApplication().invokeLater(
     new Runnable() { 
      public void run() { 
     msgs.callback(response); 
       } 
      }); 
    } 
     catch (final Exception e) { 
      UiApplication.getUiApplication().invokeLater(
      new Runnable() { 
       public void run() { 
       msgs.callback("Exception (" + e.getClass() + "): " 
        + e.getMessage()); 
       } 
      }); 
     } 
     finally { 
      try { 
      din.close(); 
      din = null; 
      hc.close(); 
      hc = null; 
      } 
      catch (Exception e) { 
      } 
     } 
     } 
    }); 
    t.start(); 
    } 
} 

4.Create等待屏幕(全屏的混合動力和AnimatedGIFField與ResponseCallback接口):

public class WaitScreen extends FullScreen implements ResponseCallback 
{ 
    StartScreen startScreen; 
    private GIFEncodedImage _image; 
    private int _currentFrame; 
    private int _width, _height, _xPos, _yPos; 
    private AnimatorThread _animatorThread; 
    public WaitScreen(StartScreen startScreen) { 
     super(new VerticalFieldManager(), Field.NON_FOCUSABLE); 
     setBackground(
      BackgroundFactory.createSolidTransparentBackground(
       Color.WHITE, 100)); 
     this.startScreen = startScreen; 
     EncodedImage encImg = 
      GIFEncodedImage.getEncodedImageResource("ajax-loader.gif"); 
     GIFEncodedImage img = (GIFEncodedImage) encImg; 

     // Store the image and it's dimensions. 
     _image = img; 
     _width = img.getWidth(); 
     _height = img.getHeight(); 
     _xPos = (Display.getWidth() - _width) >> 1; 
     _yPos = (Display.getHeight() - _height) >> 1; 
     // Start the animation thread. 
     _animatorThread = new AnimatorThread(this); 
     _animatorThread.start(); 
     UiApplication.getUiApplication().pushScreen(this); 
    } 

    protected void paint(Graphics graphics) { 
     super.paint(graphics); 
      // Draw the animation frame. 
      graphics 
       .drawImage(_xPos, _yPos, _image 
       .getFrameWidth(_currentFrame), _image 
        .getFrameHeight(_currentFrame), _image, 
       _currentFrame, 0, 0); 
    } 

    protected void onUndisplay() { 
     _animatorThread.stop(); 
    } 

    private class AnimatorThread extends Thread { 
     private WaitScreen _theField; 
     private boolean _keepGoing = true; 
     private int _totalFrames, _loopCount, _totalLoops; 
     public AnimatorThread(WaitScreen _theScreen) { 
      _theField = _theScreen; 
      _totalFrames = _image.getFrameCount(); 
      _totalLoops = _image.getIterations(); 

     } 

     public synchronized void stop() { 
      _keepGoing = false; 
     } 

     public void run() { 
      while (_keepGoing) { 
       // Invalidate the field so that it is redrawn. 
       UiApplication.getUiApplication().invokeAndWait(
        new Runnable() { 
        public void run() { 
         _theField.invalidate(); 
        } 
       }); 
       try { 
        // Sleep for the current frame delay before 
        // the next frame is drawn. 
        sleep(_image.getFrameDelay(_currentFrame) * 10); 
       } catch (InterruptedException iex) { 
       } // Couldn't sleep. 
       // Increment the frame. 
       ++_currentFrame; 
       if (_currentFrame == _totalFrames) { 
        // Reset back to frame 0 
        // if we have reached the end. 
        _currentFrame = 0; 
        ++_loopCount; 
        // Check if the animation should continue. 
        if (_loopCount == _totalLoops) { 
        _keepGoing = false; 
        } 
       } 
      } 
     } 

    } 

    public void callback(String data) { 
     startScreen.updateScreen(data); 
     UiApplication.getUiApplication().popScreen(this); 
    } 
} 

5.In年底,創建啓動屏幕調用HttpConnector .HttpGetStream並顯示等待屏幕:

public class StartScreen extends MainScreen 
{ 
    public RichTextField text; 
    WaitScreen msgs; 
    public StartScreen() {  
     text = new RichTextField(); 
     this.add(text); 
    } 

    protected void makeMenu(Menu menu, int instance) { 
     menu.add(runWait); 
     super.makeMenu(menu, instance); 
    } 

    MenuItem runWait = new MenuItem("wait", 1, 1) { 
     public void run() { 
      UiApplication.getUiApplication().invokeLater(
       new Runnable() { 
        public void run() { 
         getFile(); 
        } 
      });    
     } 
    }; 

    public void getFile() { 
     msgs = new WaitScreen(this); 
     HttpConnector.HttpGetStream(
      "stackoverflow.com/faq", msgs);     
    } 

    //you should implement this method to use callback data on the screen. 
    public void updateScreen(String data) 
    { 
     text.setText(data); 
    } 
} 

UPDATE:另一種解決方案naviina.eu: A Web2.0/Ajax-style loading popup in a native BlackBerry application

+0

我希望我可以兩次這樣做,好吧,很多次。辦法。 – Irwin 2011-01-08 15:24:12

+0

感謝分享。我還可以通過添加「graphics.drawText(text,xText,yImage);」在paint()方法中。要計算圖像和文本的座標,請使用「this.getFont()。getAdvance(text)」和「this.getFont()。getHeight();」。 – bob 2011-08-30 22:44:47

2

最簡單的方法可能是使用標準GaugeField,設置樣式GaugeField.PERCENT。這會給你一個進度條。將其添加到PopupScreen中,它將位於您的內容之上。就像..

private GaugeField _gaugeField; 
private PopupScreen _popup; 

public ProgressBar() {  
    DialogFieldManager manager = new DialogFieldManager(); 
    _popup = new PopupScreen(manager); 
    _gaugeField = new GaugeField(null, 0, 100, 0, GaugeField.PERCENT);  
    manager.addCustomField(_gaugeField); 
} 

然後有一個更新方法,它將使用_gaugeField.setValue(newValue);更新進度條。

我通常有這樣從哪個線程正在做你的情況的處理(搬入叫,每次操作完成進度條進行更新。

+0

感謝您的回答,但我不需要進度條,而是一個動畫「等待」對話框。你能提出一些持續的自更新技術嗎? – 2009-04-29 08:16:49

3

如果它只是一個動畫你能上的彈出顯示的animated gif ?並關閉它加載操作完成時

+0

感謝Fermin,+1。 – 2009-04-29 11:25:21

4

的基本模式爲這種事情是:

有一個線程中運行一個循環,更新的變量(如動畫圖像的幀索引),然後在繪製圖像的Field上調用invalidate(然後睡覺一段時間)。無效將排隊重新繪製該字段。

在字段的paint方法中,讀取變量並繪製圖像的相應框。

僞代碼(沒有完全完成,但給你的想法):

public class AnimatedImageField extends Field implements Runnable { 

    private int currentFrame; 
    private Bitmap[] animationFrames; 

    public void run() { 
    while(true) { 
     currentFrame = (currentFrame + 1) % animationFrames.length; 
     invalidate(); 
     Thread.sleep(100); 
     } 
    } 

    protected void paint(Graphics g) { 
     g.drawBitmap(0, 0, imageWidth, imageHeight, animationFrames[currentFrame], 0, 0); 
    } 
    } 

還要注意這裏我使用的位圖的數組,但EncodedImage讓你能夠將GIF動畫作爲一個對象,包括獲取特定幀的方法。

編輯:爲了完整:將此添加到PopupScreen(如在Fermin的答案中)或直接通過覆蓋Screen創建自己的對話框。單獨的線程是必需的,因爲RIM API不是線程安全的:您需要在事件線程上執行與UI相關的所有操作(或者同時持有事件鎖,請參閱BlackBerry UI Threading - The Very Basics

2

我建議看看這個簡單的實現。我喜歡這個,但從來沒有用過它。可能對你有幫助。

link text

4

這是加載畫面簡單的代碼....

   HorizontalFieldManager popHF = new HorizontalFieldManager(); 
       popHF.add(new CustomLabelField("Pls wait...")); 
       final PopupScreen waitScreen = new PopupScreen(popHF); 
       new Thread() 
       { 
        public void run() 
        { 

         synchronized (UiApplication.getEventLock()) 
         { 
          UiApplication.getUiApplication().pushScreen(waitScreen); 
         } 
         //Here Some Network Call 

         synchronized (UiApplication.getEventLock()) 
         { 
          UiApplication.getUiApplication().popScreen(waitScreen); 
         } 
        } 
       }.start();