CN1 Layout problems

86 views
Skip to first unread message

kyr...@gmail.com

unread,
Aug 16, 2015, 12:10:12 PM8/16/15
to CodenameOne Discussions
I have a BorderLayout that contains a heading in the north, then in the south it contains a text area, a button and then a list. My problem is that. When the list is big it dominates the layout and actually cuts off the heading part. I want to make it so that the list always remains below the heading at all times, no matter how big it gets. Another problem I have is in my list. When a certain list item is big it cuts off and only displays a portion of it. Here is how I set up my layouts...

So I start my app off with the showMainForm() method below: 

    public void showMainForm() {

        main = new Form("");
        main.setLayout(new BorderLayout());
        mainC = mainContainer();
        mainC.setScrollableY(true);
        
        main.setScrollableY(false);
        main.addComponent(BorderLayout.CENTER, mainC);

        main.setUIID("Form1");
        main.show();
        
        mainC.addScrollListener(new ScrollListener() {

            public int scrollSize = 0;
                    
            @Override
            public void scrollChanged(int scrollX, int scrollY, int oldscrollX, int oldscrollY) {
                
                if (scrollY > scrollSize && !hasScrolled) {
                    hasScrolled = true;
                    System.out.println("Scrolled");
                                   
                    commentC = commentContainer();
                    main.replaceAndWait(mainC, commentC, CommonTransitions.createSlide(CommonTransitions.SLIDE_VERTICAL, false, 200));
                    updateComments();

                }
            }
        });

    }

If you look at the scroll changed listener, I use main.replaceAndWait to show the comments container when the user scrolls up. This container should basically have a heading at the top of the layout, then at the bottom it should allow users to type and post a comment and then just above that It should have a scrollable list of all the comments for that specific post. This is the layout that I used. 

    private Container commentContainer() {
    
        BorderLayout bl3 = new BorderLayout();
        //bl3.setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE);
        Container mainContainer = new Container();
        mainContainer.setLayout(bl3);
        mainContainer.setScrollableY(false);
        
//This is where I create the heading...
        BorderLayout topBorder = new BorderLayout();
        topBorder.setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE);
        Container topContainer = new Container(topBorder);
        Label headingLabel = new Label("Comments");
        Button backButton = new Button("");
        backButton.setIcon(getImageFromRes("xunpressed.png"));
        backButton.setPressedIcon(getImageFromRes("xpressed.png"));
        topContainer.addComponent(BorderLayout.CENTER, headingLabel);
        topContainer.addComponent(BorderLayout.EAST, backButton);
        mainContainer.addComponent(BorderLayout.NORTH, topContainer);
        
        BorderLayout bl = new BorderLayout();
        //bl.setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE);
        cont = new Container(bl);
        
//This is the bottom where I the user can make a comment
        BorderLayout bl2 = new BorderLayout();
        //bl2.setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE);
        Container containerBottom = new Container(bl2);
        final TextArea ta = new TextArea();
        ta.setUIID("TextArea1");
        ta.setHint("Add Comment");
        ta.setMaxSize(200);
        ta.setColumns(20);
        ta.setRows(4);
        ta.setGrowByContent(true);
        ta.setScrollVisible(true);

        Button btnPostComment = new Button("");
        btnPostComment.setUIID("ButtonBack");
        btnPostComment.setIcon(getImageFromRes("postcommentunpressed.png"));
        btnPostComment.setPressedIcon(getImageFromRes("postcommentpressed.png"));
        
        btnPostComment.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent evt) {
                /*commentForm.setTransitionOutAnimator(CommonTransitions.createSlide(CommonTransitions.SLIDE_VERTICAL, false, 200));
                main.show();*/
                System.out.println("Pressed");
            if(ta.getText().length() >0) {
                ConnectionRequest cr = new ConnectionRequest() {
                        @Override
                        protected void handleException(Exception err) {
                            super.handleException(err);
                        }

                    };

                    cr.setDuplicateSupported(true);
                    cr.setPost(true);
                    cr.addArgument("id", posts.get(tabs.getSelectedIndex()).getId() + "");
                    cr.addArgument("comment", ta.getText() + "");
                    cr.setUrl(URL + "postComment.php");
                    cr.setFailSilently(false);
                    ta.setText("");
                    ta.setHint("Posting comment");
                    manager.addToQueueAndWait(cr);
                
                main.replaceAndWait(commentC, mainC, CommonTransitions.createSlide(CommonTransitions.SLIDE_VERTICAL, false, 200));
                
            } 
            }
            
        });
        
        containerBottom.addComponent(BorderLayout.EAST, btnPostComment);
        containerBottom.addComponent(BorderLayout.CENTER, ta);
        Container filler = new Container();
        filler.setUIID("Container1");
        containerBottom.addComponent(BorderLayout.NORTH, filler);        
        
        Container bottomContainer = new Container(new BoxLayout(BoxLayout.Y_AXIS));
        bottomContainer.addComponent(cont);
        bottomContainer.addComponent(containerBottom);
        
        mainContainer.addComponent(BorderLayout.SOUTH, bottomContainer);

        return mainContainer;
    }


//I've added the heading and the ability to make a comment at the bottom. Notice I do not fetch the list of comments or add the comments list yet, this is so the layout still shows even //if the user's internet is slow. If I had fetched the comments in this method, the user would have to wait for all the comments to be fetched before the method would return. I then call //this method::public void updateComments() {
        tempList.clear();
        
        ConnectionRequest cr = new ConnectionRequest() {
            @Override
            protected void handleException(Exception err) {
                super.handleException(err);
            }

        };

        cr.setDuplicateSupported(true);
        cr.setPost(true);
        cr.addArgument("id", posts.get(tabs.getSelectedIndex()).getId()+"");
        cr.setUrl(URL + "fetchComments.php");
        cr.setFailSilently(false);
        manager.addToQueueAndWait(cr);
        
        byte[] data = cr.getResponseData();
        Map tempMap = (parseJsonObject(data));
            java.util.List listMessages = (java.util.List) tempMap.get("posts");

        if (listMessages != null && !listMessages.isEmpty()) {

            for (Object listMessage : listMessages) {
                Map tempListMessage = (Map) listMessage;
                String tempComment = tempListMessage.get("comment").toString();
                tempList.add(tempComment);
            }

        } else {
            tempList.add("No comments...");
        }
        
        commentList = new List(new ListModel() {

            private int selected;
            
            public Object getItemAt(int index) {
                
                return tempList.get(index);
                
            }

            public int getSize() {
                return tempList.size();
            }

            public int getSelectedIndex() {
                return selected;
            }

            public void setSelectedIndex(int index) {
            }

            public void addDataChangedListener(DataChangedListener l) {
            }

            public void removeDataChangedListener(DataChangedListener l) {
            }

            public void addSelectionListener(SelectionListener l) {
            }

            public void removeSelectionListener(SelectionListener l) {
            }

            public void addItem(Object item) {
            }

            public void removeItem(int index) {
            }
            
        });
        
        commentList.setListCellRenderer(new CommentsRenderer());
        cont.addComponent(BorderLayout.CENTER, commentList);
        
        main.revalidate();
    }

//This is where I fetch the list of comments, then add the list to the layout and revalidate. Below is my listRenderer: 

        public CommentsRenderer() {
            
            BorderLayout bl = new BorderLayout();
            //bl.setCenterBehavior(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE);
            setLayout(bl);
            setUIID("ContainerListItem");
            
            cTop.setUIID("ContainerBlackList");
            cBottom.setUIID("ContainerBlackList");
            comment.setUIID("LabelComment");
            //comment.setFocusable(false);
            comment.setEditable(false);
            comment.setGrowByContent(true);
            //comment.setColumns(20);
            
            addComponent(BorderLayout.SOUTH, comment);
            //addComponent(cBottom);
            //addComponent(BorderLayout.NORTH, cTop);
        }
        
        public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {
            //throw new UnsupportedOperationException("Not supported yet."); 
            String commentText = (String) value;
            comment.setText(commentText);
            return this;
        }

        public Component getListFocusComponent(List list) {
            
            return focus;
            
        }        
        
    }

How do I make it so that my list stays the same size and my list items become as big as they need to be to show the entire comment. All the list items seem to be the same size. No matter how big the String actually is. Please help me I cannot figure this one out... 


Shai Almog

unread,
Aug 17, 2015, 12:04:35 AM8/17/15
to CodenameOne Discussions, kyr...@gmail.com
Place the list in the center.
SOUTH/NORTH take up their preferred sizes which should be small. The center takes up available space ignoring preferred size.

kyr...@gmail.com

unread,
Aug 17, 2015, 11:45:19 AM8/17/15
to CodenameOne Discussions, kyr...@gmail.com
Okay I added it to the center. The list is sizing fine now but the actual list items are only ever 2 lines. Even if the text inside them is longer than 2 lines. It just cuts off the text...

Shai Almog

unread,
Aug 17, 2015, 12:27:14 PM8/17/15
to CodenameOne Discussions, kyr...@gmail.com
A list row can't change its size, all rows must be exactly the same height: https://www.codenameone.com/blog/deeper-in-the-renderer.html

kyri88

unread,
Aug 18, 2015, 4:36:03 AM8/18/15
to Shai Almog, CodenameOne Discussions
So therefore should I rather use ContainerList? To allow for variable heights


Sent from Samsung Mobile

Shai Almog

unread,
Aug 18, 2015, 11:33:16 AM8/18/15
to codenameone...@googlegroups.com, shai....@gmail.com, kyr...@gmail.com
I would recommend using components in a container and avoiding lists/container list altogether. E.g. the property cross demo doesn't use lists at all yet appears like it does and is pretty spiffy: https://www.udemy.com/learn-mobile-programming-by-example-with-codename-one/

And the same is true for chat: https://www.codenameone.com/blog/building-a-chat-app-with-codename-one-part-5.html

kyr...@gmail.com

unread,
Aug 20, 2015, 10:40:08 AM8/20/15
to CodenameOne Discussions, shai....@gmail.com, kyr...@gmail.com
Worked perfectly. Thanks a lot shai...
Reply all
Reply to author
Forward
0 new messages