創(chuàng)建使用觸摸屏的Java ME 程序
楊建強(qiáng)
摘要: 介紹了Canvas 類(lèi)中可用于捕獲觸摸屏事件的方法, 創(chuàng)建了一個(gè)類(lèi)似于iPhone 手機(jī)上的圖片瀏覽程序。
關(guān)鍵詞: Java ME; Canvas
1 Canvas 類(lèi)
Canvas 類(lèi)位于javax.microedition.lcdui 包中, 它提供了低級(jí)屏幕和圖像操作方法。該類(lèi)自身是抽象類(lèi), 使用的時(shí)候需要給出具體的實(shí)現(xiàn)。Canvas 中最重要的方法是paint (Graphics g),它完成圖像的實(shí)際繪制。當(dāng)然, 在這里paint () 方法并不是重點(diǎn), 感興趣的是其他5 個(gè)方法, 它們可用于創(chuàng)建使用觸摸屏的Java ME 程序。這些方法包括hasPointerEvents ()、hasPointer-MotionEvents ( ) 、pointerDragged ( int x, int y) 、pointerPressed(int x, int y), 以及pointerReleased (int x, int y)。這5 個(gè)方法最初被用于處理具有指點(diǎn)能力的界面———也即用戶能夠使用指點(diǎn)設(shè)備與這樣的界面交互。不過(guò), 在具有觸摸功能的非指點(diǎn)設(shè)備上, 這些方法工作得一樣好。
當(dāng)發(fā)生指點(diǎn)事件時(shí), 也即按下、釋放和拖動(dòng)指點(diǎn)設(shè)備時(shí),系統(tǒng)會(huì)分別調(diào)用pointerPressed (int x, int y) 、pointerReleased(int x, int y) 和pointerDragged (int x, int y) 方法, 此時(shí), 參數(shù)x、y 中存有指點(diǎn)事件發(fā)生時(shí)指點(diǎn)所在的坐標(biāo)。因此, 可以利用這些方法獲得指點(diǎn)所在的位置, 并根據(jù)需要完成相應(yīng)的操作。注意, 系統(tǒng)對(duì)這些方法的調(diào)用是串行的, 也即系統(tǒng)從不在前一個(gè)調(diào)用方法返回之前調(diào)用另一個(gè)方法。方法hasPointerEvents() 檢查設(shè)備是否支持指點(diǎn)按下和釋放事件。當(dāng)has-PointerEvents () 返回true 時(shí), 意味著設(shè)備支持pointerPressed(int x, int y) 和pointerReleased (int x, int y) 方法。方法has-PointerMotionEvents () 檢查設(shè)備是否支持指點(diǎn)移動(dòng)事件。當(dāng)hasPointerMotionEvents () 返回true 時(shí), 意味著設(shè)備支持pointerDragged(int x, int y) 方法。
2 利用Canvas 創(chuàng)建觸摸屏圖片瀏覽器
有了前面的基礎(chǔ), 現(xiàn)在來(lái)創(chuàng)建一個(gè)類(lèi)似于iPhone 手機(jī)上的觸摸屏圖片瀏覽器。首先, 讓先看一下程序運(yùn)行時(shí)的屏幕截圖, 從而搞清楚要實(shí)現(xiàn)的效果是什么。如圖1 顯示Java ME程序啟動(dòng)后加載的圖片, 以及稍微向左拖動(dòng)或滑動(dòng)該圖片后的效果。
順便說(shuō)一下, 使用Java ME SDK 3.0 作為測(cè)試平臺(tái), 并選用DefaultFxTouchPhone1 作為目標(biāo)模擬器。因此, 給出的屏幕截圖來(lái)自于電腦上運(yùn)行的模擬器。當(dāng)然, 在模擬器只能使用鼠標(biāo)來(lái)代替手指。
選擇的圖片比屏幕的尺寸要寬一些, 為的是創(chuàng)造出圖片滾動(dòng)的效果。在實(shí)際設(shè)備上, 當(dāng)手指在屏幕上左右滑動(dòng)時(shí), 程序會(huì)根據(jù)滑動(dòng)的距離顯示出當(dāng)前圖片的剩余部分, 或者顯示出前一幅或下一幅圖片。圖片剛加載時(shí)剩余部分位于屏幕右側(cè)。程序是這樣設(shè)置的, 如果水平滑動(dòng)的距離少有20 個(gè)點(diǎn)(像素),將顯示出當(dāng)前圖片的剩余部分。如果滑動(dòng)的距離超過(guò)20 個(gè)點(diǎn),則顯示前一幅或下一幅圖片(分別對(duì)應(yīng)向左、向右滑動(dòng)), 如圖2 所示。要達(dá)到的效果就是通過(guò)手指的滑動(dòng)來(lái)逐個(gè)顯示圖片庫(kù)中的圖片。
知道了想要的結(jié)果, 現(xiàn)在來(lái)看一看完成上述任務(wù)的Canvas類(lèi)的代碼。
public class BrowseImageCanvas extends Canvas {
private boolean scroll = false;
private int currentImage = 0;
private Image[] images; // 存放多個(gè)圖片,相當(dāng)于圖片庫(kù)
private int pressX, releaseX, dragX = 0;
public BrowseImageCanvas() {
// 啟動(dòng)時(shí)加載圖片,這里加載3 個(gè)圖片
images = new Image[3];
images[0] = Image.createImage("/flower0.jpg");
images[1] = Image.createImage("/flower1.jpg");
images[2] = Image.createImage("/flower2.jpg");
}
protected void paint(Graphics g) {
g.setGrayScale(255);
g.fillRect(0, 0, getWidth(), getHeight()); // 清屏
if (scroll) { // 滾動(dòng)當(dāng)前圖片
g.drawImage(images[currentImage], -dragX, 0,
Graphics.LEFT | Graphics.TOP);
scroll = false;
return;
}
if (pressX < releaseX) { // 向右滑動(dòng),顯示下一幅圖片
currentImage++;
if (currentImage == images.length) currentImage = 0;
}
if (pressX > releaseX) { // 向左滑動(dòng),顯示前一幅圖片
currentImage--;
if (currentImage < 0) currentImage = (images.length - 1);
}
// 繪制新的圖片
g.drawImage (images [currentImage], 0, 0, Graphics.
LEFT | Graphics.TOP);
}
protected void pointerPressed(int x, int y) { // 記下
//開(kāi)始觸摸的水平位置
pressX = x;
}
// 記下觸摸釋放的水平位置,判斷滑動(dòng)的距離決定是否加
//載新圖片
protected void pointerReleased(int x, int y) {
if (scroll) return;
releaseX = x;
if (Math.abs(releaseX - pressX) > 20) { // 滑動(dòng)距離超
//過(guò)20 個(gè)點(diǎn)加載新圖片
repaint();
}
}
protected void pointerDragged(int x, int y) { //在這里
//決定是否滾動(dòng)圖片
int deltaX = pressX - x;
if (Math.abs(deltaX) <= 20) { // 滑動(dòng)距離少于20 個(gè)點(diǎn)
//滾動(dòng)當(dāng)前圖片
int imageWidth = images[currentImage].getWidth();
if (imageWidth > getWidth()) {
dragX += deltaX;
if (dragX < 0) dragX = 0;
else if (dragX + getWidth() > imageWidth) dragX
= imageWidth - getWidth();
}
scroll = true;
repaint();
}
}
}
程序中, pointerPressed ( ) 、pointerReleased ( ) 、pointer-Dragged () 方法設(shè)置各種參數(shù), paint () 利用這些參數(shù)來(lái)決定是否滾動(dòng)當(dāng)前圖片或顯示新圖片。在pointerPressed () 方法中,保存了用戶觸摸位置的x 軸坐標(biāo), 然后, 在pointerReleased ()和pointerDragged () 方法中確定用戶手指沿水平方向移動(dòng)的距離大小(deltaX)。如果移動(dòng)超過(guò)20 點(diǎn), 則顯示新圖片, 否則就沿x 軸方向卷動(dòng)圖片。可以左右兩個(gè)方向移動(dòng)。當(dāng)然, 為了簡(jiǎn)化問(wèn)題, 程序忽略了沿y 軸方向的移動(dòng)。
3 結(jié)語(yǔ)
自Java ME 誕生以來(lái), 它就已經(jīng)具備了滿足觸摸屏界面的能力, 只是那些提供Java ME 實(shí)現(xiàn)的設(shè)備制造商沒(méi)有跟上步伐。介紹了Canvas 類(lèi)中的能夠捕獲觸摸屏上指點(diǎn)運(yùn)動(dòng)的接口,并以一個(gè)類(lèi)似于iPhone 手機(jī)上的圖片瀏覽程序來(lái)演示其使用方法。希望能夠起到拋磚引玉的作用, 啟發(fā)讀者寫(xiě)出更加實(shí)用的觸摸屏Java 程序。