这阵子忙项目,写了个控件,有点像文本域,显示文章用的,带滚动条,有拖拽事件,不过还是有个小问题不咋完美。
我承认我的代码不适合阅读,因为注释比较少,并且这个控件的开发难度有点大,主要是拖拽的地方有点复杂,最重要的是,代码还经过一定的优化,合并了许多变量,不过有兴趣的人也可以挑战一下~
设计思路很简单,滚动条的走动依附文本的走动,根据倍数算出各个变量。
具体的实现我自己都不愿意回忆了。
该代码发布之意在于供人使用,不侧重于供人学习阅读。
package com.ctai.items.textarea;
import java.util.Vector;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import com.ctai.utils.ColorSet;
import com.ctai.utils.DefaultProperties;
public class Textarea
{
/** 文字颜色 */
private int i_c_strColor;
/** x, y, 宽, 高*/
public int x, y, width, hight;
/** 文字整体高度 */
private int i_allStrHight;
/** 整体高度 */
private int i_strHight;
private Vector v;
/** 倍数 */
private int Multiple;
/** 滚动条高度 */
private int scrollHight;
/** 滚动条的X和Y坐标 */
private int scrollX, scrollY;
/** ↑↓按钮方块固定Y */
private int boxY;
/** ↑↓按钮方块的宽高 */
private int boxWH = 16;
/** 方向键滚屏像素值 */
private int rollValue;
/** 方向键滚屏侧滑块移动的偏差像素值 */
private int rollMoveScrollValue;
/** 临时变量 */
private int temp, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
/** 文字是否超过一篇 */
private boolean b_isHaveMore = true;
private int i_dragged[] = new int[2];
/**
* 文本域
* @param st_strOut 文本域内文字
* @param font 当前g的字体
* @param i_c_strColor 文字颜色
* @param x
* @param y
* @param width 宽
* @param hight 高
* @param rollValue 方向键滚屏像素值
* */
public Textarea(String st_strOut, Font font, int i_c_strColor, int x, int y, int width, int hight, int rollValue)
{
this.i_c_strColor = i_c_strColor;
this.x = x;
this.scrollX = x + width; // 滑块X的坐标初始化
this.y = y;
this.temp7 = y;
this.boxY = y;
this.scrollY = y + boxWH; // 滑块Y的坐标初始化
this.width = width;
this.hight = hight;
this.rollValue = rollValue;
v = getSubsection(st_strOut, font, width, "\r\n"); // 赋值vector
init();
temp8 = 320 - (boxY + boxWH * 2 + scrollHight + 30);
}
public void init()
{
Multiple = (temp6 + ((260 / i_strHight) - 1)) / (260 / i_strHight); //倍数
if (Multiple == 1)
{
b_isHaveMore = false;
}
else
{
scrollHight = (hight - boxWH * 2) * 260 / (temp6 * i_strHight);
}
temp = hight - boxWH;
temp2 = (boxWH >> 2);
temp3 = scrollX + (boxWH >> 1);
temp4 = temp2 * 3;
temp5 = boxWH * 2;
}
public void paint(Graphics g)
{
g.setColor(i_c_strColor);
if (v != null && v.size() > 0)
{
for (int i = 0; i < v.size(); i++)
{
g.drawString(v.elementAt(i).toString(), x, i * i_strHight + y, 0);
}
}
// 画整个滚动条
g.setColor(ColorSet.scrollBackColor);
g.fillRect(scrollX - 1, boxY - 1, boxWH + 2, hight + 2);
// 画上、下小箭头块边框
g.setColor(ColorSet.scrollBorderColor);
g.fillRect(scrollX - 1, boxY - 1, boxWH + 2, boxWH + 2);
g.fillRect(scrollX - 1, boxY + temp - 1, boxWH + 2, boxWH + 2);
// 画上、下箭头小块
g.setColor(ColorSet.scrollFontColor);
g.fillRect(scrollX, boxY, boxWH, boxWH);
g.fillRect(scrollX, boxY + temp, boxWH, boxWH);
// 画箭头
g.setColor(ColorSet.scrollIcoColor);
// 画∧
// 画/
g.drawLine(temp3, boxY + temp2, scrollX + temp2, boxY + temp4);
// 画\
g.drawLine(temp3, boxY + temp2, scrollX + temp4, boxY + temp4);
// 画∨
// 画\
g.drawLine(temp3, boxY + temp + temp4, scrollX + temp2, boxY + temp + temp2);
// 画/
g.drawLine(temp3, boxY + temp + temp4, scrollX + temp4, boxY + temp + temp2);
g.setColor(ColorSet.scrollBorderColor);
g.fillRect(scrollX, scrollY + rollMoveScrollValue, boxWH, scrollHight);
g.setColor(ColorSet.scrollFontColor);
g.fillRect(scrollX + 1, scrollY + rollMoveScrollValue + 1, boxWH - 2, scrollHight - 2);
}
public void pointerDragged(int x, int y)
{
if(b_isHaveMore)
{
i_dragged[1] = i_dragged[0];
i_dragged[0] = y;
if(x < scrollX && y > boxY && y < 290)
{
this.y -= i_dragged[0] - i_dragged[1];
if (this.y - this.temp7 <= i_allStrHight)
{
this.y = i_allStrHight + this.temp7;
}
else if (this.y >= boxY)
{
this.y = boxY;
}
rollMoveScrollValue = getXY(temp8, this.y - this.temp7, i_allStrHight);
if (rollMoveScrollValue < 0)
{
rollMoveScrollValue = 0;
}
}
if(x > scrollX && x < 239 && y > scrollY + rollMoveScrollValue && y < scrollY + rollMoveScrollValue + scrollHight)
{
this.y += (i_dragged[0] - i_dragged[1]) * (i_allStrHight / (hight - (boxWH * 2) - scrollHight));
if (this.y - this.temp7 <= i_allStrHight)
{
this.y = i_allStrHight + this.temp7;
}
else if (this.y >= boxY)
{
this.y = boxY;
}
rollMoveScrollValue = getXY(temp8, this.y - this.temp7, i_allStrHight);
if (rollMoveScrollValue < 0)
{
rollMoveScrollValue = 0;
}
}
}
}
public void keyPressed(int keyCode)
{
if (b_isHaveMore)
{
if (keyCode == DefaultProperties.KEY_DOWN)
{
this.y -= rollValue;
if (this.y - this.temp7 <= i_allStrHight)
{
this.y = i_allStrHight + this.temp7 + 2;
}
}
if (keyCode == DefaultProperties.KEY_UP)
{
this.y += rollValue;
if (this.y >= boxY)
{
this.y = boxY;
}
}
rollMoveScrollValue = getXY(temp8, this.y - this.temp7, i_allStrHight);
if (rollMoveScrollValue < 0)
{
rollMoveScrollValue = 0;
}
}
}
public void pointerPressed(int x, int y)
{
if (b_isHaveMore)
{
i_dragged[1] = y;
i_dragged[0] = y;
if (x > scrollX && x < scrollX + boxWH && y > scrollY && y < scrollY + hight - temp5) // 在滑块内点击时间的捕捉
{
if (y < scrollY + rollMoveScrollValue)
{
this.y += hight;
if (this.y >= boxY)
{
this.y = boxY;
}
}
else if (y > scrollY + rollMoveScrollValue + scrollHight)
{
this.y -= hight;
if (this.y - this.temp7 <= i_allStrHight)
{
this.y = i_allStrHight + this.temp7 + 2;
}
}
rollMoveScrollValue = getXY(temp8, this.y - this.temp7, i_allStrHight);
if (rollMoveScrollValue < 0)
{
rollMoveScrollValue = 0;
}
}
else if (x > scrollX && x < scrollX + boxWH && y > boxY && y < boxY + boxWH)
{
this.y += rollValue;
if (this.y >= boxY)
{
this.y = boxY;
}
rollMoveScrollValue = getXY(temp8, this.y - this.temp7, i_allStrHight);
if (rollMoveScrollValue < 0)
{
rollMoveScrollValue = 0;
}
}
else if (x > scrollX && x < scrollX + boxWH && y > boxY + temp && y < boxY + hight)
{
this.y -= rollValue;
if (this.y - this.temp7 <= i_allStrHight)
{
this.y = i_allStrHight + this.temp7 + 2;
}
rollMoveScrollValue = getXY(temp8, this.y - this.temp7, i_allStrHight);
}
}
}
private final int getXY(int w, int x, int Exp)
{
return (int) (((long) (x * w) * 1000000) / ((long) Exp * 1000000));
}
/** 此方法会根据文字内容自动返回长度适应给定width的vector */
public Vector getSubsection(String strSource, Font font, int width, String strSplit)
{
Vector vector = new Vector();
String temp = strSource;
int i, j;
int LastLength = 1;
int step = 0;
try {
while (!temp.equals(""))
{
i = temp.indexOf("\n");
if (i > 0)
{
if (font.stringWidth(temp.substring(0, i - 1)) >= width)
{
i = -1;
}
}
if (i == -1)
{
if (LastLength > temp.length())
{
i = temp.length();
}
else
{
i = LastLength;
step = font.stringWidth(temp.substring(0, i)) > width ? -1 : 1;
if (i < temp.length())
{
while (!(font.stringWidth(temp.substring(0, i)) <= width && font.stringWidth(temp.substring(0, i + 1)) > width))
{
i = i + step;
if (i == temp.length())
{
break;
}
}
}
}
if (!strSplit.equals(""))
{
j = i;
if (i < temp.length())
{
while (strSplit.indexOf(temp.substring(i - 1, i)) == -1)
{
i--;
if (i == 0)
{
i = j;
break;
}
}
}
}
}
LastLength = i;
vector.addElement(temp.substring(0, i));
if (i == temp.length())
{
temp = "";
}
else
{
temp = temp.substring(i);
if (temp.substring(0, 1).equals("\n"))
{
temp = temp.substring(1);
}
}
}
}
catch (Exception e)
{
System.out.println("getSubsection:" + e);
}
temp6 = vector.size();
i_strHight = font.getHeight();
i_allStrHight = 320 - boxY - 30 - vector.size() * i_strHight;
return vector;
}
}
有些颜色的静态变量是另一个颜色管理类的,使用时替换成你想要的颜色即可。
此控件支持的触屏事件:文字域的拖拽,滚动条的拖拽,上下按钮的点击,滚动条底色区域的翻屏事件
此控件支持的按键事件:手机键盘上下按钮文字像素滚动。
附件有这个类的源码。