Blackberry - Экран загрузки / ожидания с анимацией

Есть ли способ показать экран «Загрузка» с анимацией в Blackberry?

Опции:

  • PME анимационный контент
  • многопоточность + набор изображений + таймер / счетчик
  • стандартный обод api
  • каким-то другим способом

Что-нибудь из этого?

Спасибо!


person Maksym Gontar    schedule 29.04.2009    source источник
comment
Вы можете просмотреть пример, используя всплывающий экран здесь. supportforums.blackberry.com/t5/Java-Development/ Я решил свою проблему с помощью этого.   -  person BSKANIA    schedule 27.04.2012


Ответы (7)


Фермин, Энтони +1. Спасибо всем, вы дали мне часть ответа.
Мое окончательное решение:

1. Создайте или сгенерируйте (бесплатный Ajax-генератор загрузочных файлов GIF) анимацию и добавьте ее в проект.

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. Создайте 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 в собственном приложении BlackBerry

person Maksym Gontar    schedule 04.05.2009
comment
Спасибо, что поделились этим. Я также мог показать текст рядом с изображением, добавив graphics.drawText (text, xText, yImage); в методе paint (). Для вычисления координат изображения и текста использовались this.getFont (). GetAdvance (text) и this.getFont (). GetHeight () ;. - person bob; 31.08.2011
comment
можно добавить изображения любых рамок? Я добавляю изображение с 12 кадрами, но оно не закрашено должным образом. он появляется и исчезает .. не уверен, в чем проблема .. - person varunrao321; 23.05.2012
comment
@Newbie распечатайте или посмотрите значение _totalLoops в отладке - это количество циклов для воспроизведения. Проверьте, имеет ли ваша анимация значение числа бесконечных циклов, может быть, оно равно 1, поэтому воспроизводится только один раз. - person Maksym Gontar; 23.05.2012
comment
Если вы столкнулись с NPE (NullPointerEx) при загрузке изображения GIF, прочтите это: supportforums.blackberry.com/t5/Java-Development/ - person Mark Joseph Del Rosario; 03.10.2012

Базовый шаблон для такого рода вещей:

Создайте поток, выполняющий цикл, который обновляет переменную (например, индекс кадра анимированного изображения), а затем вызывает недействительность в поле, которое рисует изображение (а затем засыпает на некоторое время). Недействительный объект поставит в очередь перерисовку поля.

В методе рисования поля прочтите переменную и нарисуйте соответствующий кадр изображения.

Псевдокод (не полностью, но чтобы дать вам представление):

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 (как в ответе Фермина) или создайте свой собственный диалог, напрямую переопределив экран. Отдельный поток необходим, потому что RIM API не является потокобезопасным: вам нужно делать все, что связано с пользовательским интерфейсом в потоке событий (или, удерживая блокировку событий, см. BlackBerry UI Threading - самые основы

person Anthony Rizk    schedule 29.04.2009

Это простой код для экрана загрузки ....

                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();
person Dhiral Pandya    schedule 27.09.2011

Если бы это просто анимация, вы могли бы показать анимированный gif во всплывающем окне и закрыть его после завершения операции загрузки?

person Fermin    schedule 29.04.2009

Самый простой способ - это использовать стандартный 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); для обновления индикатора выполнения.

Обычно у меня это вызывается из того потока, который выполняет работу (загрузка в вашем случае, каждый раз, когда операция завершается, индикатор выполнения обновляется.

person Fermin    schedule 29.04.2009
comment
Спасибо за ответ, но мне нужен не индикатор выполнения, а диалоговое окно ожидания анимации. Не могли бы вы предложить какую-нибудь технику непрерывного самообновления? - person Maksym Gontar; 29.04.2009

Предлагаю взглянуть на эту простую реализацию. Мне это понравилось, но никогда не использовал. Может быть вам полезно.

текст ссылки

person Sameer    schedule 30.09.2009
comment
да, это здорово! но посмотрите мой ответ, он уже есть, в конце концов))) - person Maksym Gontar; 30.09.2009

ActivityIndicator - хороший вариант, если вы работаете как минимум с BB OS 6.0.

http://www.brighthub.com/mobile/blackberry-platform/articles/94258.aspx

http://docs.blackberry.com/en/developers/deliverables/17966/Screen_APIs_1245069_11.jsp

person milkersarac    schedule 17.08.2011