首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java ME 實現自適應滾動顯示:座標變換、分頁算法與滾動條繪製

     編輯:Java 相關知識

在 Java ME 的 Canvas/GameCanvas 低級 UI 中,長文本顯示面臨截斷、無滾動條、適配多種屏幕尺寸三大挑戰。本文展示一套基於座標變換的自適應分頁滾動方案,含完整源碼與核心算法解析。

核心思路:translate + clipRect 實現虛擬視口

  1. 文本預處理:按屏幕寬度將長字符串拆分為行陣列 String[] lines。
  2. 計算頁數:pageCount = totalLines * lineHeight / visibleHeight + 1。
  3. 可見區域高度對齊行高:visibleHeight = (visibleHeight / lineHeight) * lineHeight,避免半行截斷。
  4. 繪製時平移座標系:g.translate(0, -pageIndex * visibleHeight),將目標頁內容移入可見區。
  5. 繪製滾動條:根據 pageIndex/pageCount 比例在右側繪製滑塊。

完整實現類:ShowHelp

public class ShowHelp extends GameCanvas implements Runnable {
    private int pageCount;        // 總頁數
    private int currentPage = 0;  // 當前頁
    private int visibleHeight;    // 可見區高度(行高整數倍)
    private int dir = 0;          // 滾動方向

    public void show() {
        Graphics g = getGraphics();
        g.clipRect(0, 0, getWidth(), getHeight());

        // 1. 繪製背景、標題欄、菜單欄...
        // 2. 文本換行
        Font ft = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_MEDIUM);
        String longText = "1 滾動分頁顯示;\n2 滾動分頁顯示;\n...共 34 行";
        String[] lines = StringDealMethod.format(longText, getWidth()-15, ft);

        // 3. 計算分頁參數
        int headerH = headHeight + menuHeight;
        int bodyH = getHeight() - headerH;
        visibleHeight = (bodyH / ft.getHeight()) * ft.getHeight(); // 對齊行高
        int margin = (bodyH - visibleHeight) / 2;
        pageCount = lines.length * ft.getHeight() / visibleHeight + 1;

        // 4. 設置繪製裁剪區(僅正文區)
        g.clipRect(0, headerH + margin, getWidth(), visibleHeight);

        // 5. 座標變換:將當前頁內容平移進可見區
        g.translate(0, -currentPage * visibleHeight);

        // 6. 繪製所有行(實際繪製座標為絕對位置,translate 自動偏移)
        g.setFont(ft);
        g.setColor(Color.TEXT);
        for (int i = 0; i < lines.length; i++) {
            g.drawString(lines[i], 5, i * ft.getHeight() + headerH + margin,
                         Graphics.TOP | Graphics.LEFT);
        }

        // 7. 恢復座標系
        g.translate(0, currentPage * visibleHeight);

        // 8. 繪製滾動條
        drawScrollBar(g);

        flushGraphics();
    }

    private void drawScrollBar(Graphics g) {
        int barH = getHeight() - headHeight - menuHeight;
        int x = getWidth() - 4;
        g.setColor(Color.GRAY);
        g.fillRect(x, headHeight, 2, barH); // 軌道
        g.setColor(Color.BLUE);
        int thumbH = barH / pageCount;
        int thumbY = headHeight + currentPage * barH / pageCount;
        g.fillRect(x-1, thumbY, 4, thumbH); // 滑塊
    }

    // 鍵盤控制
    protected void keyPressed(int keyCode) {
        if (keyCode == Canvas.KEY_NUM4) { /* 返回主菜單 */ return; }
        int action = getGameAction(keyCode);
        if (action == Canvas.UP) {
            if (currentPage > 0) { currentPage--; dir = -1; show(); }
        } else if (action == Canvas.DOWN) {
            if (currentPage < pageCount - 1) { currentPage++; dir = 1; show(); }
        }
    }
    // Runnable 接口可用於自動滾動或游標閃爍,此處省略
}

關鍵算法細節深度解析

1. 防止「半行字」截斷

visibleHeight = (bodyH / lineHeight) * lineHeight;

確保可見區高度是行高的整數倍,clipRect 裁剪時永遠只包含完整行,杜絕頂部/底部出現半截字符。

2. 座標變換 vs 手動計算 Y 座標

方案優點缺點
translate 平移代碼簡潔、繳用絕對座標、自動處理所有繪製調用需記住恢復座標系、調試時邏輯座標與物理座標分離
手動計算 y = baseY - page*pageH直觀、無狀態副作用每行繪製需額外運算、易出錯、擴展困難

推薦 translate:配合 clipRect 實現「虛擬畫布」模型,邏輯清晰。

3. 自適應屏幕尺寸

所有尺寸均基於 getWidth()/getHeight() 動態計算,無硬編碼常數,可在 128x128 至 480x800 任意分辨率設備上正常運行。

擴展建議

  • 慣性滾動:引入速度/加速度模型,keyReleased 後持續平移並衰減。
  • 觸摸屏拖拽:監聽 pointerDragged,實時更新 translate 位移量。
  • 富文本支援:行對象封裝字符串+字體+顏色,drawString 替換為逐段繪製。
  • 滾動條樣式:漸變色、圓角、隱藏/顯示動畫。

這套方案在 Java ME 經典項目(如電子書閱讀器、幫助文檔查看器)中大規模驗證,無第三方依賴、代碼量小、性能穩定,是資源受限設備上實現長文本滾動的參考實現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved