4

現在、GWT DataGridヘッダーは、垂直スクロール中に固定ヘッダー行を使用してこのトリックを実行します。(最初の)列全体で同じことを達成する方法はありますか?

4

2 に答える 2

3

DataGridの最初の列をフリーズするScrolledGridを実装しました。最初の列をフリーズさせるには、DataGridの代わりにそれを使用する必要があります。

import com.google.gwt.dom.client.*;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.client.ui.HeaderPanel;
import com.google.gwt.user.client.ui.ScrollPanel;

/**
 *
 * @author Yuri Plaksyuk
 */
public class ScrolledGrid extends DataGrid {

    private final Text cssText;
    private boolean addedClass = false;
    private int currentScrollLeft = 0;

    public ScrolledGrid() {
        cssText = Document.get().createTextNode("");

        StyleElement styleElement = Document.get().createStyleElement();
        styleElement.setType("text/css");
        styleElement.appendChild(cssText);

        HeaderPanel headerPanel = (HeaderPanel) getWidget();
        headerPanel.getElement().insertFirst(styleElement);

        final ScrollPanel scrollPanel = (ScrollPanel) headerPanel.getContentWidget();
        scrollPanel.addScrollHandler(new ScrollHandler() {

            @Override
            public void onScroll(ScrollEvent event) {
                int scrollLeft = scrollPanel.getHorizontalScrollPosition();
                if (scrollLeft != currentScrollLeft) {
                    StringBuilder css = new StringBuilder();
                    if (scrollLeft > 0) {
                        css.append(".ScrolledGrid-frozen {");
                        css.append("background-color: inherit;");
                        css.append("}");

                        css.append(".ScrolledGrid-frozen div {");
                        css.append("position: absolute;");
                        css.append("left: ").append(scrollLeft).append("px;");
                        css.append("width: ").append(getColumnWidth(getColumn(0))).append(";");
                        css.append("padding-left: 1.3em;");
                        css.append("padding-right: 0.5em;");
                        css.append("margin-top: -0.7em;");
                        css.append("white-space: nowrap;");
                        css.append("background-color: inherit;");
                        css.append("}");
                    }
                    else
                        css.append(".ScrolledGrid-frozen { }");

                    css.append("th.ScrolledGrid-frozen { background-color: white; }");

                    cssText.setData(css.toString());


                    if (!addedClass) {
                        NodeList<TableRowElement> rows;
                        TableRowElement row;
                        TableCellElement cell;

                        rows = getTableHeadElement().getRows();
                        for (int i = 0; i < rows.getLength(); ++i) {
                            row = rows.getItem(i);
                            cell = row.getCells().getItem(0);
                            cell.setInnerHTML("<div>" + cell.getInnerHTML() + "</div>");
                            cell.addClassName("ScrolledGrid-frozen");
                        }

                        rows = getTableBodyElement().getRows();
                        for (int i = 0; i < rows.getLength(); ++i) {
                            row = rows.getItem(i);
                            cell = row.getCells().getItem(0);

                            cell.addClassName("ScrolledGrid-frozen");
                        }
                        addedClass = true;
                    }

                    currentScrollLeft = scrollLeft;
                }
            }
        });
    }
}

残念ながら、一部のCSS値はハードコーディングされています。

于 2012-07-25T15:17:50.533 に答える
0

次の目標を達成するために、Yuriのソリューションを採用しました。

  • ちらつきません
  • 任意の行の高さに対応します
  • SelectionModelで動作します
  • より均一なソリューション

列自体を混乱させることはありませんが、代わりに行レベルで任意の「凍結」情報を表示します。

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.*;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.DefaultCellTableBuilder;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HeaderPanel;
import com.google.gwt.user.client.ui.ScrollPanel;

/**
 * @author Daniel Lintner
 *
 * A DataGrid extension with the ability to display some row-level-information
 * when scrolling left (horizontal), hence important columns out of sight of the user.
 */
public class FrozenDataGrid extends DataGrid
{
    //textnode getting updated dynamically when scolling horizontally
    private Text cssText;

    //the latest scroll-position
    private int currentScrollLeft = 0;

    //an object extracting String-info from your rowdata
    private FrozenValueProvider valueProvider;

    //inject basic styling into the document - once
    //this is how the frozen row-info looks like
    static
    {
        Text baseCss = Document.get().createTextNode("");
        StyleElement styleElement = Document.get().createStyleElement();
        styleElement.setType("text/css");
        styleElement.appendChild(baseCss);

        StringBuilder css = new StringBuilder();
        css.append(".ScrolledGrid-base {");
        css.append("position: absolute;");
        css.append("background-color: gray;");
        css.append("padding: .3em;");
        css.append("padding-left: .5em;");
        css.append("padding-right: .5em;");
        css.append("border-radius: 3px 3px;");
        css.append("transition: opacity 500ms;");
        css.append("color: white;");
        css.append("margin-top: 2px;");
        css.append("white-space: nowrap;");
        css.append("}");
        baseCss.setData(css.toString());
        Document.get().getBody().insertFirst(styleElement);
    }

    public FrozenDataGrid()
    {
        super();
        init();
    }

    public FrozenDataGrid(int pageSize, DataGrid.Resources resources)
    {
        super(pageSize, resources);
        init();
    }

    public void init()
    {
        //create a css textnode
        cssText = Document.get().createTextNode("");

        //create dynamic css Style
        StyleElement styleElement = Document.get().createStyleElement();
        styleElement.setType("text/css");
        styleElement.appendChild(cssText);

        //append the initial style condition
        //todo the name of this style might be built dynamically per instance - if multiple grid-instances exist/not the use-case by now
        StringBuilder css = new StringBuilder();
        css.append(".ScrolledGrid-frozen {");
        css.append("opacity:0;");
        css.append("}");
        cssText.setData(css.toString());

        //set a custom CellTableBuilder in order to inject the info-div to the row
        setTableBuilder(new DefaultCellTableBuilder(this)
        {
            @Override
            public void buildRowImpl(final Object rowValue, final int absRowIndex)
            {
                //do what DefaultCellTableBuilder does
                super.buildRowImpl(rowValue, absRowIndex);

                //only do something if there is a valueProvider
                if(valueProvider != null) {
                    //we do this deferred because this row has to created first in order to access it
                    Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand()
                    {
                        @Override
                        public void execute()
                        {
                            createInfoDiv(getTableBodyElement().getRows().getItem(absRowIndex % getPageSize()), rowValue);
                        }
                    });
                }
            }
        });

        //fetch the ScrollPanel from the grid
        HeaderPanel headerPanel = (HeaderPanel) getWidget();
        headerPanel.getElement().insertFirst(styleElement);
        final ScrollPanel scrollPanel = (ScrollPanel) headerPanel.getContentWidget();

        //setup a timer handling the left-offset-css thing
        //we use a timer to be able to cancel this operation -> e.g. continuous scroll
        final Timer timer = new Timer(){

            @Override
            public void run() {
                StringBuilder css = new StringBuilder();

                //we need to left-offset the info-divs
                if (scrollPanel.getHorizontalScrollPosition() > 100)
                {
                    css.append(".ScrolledGrid-frozen {");
                    css.append("left: ").append(3 + scrollPanel.getHorizontalScrollPosition()).append("px;");
                    css.append("opacity: 1;");
                    css.append("}");
                }
                //we are close to the leftmost scroll position: info hidden
                else
                {
                    css.append(".ScrolledGrid-frozen {");
                    css.append("opacity:0;");
                    css.append("}");
                }

                cssText.setData(css.toString());
            }
        };

        //track scrolling
        scrollPanel.addScrollHandler(new ScrollHandler()
        {
            @Override
            public void onScroll(ScrollEvent event)
            {
                //cancel previous actions to scroll events
                if(timer.isRunning())
                    timer.cancel();

                //actual horizontal scrollposition
                int scrollLeft = scrollPanel.getHorizontalScrollPosition();

                //a horizontal scroll takes places
                if (scrollLeft != currentScrollLeft)
                {
                    //first we hide the row-info
                    StringBuilder css = new StringBuilder();
                    css.append(".ScrolledGrid-frozen {");
                    css.append("opacity:0;");
                    css.append("}");
                    cssText.setData(css.toString());

                    //render left offset after a delay
                    timer.schedule(500);

                    //remember the current horizontal position
                    currentScrollLeft = scrollLeft;
                }
            }
        });
    }

    private void createInfoDiv(TableRowElement row, Object value)
    {
        //create a div element and add value and style to it
        DivElement div = Document.get().createDivElement();
        div.setInnerText(valueProvider.getFrozenValue(value));
        div.addClassName("ScrolledGrid-base");
        div.addClassName("ScrolledGrid-frozen");

        //we add it to the first child of the row, because added as child of the row directly
        // confuses the CellTable with coordinating header positions
        row.getFirstChildElement().insertFirst(div);
    }

    public void setFrozenValueProvider(FrozenValueProvider valueProvider) {

        this.valueProvider = valueProvider;
    }

    public interface FrozenValueProvider<T>{
        String getFrozenValue(T data);
    }
}

これが、このめったに不十分に解決された問題の開発者に役立つことを願っています。そして...まだ改善の余地があります。

乾杯ダン

于 2018-04-16T13:12:35.377 に答える