3

I want to show thumbnail images in a Grid.

This is my relevant code (simplified):

addColumnVisibilityChangeListener(event -> {
    if (ID_THUMBNAIL.equals(event.getColumn().getId())) {
        if (event.isHidden()) {
            setBodyRowHeight(-1);
        } else {
            setBodyRowHeight(130);
        }
        // needed to force rendering of current values
        getDataProvider().refreshAll();
    }
});
// rescale returns a (cached) ExternalResource, image is 120x120px max
// aspect ratio is preserved, so at least width or height is 120px
grid.addColumn(this::rescale, new ImageRenderer<>(this::showImage))
    .setCaption(ID_THUMBNAIL)
    .setStyleGenerator(r -> ID_THUMBNAIL)
    .setWidth(131);

The CSS is:

.asset-grid td.thumbnail {
  // height is set bij Vaadin Grid
  padding: 5px;
  text-align: center !important;    
}
.asset-grid td.thumbnail img {
  vertical-align: middle !important;
}

Everything works except the vertical alignment of the thumbnail image. It is displayed at the top of the cell. I tried several settings, but nothing works.

Morfic
  • 15,178
  • 3
  • 51
  • 61
rmuller
  • 12,062
  • 4
  • 64
  • 92
  • Did you try add : " display: table-cell; " to .asset-grid td.thumbnail ? – 1011sophie Oct 11 '17 at 08:04
  • Just tried it, no difference – rmuller Oct 11 '17 at 08:19
  • I have a couple of working workarounds, but it depeends on how you are setting the row height. So it would help if you could provide a [sscce](http://sscce.org) so we can take all elements into consideration. – Morfic Oct 18 '17 at 17:04
  • @Morfic Updated my question (setting the row height). This code is simplified, but it contains all information, no other CSS is used (rest is default Valo). – rmuller Oct 18 '17 at 17:57
  • It should be sufficient, but please let me know the exact vaadin version you're using because [`setBodyRowHeight` no longer exists in v8.1.4+](https://stackoverflow.com/questions/46259633/vaadin-grid-setbodyrowheight-doesnt-exist-in-latest-8-1-4-api) (it's supposed to be fixed in 8.2.0) – Morfic Oct 19 '17 at 08:52
  • @Morfic 8.2.0.alpha2 – rmuller Oct 19 '17 at 09:10

1 Answers1

2

This is based mainly on this answer on how to vertical-align image in div with some minor variations by trial and error.

It's possible to use the original answer with a fixed line-size (eg 130) and vertical-align: middle, but the updated version offers flexibility no matter what height you set (tested in chrome and edge).

Code:

import com.vaadin.event.ShortcutAction;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.Resource;
import com.vaadin.ui.*;
import com.vaadin.ui.renderers.ClickableRenderer;
import com.vaadin.ui.renderers.ImageRenderer;

public class GridWithImages extends VerticalLayout {

    public GridWithImages() {
        // basic grid setup
        Grid<User> grid = new Grid<>();
        grid.addColumn(User::getId)
            .setCaption("Id");
        Grid.Column<User, Resource> thumbnailColumn = grid.addColumn(User::getThumbnail)
                                                          .setCaption("Thumbnail")
                                                          .setRenderer(new ImageRenderer<>(this::showImage))
                                                          .setStyleGenerator(r -> "thumbnail")
                                                          .setWidth(131);
        grid.setItems(new User(1), new User(2), new User(3));
        grid.setBodyRowHeight(130);

        // allow to easily update height and width for testing purposes
        TextField rowHeightField = new TextField("Row height", "130");
        TextField thumbnailColumnWidthField = new TextField("Thumbnail width", "131");
        Button button = new Button("Update", event -> {
            // NOT SAFE, NOT ELEGANT, but for the sake of brevity just use those values...
            grid.setBodyRowHeight(Integer.valueOf(rowHeightField.getValue()));
            thumbnailColumn.setWidth(Integer.valueOf(thumbnailColumnWidthField.getValue()));
        });
        button.setClickShortcut(ShortcutAction.KeyCode.ENTER);

        addComponents(grid, rowHeightField, thumbnailColumnWidthField, button);
    }

    // image renderer click handler
    private void showImage(ClickableRenderer.RendererClickEvent<User> event) {
        Notification.show("This will be the actual image in full size... maybe, maybe not!");
    }

    // basic bean for easy binding
    private class User {
        private int id;
        private Resource thumbnail = new ExternalResource("https://www.gravatar.com/avatar/d9269818df2a058ad6bf9dbbaf1e8240?s=32&d=identicon&r=PG");

        public User(int id) {
            this.id = id;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public Resource getThumbnail() {
            return thumbnail;
        }

        public void setThumbnail(Resource thumbnail) {
            this.thumbnail = thumbnail;
        }
    }
}

Theme:

td.v-grid-cell.thumbnail > img {
  vertical-align: unset; // leaving it centered as inherited, shifts the image a few pixels downwards
  position: relative;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%); // https://stackoverflow.com/questions/34551381/is-the-css3-transform-translate-percentage-values-relative-to-its-width-and-or-h
}

Result:

vaadin center image in grid

Morfic
  • 15,178
  • 3
  • 51
  • 61
  • Hats off! So it was just a matter of CSS. Thanks for all the time you invest in answering these questions. Really appreciated! – rmuller Oct 19 '17 at 11:50
  • @rmuller You're welcome, that's what SO is all about. Also yes, pretty much CSS related. – Morfic Oct 19 '17 at 13:13