【问题描述】
我们常看到一些滚动显示的实例,比如UC浏览器中,显示网页的内容。当内容比较多时,采用滚动分页显示是合理的。在Canvas中绘图中,多余的内容被截断了。如何实现滚动分页显示呢?
【原理】
JavaMe中有一个坐标变换的功能。当触发相应的按键事件时,我们就让其显示相应的页,并且使滚动条滚动到相应的位置。
【代码清单】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
ShowHelp.java package com.token.view; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.game.GameCanvas; import com.token.util.StringDealMethod; import com.token.util.UIController; import com.token.view.components.*; public class ShowHelp extends GameCanvas { private UIController controller; private Graphics graphics; private Font ft; private int width; private int height; private Menu menu; private Head head; private BackGroud backGroud; private int page = 0 ; private int currentPageIndex = 0 ; private int bodyHeight; private int dir = 0 ; public ShowHelp(UIController control) { super ( false ); this .controller=control; setFullScreenMode( true ); width = getWidth(); height = getHeight(); menu = new Menu( this ); head = new Head( this ); backGroud = new BackGroud( this ); } public void show() { int margin = 0 ; graphics = getGraphics(); graphics.clipRect( 0 , 0 , width, height); backGroud.drawBackGroud( this , graphics); head.drawHead( this , graphics, "帮助" ); menu.drawMenu( this , graphics, "" , "返回" ); //flushGraphics(); ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_MEDIUM); String info = "1 滚动分页显示;\n" + "2 滚动分页显示;\n" + "3 滚动分页显示;\n" + "4 滚动分页显示;\n" + "5 滚动分页显示;\n" + "6 滚动分页显示;\n" + "7 滚动分页显示;\n" + "8 滚动分页显示;\n" + "9 滚动分页显示;\n" + "10 滚动分页显示;\n" + "11 滚动分页显示;\n" + "12 滚动分页显示;\n" + "13 滚动分页显示;\n" + "14 滚动分页显示;\n" + "15 滚动分页显示;\n" + "16 滚动分页显示;\n" + "17 滚动分页显示;\n" + "18 滚动分页显示;\n" + "19 滚动分页显示;\n" + "20 滚动分页显示;\n" + "21 滚动分页显示;\n" + "22 滚动分页显示;\n" + "23 滚动分页显示;\n" + "24 滚动分页显示;\n" + "25 滚动分页显示;\n" + "26 滚动分页显示;\n" + "27 滚动分页显示;\n" + "28 滚动分页显示;\n" + "29 滚动分页显示;\n" + "30 滚动分页显示;\n" + "31 滚动分页显示;\n" + "32 滚动分页显示;\n" + "33 滚动分页显示;\n" + "34 滚动分页显示;\n" ; String info_wrap1[] = StringDealMethod.format(info, width- 15 , ft); page = info_wrap1.length*ft.getHeight()/(height-head.menuHeight-menu.menuHeight- 2 *margin)+ 1 ; bodyHeight = (( int ) (height-head.menuHeight-menu.menuHeight)/ft.getHeight())*ft.getHeight(); margin = (height-head.menuHeight-menu.menuHeight-bodyHeight)/ 2 ; graphics.setFont(ft); graphics.setColor(Color.text); graphics.clipRect( 0 , head.menuHeight+margin, width, bodyHeight); graphics.translate( 0 , dir*currentPageIndex*bodyHeight); for ( int i= 0 ; i<info_wrap1.length;i++) { graphics.drawString(info_wrap1[i], 5 , i * ft.getHeight()+head.menuHeight+margin, Graphics.TOP|Graphics.LEFT); } graphics.translate( 0 , -dir*currentPageIndex*bodyHeight); drawScrollBar(); flushGraphics(); //System.out.println(graphics.getTranslateY()); } private void drawScrollBar() { int barHeight = height-head.menuHeight-menu.menuHeight; graphics.setColor(Color.menuFrame); graphics.fillRect(width- 3 , head.menuHeight, 2 , barHeight); graphics.setColor(Color.selectBg); graphics.fillRect(width- 4 , head.menuHeight+(currentPageIndex)*barHeight/page, 4 , barHeight/page); } protected void keyPressed( int keyCode) { //System.out.println(keycode); switch (keyCode) { case KeyID.SOFT_RIGHT: { String flag = "0" ; Object [] args = {flag, "" }; controller.handleEvent(UIController.EventID.EVENT_MAIN_SCREEN,args); break ; } default : ; } keyCode = getGameAction(keyCode); //System.out.println(page); switch (keyCode) { case UP: { dir = - 1 ; if (currentPageIndex> 0 ) { currentPageIndex--; } else { //dir = 0; } show(); break ; } case DOWN: { dir = - 1 ; if (currentPageIndex<page- 1 ) { currentPageIndex++; } else { //dir = 0; } show(); break ; } } } } |
*UIController请参考JavaMe连载(3)-也说MVC设计模式,此处不再赘述。
【分析】
1 字符串拆分
String info_wrap1[] = StringDealMethod.format(info, width-15, ft);
具体请参考JavaMe连载(4)-绘制可自动换行文本
2 避免字截断
如何在指定的区域内绘制整行文本,而不会因为字体或屏幕高度的改变使文本出现截断的问题,使文本出现“半截字”的问题呢?
bodyHeight = ((int) (height-head.menuHeight-menu.menuHeight)/ft.getHeight())*ft.getHeight();
经过上述处理后,滚动区域的高度bodyHeight总会是字体高度的整数倍,这样就不会出现上述字截断的问题了。
3 绘制文本
1
2
3
4
|
for(int i=0; i<info_wrap1.length;i++) { graphics.drawString(info_wrap1[i],5, i * ft.getHeight()+head.menuHeight+margin, Graphics.TOP|Graphics.LEFT); } |
4 坐标变换
1
2
|
graphics.clipRect(0, head.menuHeight+margin, width, bodyHeight); graphics.translate(0, dir*currentPageIndex*bodyHeight); |
文本绘制完成后,将坐标变换回来。
1
|
graphics.translate( 0 , -dir*currentPageIndex*bodyHeight); |
5 绘制滚动条
1
2
3
4
5
6
7
8
9
|
private void drawScrollBar() { int barHeight = height-head.menuHeight-menu.menuHeight; graphics.setColor(Color.menuFrame); graphics.fillRect(width-3, head.menuHeight, 2, barHeight); graphics.setColor(Color.selectBg); graphics.fillRect(width-4, head.menuHeight+(currentPageIndex)*barHeight/page, 4, barHeight/page); } |
6 事件处理
当检测到按键事件后,进行翻页操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
protected void keyPressed( int keyCode) { //System.out.println(keycode); switch (keyCode) { case KeyID.SOFT_RIGHT: { String flag = "0" ; Object [] args = {flag, "" }; controller.handleEvent(UIController.EventID.EVENT_MAIN_SCREEN,args); break ; } default : ; } keyCode = getGameAction(keyCode); //System.out.println(page); switch (keyCode) { case UP: { dir = -1; if (currentPageIndex>0) { currentPageIndex--; } else { //dir = 0; } show(); break ; } case DOWN: { dir = -1; if (currentPageIndex<page-1) { currentPageIndex++; } else { //dir = 0; } show(); break ; } } } |
本例方法能自适应的检测屏幕的宽度和长度,依据字体的大小,对文本进行分页,滚动显示,实现效果如图1所示:
图 滚动显示效果