问题
Here I am creating a screen for chatting that contains a top bar, custom vertical scroll manager, an Editfield
to send messages and a send button.
Now I create a message layout: it has VerticalFieldManager
and it contains EditField
that is focusable and readonly, and two LabelField
s for name and date. This vertical field manager is created dynamically depending on the number of chat messages. This is all laid out in custom scroll.
I need scrolling to start from the bottom of the screen. Right now, it works from top of the screen.
At the bottom on the screen I have a BasicEditField
and send button.
Each 7 seconds, I refresh the page and when refreshing the page, I recreate the whole layout. So I need to retain focus on the BasicEditField
whenever my page refreshes. And I also want the scrolling to work reversed.
Here my vertical scroll manager class
public class VerticalScrollManager extends VerticalFieldManager implements
ScrollChangeListener {
public VerticalScrollManager() {
this(VERTICAL_SCROLL | NO_VERTICAL_SCROLLBAR|DOWNWARD, Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public VerticalScrollManager(int w, int h) {
this(VERTICAL_SCROLL | NO_VERTICAL_SCROLLBAR|DOWNWARD, w, h);
}
public VerticalScrollManager(long style) {
this(style, Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public VerticalScrollManager(long style, int w, int h) {
super(style);
maxVisibleHeight = h;
maxVisibleWidth = w;
setScrollListener(this);
}
protected void sublayout(int w, int h) {
isScrolling = ((getStyle() & VERTICAL_SCROLL) == VERTICAL_SCROLL);
int scrollbarWidth = isScrolling ? SCROLLBAR_WIDTH + SCROLLBAR_LEFT_MARGIN + SCROLLBAR_RIGHT_MARGIN : 0;
visibleHeight = Math.min(h, maxVisibleHeight);
visibleWidth = Math.min(w, maxVisibleWidth);
int myWidth = visibleWidth - scrollbarWidth;
super.sublayout(myWidth, visibleHeight);
visibleHeight = getHeight();
totalHeight = getVirtualHeight();
visibleWidth = getWidth() + scrollbarWidth;
setExtent(visibleWidth, visibleHeight);
setVirtualExtent(visibleWidth, totalHeight);
isScrolling = (visibleHeight < totalHeight);
if (isScrolling) {
sliderHeight = visibleHeight * visibleHeight / totalHeight;
sliderHeight = Math.max(sliderHeight, 1); // show at least one pixel!
sliderXPosition = visibleWidth - SCROLLBAR_WIDTH - SCROLLBAR_RIGHT_MARGIN;
}
}
public void scrollChanged(Manager mgr, int newX, int newY) {
if (mgr == this) {
invalidate(newX + sliderXPosition, newY, SCROLLBAR_WIDTH + SCROLLBAR_RIGHT_MARGIN, getVisibleHeight());
}
}
}
and here my screen that handle ui and functionality
public class ChatScreen extends MainScreen implements FieldChangeListener, FocusChangeListener {
class MainTask implements Runnable
{
public MainTask()
{}
public void run() {
try
{
if(textMsg.getText().equals(""))
{
IssueHTTPPostL();
}
else
{
IssueHTTPPostChat(textMsg.getText());
}
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
if(replyCode.equalsIgnoreCase("success"))
{
if(chatMsgData!=null && chatMsgData.length>0 )
{
for( int i=0; i<chatMsgData.length; i++)
{
final String name = chatMsgData[i].name;
final String email = chatMsgData[i].email;
final String date = chatMsgData[i].date;
final String msg = chatMsgData[i].message;
final String vappUser = chatMsgData[i].vappUser;
if(chatMsgData[i].isReply.equals("0"))
{
vfm = new VerticalFieldManager(VerticalFieldManager.FIELD_RIGHT)
{
protected void paintBackground(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRoundRect(30, 0, getWidth()-30, getHeight(), 12, 12);
g.setColor(0X626262);
g.drawRoundRect(30, 0, getWidth()-30, getHeight(), 12, 12);
//g.drawBitmap(0,0,getWidth(),getHeight(),imgRight,0,0);
}
};
lblName = new LabelField(name, LabelField.FIELD_LEFT|DrawStyle.LEFT)
{
protected void paint(Graphics g)
{
g.setColor(Color.BLACK);
super.paint(g);
};
};
if(name.equals("")||name.equals("Name"))
{
lblName.setText(email);
}
lblDate = new LabelField(date, LabelField.FIELD_RIGHT|DrawStyle.RIGHT);
lblDate.setFont(font.derive(Font.PLAIN, dateFontSize));
lblName.setFont(font.derive(Font.BOLD, nameFontSize));
JustifiedHorizontalFieldManager hfm = new JustifiedHorizontalFieldManager(lblName, lblDate, true);
hfm.setMargin(10, 10, 10, 50);
lblMsg = new EditField(EditField.FOCUSABLE|EditField.READONLY)
{
protected void paint(Graphics g)
{
g.setColor(0x626262);
super.paint(g);
};
};
lblMsg.setText(msg);
lblMsg.setMargin(10, 10, 10, 50);
lblMsg.setFont(font.derive(Font.PLAIN, msgFontSize));
vfm.add(hfm);
vfm.add(lblMsg);
vfm.setMargin(10, 20, 10, 0);
}
else
{
vfm = new VerticalFieldManager(VerticalFieldManager.FIELD_LEFT)
{
protected void paintBackground(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRoundRect(0, 0, getWidth()-30, getHeight(), 12, 12);
g.setColor(Color.BLACK);
g.drawRoundRect(0, 0, getWidth()-30, getHeight(), 12, 12);
//g.drawBitmap(0,0,getWidth(),getHeight(),imgLeft,0,0);
}
};
lblName = new LabelField(vappUser, LabelField.FIELD_LEFT|DrawStyle.LEFT)
{
protected void paint(Graphics g)
{
g.setColor(Color.BLACK);
super.paint(g);
};
};
if(name.equals("")||name.equals("Name"))
{
lblName.setText(email);
}
lblDate = new LabelField(date, LabelField.FIELD_RIGHT|DrawStyle.RIGHT)
{
protected void paint(Graphics g)
{
g.setColor(0X626262);
super.paint(g);
};
};
lblDate.setFont(font.derive(Font.PLAIN, dateFontSize));
lblName.setFont(font.derive(Font.BOLD, nameFontSize));
JustifiedHorizontalFieldManager hfm = new JustifiedHorizontalFieldManager(lblName, lblDate, true);
//hfm.setMargin("top", "right", "bottom", "left");
hfm.setMargin(10, 50, 10, 10);
lblMsg = new EditField(EditField.FOCUSABLE|EditField.READONLY)
{
protected void paint(Graphics g)
{
g.setColor(0x626262);
super.paint(g);
};
};
lblMsg.setText(msg);
lblMsg.setMargin(10, 40, 10, 10);
lblMsg.setFont(font.derive(Font.PLAIN, msgFontSize));
vfm.add(hfm);
vfm.add(lblMsg);
vfm.setMargin(10, 10, 20, 0);
}
vsm.add(vfm);
}
}
add(vsm);
add(sendHfm);
}
else
{
timer.cancel();
UiApplication.getUiApplication().popScreen(ChatScreen.this);
UiApplication.getUiApplication().pushScreen(new ChatListScreen());
}
}
});
}
catch(Exception e)
{e.printStackTrace();}
}
}
}
回答1:
If I understand you correctly, you have one VerticalFieldManager
in the middle of the screen (below the Top Bar, and above the Send button). You would like to have that manager start at the bottom of its content. Right?
For that, try using
vsm.setVerticalScroll(vsm.getVirtualHeight());
where vsm
is that vertical field manager that contains the old read-only messages.
Anytime something happens (like a page refresh) that might take focus off your BasicEditField
, you can get it back with
textMsg.setFocus();
where textMsg
is the edit field. Obviously, in order for this to work, you need to keep vsm
and textMsg
as member variables, instead of just creating them as local variables and adding them to your screen with add()
.
来源:https://stackoverflow.com/questions/15401993/how-to-create-custom-scrolling-always-start-from-bottom