【问题标题】:Blackberry - Loading/Wait screen with animationBlackberry - 带动画的加载/等待屏幕
【发布时间】:2010-10-22 12:25:29
【问题描述】:

有没有办法在黑莓中显示“加载”屏幕动画

选项:

  • PME 动画内容
  • 多线程+图像集+定时器/计数器
  • 标准 rim api
  • 其他方式

有这些吗?

谢谢!

【问题讨论】:

标签: user-interface blackberry java-me loading wait


【解决方案1】:

费尔明,安东尼+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 WaitScreen(FullScreen 和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.最后创建开始界面调用HttpConnector.HttpGetStream并显示WaitScreen:

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);
    }
}

更新:另一个解决方案naviina.eu: A Web2.0/Ajax-style loading popup in a native BlackBerry application

【讨论】:

  • 感谢分享。我还可以通过添加“graphics.drawText(text, xText, yImage);”在图像旁边显示文本在paint() 方法中。要计算图像和文本的坐标,请使用“this.getFont().getAdvance(text)”和“this.getFont().getHeight();”。
  • 我可以添加任何帧的图像吗?我正在添加一个 12 帧的图像,但它没有正确绘制。它出现又消失..不确定问题出在哪里..
  • @Newbie 打印出来或在调试中查看 _totalLoops 值 - 这是要播放的循环数。检查你的动画是否有无限循环caount值,也许它是1所以只播放了一次。
  • 如果你在加载GIF图片时碰巧遇到了NPE(NullPointerEx),请阅读:supportforums.blackberry.com/t5/Java-Development/…
【解决方案2】:

这种事情的基本模式是:

让一个线程运行一个循环来更新一个变量(例如动画图像的帧索引),然后在绘制图像的字段上调用 ​​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

【讨论】:

    【解决方案3】:

    这是加载屏幕的简单代码......

                    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();
    

    【讨论】:

      【解决方案4】:

      如果它只是一个动画,您能否在弹出窗口中显示animated gif 并在加载操作完成时将其关闭?

      【讨论】:

        【解决方案5】:

        最简单的方法可能是使用标准 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);更新进度条。

        我通常会从正在执行工作的任何线程调用它(在您的情况下加载,每次操作完成时,进度条都会更新。

        【讨论】:

        • 感谢您的回答,但我不需要进度条,而是动画“等待”对话框。你能推荐一些持续自我更新的技术吗?
        【解决方案6】:

        我建议看看这个简单的实现。我喜欢这个,但从未使用过。可能对你有帮助。

        link text

        【讨论】:

        • 是的,它很棒!但看看我的回答,它已经在那里了,最后)))
        【解决方案7】:

        【讨论】:

          猜你喜欢
          • 2022-01-25
          • 2013-01-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-08
          • 2023-04-03
          相关资源
          最近更新 更多