scrollComponentToVisible

32 views
Skip to first unread message

howud...@gmail.com

unread,
Aug 31, 2016, 6:07:46 PM8/31/16
to CodenameOne Discussions
I am building a picker replacement that uses a dialog to display a list of buttons.  (the iOS picker of only 3 lines is a joke)
The picker is a Dialog component with an associated button.  When the button is pressed, the dialog is shown.  I would like to scroll to the last selected item (even better would be to put it in the middle of the dialog).
when the button is clicked, my code does:
    protected void onButton() {
cnt.removeAll();
for (T t : vData) {
Button b = new Button(t.toString());
b.setAlignment(LEFT);
       b.addActionListener(e -> { onClick(t); });
       cnt.add(b);
       if (t == selectedObject)
        cmpLastVisible = b;
}

if (cmpLastVisible != null)
cnt.scrollComponentToVisible(cmpLastVisible);
this.show();
    }

however I believe it is too early to scrollComponent since the dialog is not shown and is not layed out.

1:  How can I scroll to component?
2:  How can I scroll the component to the middle of the screen?

Here is the whole dialog:
package com.howudodat.pts.ui;

import java.util.ArrayList;

import com.codename1.ui.Button;
import com.codename1.ui.Component;
import com.codename1.ui.Container;
import com.codename1.ui.Dialog;
import com.codename1.ui.FontImage;
import com.codename1.ui.Label;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.plaf.UIManager;

public class DlgPicker<T> extends Dialog {
// was the dialog canceled?
public boolean Cancelled = false;

// the data and container for the list
protected ArrayList<T>vData = null;
protected Container cnt = new Container();

// last selected objects
protected T selectedObject = null;
protected Component cmpLastVisible = null;

// this is the field that can be placed into the parent container
protected Button btnField = new Button();
// title bar for the dialog with a cancel button
protected Label lblTitle = new Label();
Button cmdClose = new Button("",FontImage.createMaterial(FontImage.MATERIAL_CLEAR, UIManager.getInstance().getComponentStyle("Command")));
/**
* constructor - Create a new DlgPicker with no parameters
*/
public DlgPicker() {
        initManualComponents();
    }
    
/**
* constructor - Create a new DlgPicker
* @param sTitle - title of the dialog
*/
public DlgPicker(String sTitle) {
lblTitle.setText(sTitle);
        initManualComponents();
    }
    
/**
* constructor - Create a new DlgPicker
* @param sTitle - title of the dialog
* @param vData - data for the list
*/
public DlgPicker(String sTitle, ArrayList<T> vData) {
this.vData = vData;
lblTitle.setText(sTitle);
        initManualComponents();
    }
    
/**
* create the base gui Note:  the list is created when showing the dialog
*/
    protected void initManualComponents() {
    this.setLayout(new BorderLayout());
    lblTitle.setAlignment(CENTER);
cmdClose.addActionListener(e->onClose());
btnField.addActionListener(e->onButton());

        Container title = new Container();
        title.setLayout(new BorderLayout());
        title.add(BorderLayout.CENTER, lblTitle);
        title.add(BorderLayout.EAST, cmdClose);
        
        cnt.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
        cnt.setScrollableY(true);
        
        this.add(BorderLayout.NORTH, title);
        this.add(BorderLayout.CENTER, cnt);
    }
    
    /**
     * retrieve the component to place in the parent (this is a button)
     * @return Component
     */
    public Component getComponent() {
    return btnField;
    }
    
    /**
     * set the title of the dialog
     */
    public void setTitle(String sTitle) {
lblTitle.setText(sTitle);
    }
    
    /**
     * set the data for the list
     * @param vData
     */
    public void setData(ArrayList<T>vData) {
    this.vData = vData;
    }
    
    /**
     * called when the button is clicked.  This is where we load the data and display the dialog
     */
    protected void onButton() {
cnt.removeAll();
for (T t : vData) {
Button b = new Button(t.toString());
b.setAlignment(LEFT);
       b.addActionListener(e -> { onClick(t); });
       cnt.add(b);
       if (t == selectedObject)
        cmpLastVisible = b;
}

if (cmpLastVisible != null)
cnt.scrollComponentToVisible(cmpLastVisible);
this.show();
    }
    
    /**
     * called when a list item is clicked.  we save the object and set the button text
     * @param t
     */
    protected void onClick(T t) {
    selectedObject = t;
    btnField.setText(t.toString());
    this.dispose();
    }
    
    /**
     * closed by clicking the cancel button
     */
    protected void onClose() {
    Cancelled = true;
    dispose();
    }
    
    public void setSelectedObject(T t) {
    selectedObject = t;
    }
    
    public T getSelectedObject() {
    return selectedObject;
    }
}



Shai Almog

unread,
Sep 1, 2016, 1:23:00 AM9/1/16
to CodenameOne Discussions, howud...@gmail.com
Picker looks completely different on device for iOS/Android so I suggest looking at the actual on device UI before making an effort.

howud...@gmail.com

unread,
Sep 1, 2016, 11:08:05 AM9/1/16
to CodenameOne Discussions, howud...@gmail.com
The picker on Android is 3 lines with a cancel / ok at the bottom.  This is good for a very small list.  I am working on a picker for a large list.  So my original question still stands

1:  How can I scroll to component?
2:  How can I scroll the component to the middle of the screen?

Shai Almog

unread,
Sep 2, 2016, 1:19:33 AM9/2/16
to CodenameOne Discussions, howud...@gmail.com
Did you run it on the device?
We don't have a screenshot of an iOS device in the javadoc https://www.codenameone.com/javadoc/com/codename1/ui/spinner/Picker.html but it does look/feel very different...

howud...@gmail.com

unread,
Sep 20, 2016, 10:42:06 AM9/20/16
to CodenameOne Discussions, howud...@gmail.com
Yes I ran it on a device both iOS and Android.  Both pickers are a joke for large lists, so my original question still stands.

howud...@gmail.com

unread,
Sep 20, 2016, 11:31:42 AM9/20/16
to CodenameOne Discussions, howud...@gmail.com
ok, so cnt.scrollComponentToVisible(cmpLastVisible); didn't work however wrapping that with callSerially() did work

 Display.getInstance().callSerially(() -> {
 
if (cmpLastVisible != null)
 cnt
.scrollComponentToVisible(cmpLastVisible);
 
});
Reply all
Reply to author
Forward
0 new messages