Class ImageViewer

java.lang.Object
com.codename1.ui.Component
com.codename1.components.ImageViewer
All Implemented Interfaces:
Animation, Editable, StyleListener

public class ImageViewer extends Component

ImageViewer allows zooming/panning an image and potentially flicking between multiple images within a list of images.

E.g. the trivial usage works like this:

Form hi = new Form("ImageViewer", new BorderLayout());
ImageViewer iv = new ImageViewer(duke);
hi.add(BorderLayout.CENTER, iv);

You can simulate pinch to zoom on the simulator by dragging the right button away from the top left corner to zoom in and towards the top left corner to zoom out. On Mac touchpads you can drag two fingers to achieve that.

A more elaborate usage includes flicking between multiple images e.g.:

Form hi = new Form("ImageViewer", new BorderLayout());

Image red = Image.createImage(100, 100, 0xffff0000);
Image green = Image.createImage(100, 100, 0xff00ff00);
Image blue = Image.createImage(100, 100, 0xff0000ff);
Image gray = Image.createImage(100, 100, 0xffcccccc);

ImageViewer iv = new ImageViewer(red);
iv.setImageList(new DefaultListModel<>(red, green, blue, gray));
hi.add(BorderLayout.CENTER, iv);

You can even download image URL's dynamically into the ImageViewer thanks to the usage of the com.codename1.ui.list.ListModel. E.g. in this model book cover images are downloaded dynamically:

Form hi = new Form("ImageViewer", new BorderLayout());
final EncodedImage placeholder = EncodedImage.createFromImage(
        FontImage.createMaterial(FontImage.MATERIAL_SYNC, s).
                scaled(300, 300), false);

class ImageList implements ListModel {
    private int selection;
    private String[] imageURLs = {
        "http://awoiaf.westeros.org/images/thumb/9/93/AGameOfThrones.jpg/300px-AGameOfThrones.jpg",
        "http://awoiaf.westeros.org/images/thumb/3/39/AClashOfKings.jpg/300px-AClashOfKings.jpg",
        "http://awoiaf.westeros.org/images/thumb/2/24/AStormOfSwords.jpg/300px-AStormOfSwords.jpg",
        "http://awoiaf.westeros.org/images/thumb/a/a3/AFeastForCrows.jpg/300px-AFeastForCrows.jpg",
        "http://awoiaf.westeros.org/images/7/79/ADanceWithDragons.jpg"
    };
    private Image[] images;
    private EventDispatcher listeners = new EventDispatcher();

    public ImageList() {
        this.images = new EncodedImage[imageURLs.length];
    }

    public Image getItemAt(final int index) {
        if(images[index] == null) {
            images[index] = placeholder;
            Util.downloadUrlToStorageInBackground(imageURLs[index], "list" + index, (e) -> {
                    try {
                        images[index] = EncodedImage.create(Storage.getInstance().createInputStream("list" + index));
                        listeners.fireDataChangeEvent(index, DataChangedListener.CHANGED);
                    } catch(IOException err) {
                        err.printStackTrace();
                    }
            });
        }
        return images[index];
    }

    public int getSize() {
        return imageURLs.length;
    }

    public int getSelectedIndex() {
        return selection;
    }

    public void setSelectedIndex(int index) {
        selection = index;
    }

    public void addDataChangedListener(DataChangedListener l) {
        listeners.addListener(l);
    }

    public void removeDataChangedListener(DataChangedListener l) {
        listeners.removeListener(l);
    }

    public void addSelectionListener(SelectionListener l) {
    }

    public void removeSelectionListener(SelectionListener l) {
    }

    public void addItem(Image item) {
    }

    public void removeItem(int index) {
    }
};

ImageList imodel = new ImageList();

ImageViewer iv = new ImageViewer(imodel.getItemAt(0));
iv.setImageList(imodel);
hi.add(BorderLayout.CENTER, iv);
  • Field Details

    • IMAGE_FIT

      public static final int IMAGE_FIT
      Indicates the initial position of the image in the viewer to FIT to the component size
      See Also:
    • IMAGE_FILL

      public static final int IMAGE_FILL
      Indicates the initial position of the image in the viewer to FILL the component size. Notice this type might drop edges of the images in order to stretch the image to the full size of the Component.
      See Also:
  • Constructor Details

    • ImageViewer

      public ImageViewer()
      Default constructor
    • ImageViewer

      public ImageViewer(Image i)

      Initializes the component with an image

      Parameters
      • i: image to show
  • Method Details

    • resetFocusable

      protected void resetFocusable()
      Restores the state of the focusable flag to its default state
      Overrides:
      resetFocusable in class Component
    • getPropertyNames

      public String[] getPropertyNames()

      A component may expose mutable property names for a UI designer to manipulate, this API is designed for usage internally by the GUI builder code

      Returns

      the property names allowing mutation

      Overrides:
      getPropertyNames in class Component
    • shouldBlockSideSwipe

      protected boolean shouldBlockSideSwipe()
      A component that might need side swipe such as the slider could block it from being used for some other purpose when on top of said component.
      Overrides:
      shouldBlockSideSwipe in class Component
    • getPropertyTypes

      public Class[] getPropertyTypes()

      Matches the property names method (see that method for further details).

      Returns

      the types of the properties

      Overrides:
      getPropertyTypes in class Component
    • getPropertyTypeNames

      public String[] getPropertyTypeNames()

      This method is here to workaround an XMLVM array type bug where property types aren't identified properly, it returns the names of the types using the following type names: String,int,double,long,byte,short,char,String[],String[][],byte[],Image,Image[],Object[],ListModel,ListCellRenderer

      Returns

      Array of type names

      Overrides:
      getPropertyTypeNames in class Component
    • getPropertyValue

      public Object getPropertyValue(String name)

      Returns the current value of the property name, this method is used by the GUI builder

      Parameters
      • name: the name of the property
      Returns

      the value of said property

      Overrides:
      getPropertyValue in class Component
    • setPropertyValue

      public String setPropertyValue(String name, Object value)

      Sets a new value to the given property, returns an error message if failed and null if successful. Notice that some builtin properties such as "$designMode" might be sent to components to indicate application state.

      Parameters
      • name: the name of the property

      • value: new value for the property

      Returns

      error message or null

      Overrides:
      setPropertyValue in class Component
    • initComponent

      public void initComponent()
      Allows subclasses to bind functionality that relies on fully initialized and "ready for action" component state
      Overrides:
      initComponent in class Component
    • getImageX

      public int getImageX()

      Returns the x position of the image viewport which can be useful when it is being panned by the user

      Returns

      x position within the image for the top left corner

    • getImageY

      public int getImageY()

      Returns the y position of the image viewport which can be useful when it is being panned by the user

      Returns

      y position within the image for the top left corner

    • deinitialize

      public void deinitialize()
      Invoked to indicate that the component initialization is being reversed since the component was detached from the container hierarchy. This allows the component to deregister animators and cleanup after itself. This method is the opposite of the initComponent() method.
      Overrides:
      deinitialize in class Component
    • keyReleased

      public void keyReleased(int key)

      If this Component is focused, the key released event will call this method

      Parameters
      • keyCode: the key code value to indicate a physical key.
      Overrides:
      keyReleased in class Component
    • pointerPressed

      public void pointerPressed(int x, int y)

      If this Component is focused, the pointer pressed event will call this method

      Parameters
      • x: the pointer x coordinate

      • y: the pointer y coordinate

      Overrides:
      pointerPressed in class Component
    • dragFinished

      protected void dragFinished(int x, int y)
      Description copied from class: Component

      Callback indicating that the drag has finished either via drop or by releasing the component

      Parameters
      • x: the x location

      • y: the y location

      Overrides:
      dragFinished in class Component
    • pointerReleased

      public void pointerReleased(int x, int y)

      If this Component is focused, the pointer released event will call this method

      Parameters
      • x: the pointer x coordinate

      • y: the pointer y coordinate

      Overrides:
      pointerReleased in class Component
    • pinchReleased

      protected void pinchReleased(int x, int y)
      Description copied from class: Component

      To be implemented by subclasses interested in being notified when a pinch zoom has ended (i.e the user has removed one of their fingers, but is still dragging).

      Parameters
      • x: The x-coordinate of the remaining finger in the drag. (Absolute)

      • y: The y-coordinate of the remaining finger in the drag. (Absolute)

      Since

      7.0

      Overrides:
      pinchReleased in class Component
    • pointerDragged

      public void pointerDragged(int x, int y)

      If this Component is focused, the pointer dragged event will call this method

      Parameters
      • x: the pointer x coordinate

      • y: the pointer y coordinate

      Overrides:
      pointerDragged in class Component
    • laidOut

      protected void laidOut()
      This is a callback method to inform the Component when it's been laidout on the parent Container
      Overrides:
      laidOut in class Component
    • pinch

      protected boolean pinch(float scale)

      Invoked by subclasses interested in handling pinch to zoom events, if true is returned other drag events will not be broadcast

      Parameters
      • scale: @param scale the scaling of the pinch operation a number larger than 1 means scaling up and smaller than 1 means scaling down. It is recommended that code would threshold the number (so a change between 1.0 and 1.02 shouldn't necessarily trigger zoom). Notice that this number is relevant to current zoom levels and unaware of them so you should also enforce limits of maximum/minimum zoom levels.
      Returns

      false by default

      Overrides:
      pinch in class Component
    • getCroppedImage

      public Image getCroppedImage(int backgroundColor)

      Gets the current image cropped using the current pan and zoom state. The cropped image dimensions will be the result of cropping the full-sized image with the current pan/zoom state. The aspect ratio will match the aspect ratio of the ImageViewer - not the source image itself.

      Parameters
      • backgroundColor: The background color, visible for letterboxing.
      Returns

      The cropped image.

      Since

      7.0

    • getCroppedImage

      public Image getCroppedImage(int width, int height, int backgroundColor)

      Gets the current image cropped using the current pan and zoom state.

      Parameters
      • width: The width of the cropped image. Use -1 to match aspect ratio of the ImageViewer component. Either height or width must be positive.

      • height: The height of the cropped image. Use -1 to match aspect ratio of the ImageViewer component. Either height or width must be positive.

      • backgroundColor: Background color to use for letterboxing.

      Returns

      Cropped image in specified dimensions.

      Since

      7.0

    • calcPreferredSize

      protected Dimension calcPreferredSize()

      Calculates the preferred size based on component content. This method is invoked lazily by getPreferred size.

      Returns

      the calculated preferred size based on component content

      Overrides:
      calcPreferredSize in class Component
    • animate

      public boolean animate()

      Allows the animation to reduce "repaint" calls when it returns false. It is called once for every frame. Frames are defined by the com.codename1.ui.Display class.

      Returns

      true if a repaint is desired or false if no repaint is necessary

      Specified by:
      animate in interface Animation
      Overrides:
      animate in class Component
    • isAllowScaleDown

      public boolean isAllowScaleDown()

      Allows the image to scale down when image initial position is set to fit this is off by default since the UX isn't great

      Returns

      the allowScaleDown

    • setAllowScaleDown

      public void setAllowScaleDown(boolean allowScaleDown)

      Allows the image to scale down when image initial position is set to fit this is off by default since the UX isn't great

      Parameters
      • allowScaleDown: the allowScaleDown to set
    • paint

      public void paint(Graphics g)

      This method paints the Component on the screen, it should be overriden by subclasses to perform custom drawing or invoke the UI API's to let the PLAF perform the rendering.

      Parameters
      • g: the component graphics
      Specified by:
      paint in interface Animation
      Overrides:
      paint in class Component
    • paintBackground

      protected void paintBackground(Graphics g)

      This method paints the Component background, it should be overriden by subclasses to perform custom background drawing.

      Parameters
      • g: the component graphics
      Overrides:
      paintBackground in class Component
    • getImage

      public Image getImage()

      Returns the currently showing image

      Returns

      the image

    • setImage

      public final void setImage(Image image)

      Sets the currently showing image

      Parameters
      • image: the image to set
    • setImageNoReposition

      public void setImageNoReposition(Image image)

      Sets the current image without any changes to the panning/scaling

      Parameters
      • image: new image instance
    • getImageList

      public ListModel<Image> getImageList()

      Returns the list model containing the images in the we can swipe through

      Returns

      the list model

    • setImageList

      public void setImageList(ListModel<Image> model)

      By providing this optional list of images you can allows swiping between multiple images

      Parameters
      • model: a list of images
    • setAnimateZoom

      public void setAnimateZoom(boolean animateZoom)

      Indicates if the zoom should bee animated. It's true by default

      Parameters
      • animateZoom: true if zoom is animated
    • isAnimatedZoom

      public boolean isAnimatedZoom()

      Indicates if the zoom should bee animated. It's true by default

      Returns

      true if zoom is animated

    • getZoom

      public float getZoom()

      Manipulate the zoom level of the application

      Returns

      the zoom

    • setZoom

      public void setZoom(float zoom)

      Manipulate the zoom level of the application

      Parameters
      • zoom: the zoom to set
    • setZoom

      public void setZoom(float zoom, float panPositionX, float panPositionY)

      Manipulate the zoom level of the application

      Parameters
      • zoom: the zoom to set

      • panPositionX: A float value between 0 and 1 to set the image x position

      • panPositionY: A float value between 0 and 1 to set the image y position

    • getSwipePlaceholder

      public Image getSwipePlaceholder()

      This image is shown briefly during swiping while the full size image is loaded

      Returns

      the swipePlaceholder

    • setSwipePlaceholder

      public void setSwipePlaceholder(Image swipePlaceholder)

      This image is shown briefly during swiping while the full size image is loaded

      Parameters
      • swipePlaceholder: the swipePlaceholder to set
    • isEagerLock

      public boolean isEagerLock()

      Eager locking effectively locks the right/left images as well as the main image, as a result more heap is taken

      Returns

      the eagerLock

    • setEagerLock

      public void setEagerLock(boolean eagerLock)

      Eager locking effectively locks the right/left images as well as the main image, as a result more heap is taken

      Parameters
      • eagerLock: the eagerLock to set
    • isCycleLeft

      public boolean isCycleLeft()

      By default the ImageViewer cycles from the beginning to the end of the list when going to the left, setting this to false prevents this behaviour

      Returns

      true if it should cycle left from beginning

    • setCycleLeft

      public void setCycleLeft(boolean cycleLeft)

      By default the ImageViewer cycles from the beginning to the end of the list when going to the left, setting this to false prevents this behaviour

      Parameters
      • cycleLeft: the cycle left to set
    • isCycleRight

      public boolean isCycleRight()

      By default the ImageViewer cycles from the end to the beginning of the list when going to the right, setting this to false prevents this behaviour

      Returns

      true if it should cycle right from the end

    • setCycleRight

      public void setCycleRight(boolean cycleRight)

      By default the ImageViewer cycles from the end to the beginning of the list when going to the right, setting this to false prevents this behaviour

      Parameters
      • cycleRight: the cycle right to set
    • getSwipeThreshold

      public float getSwipeThreshold()

      The swipe threshold is a number between 0 and 1 that indicates the threshold after which the swiped image moves to the next image. Below that number the image will bounce back

      Returns

      the threshold

    • setSwipeThreshold

      public void setSwipeThreshold(float swipeThreshold)

      The swipe threshold is a number between 0 and 1 that indicates the threshold after which the swiped image moves to the next image. Below that number the image will bounce back

      Parameters
      • swipeThreshold: the swipeThreshold to set
    • setImageInitialPosition

      public void setImageInitialPosition(int imageInitialPosition)

      Sets the viewer initial image position to fill or to fit.

      Parameters
      • imageInitialPosition: values can be IMAGE_FILL or IMAGE_FIT