public class MyApplication extends Application {
private String someVariable;
public String getSomeVariable() {
return someVariable;
}
public void setSomeVariable(String someVariable) {
this.someVariable = someVariable;
}
}
<application android:name="MyApplication" android:icon="@drawable/icon" android:label="@string/app_name">
// set
((MyApplication) this.getApplication()).setSomeVariable("foo");
// get
String s = ((MyApplication) this.getApplication()).getSomeVariable();
org.kalmeo.util.worker
接触这个类是在Kuix的Demo中的进度条,系统提供两种实现,一种是用Worker添加WorkerTask的,一种是自己用线程,实质都是一样的,Worker是一个线程,处理自己的任务队列,为每个任务启动一个线程,只不过线程没执行一次默认修改60ms.
public static final Worker instance = new Worker();Worker会自动创建一个自己的实例,Kuix 在initialize()中会启动这个线程.
KuixCanvas中(264行)会启动一个任务,用它来处理key和mouse事件
workerTask = new WorkerTask() {...}
另外,Worker还有另外一个作用(473行),Worker.instance.isCurrentThread()用来判断当前运行线程是否是最后一个启用的线程,以此判断当前线程是否属于当前窗口.有点难以理解,我的理解是J2ME用Thread管理所有线程,而Kuix则试图用Worker.instance管理自己的线程.
/**
* Revalidate (and repaint) the desktop as soon as possible. If the current
* thread is the worker thread the task is done immedialty else it is
* deferred to the next frame.
*/
public void revalidateAsSoonAsPossible() {
if (!Worker.instance.isCurrentThread()) {
revalidateNextFrame();
} else {
forceRevalidate();
forceRepaint();
}
}
/**
* @return <code>true</code> if the current Thread is the {@link Worker} thread
*/
public boolean isCurrentThread() {
return (Thread.currentThread() == thread);
}
KuixMidlet甚至用它来管理Midlet的生命周期,
/* (non-Javadoc)
* @see org.kalmeo.kuix.core.KuixInitializer#destroyImpl()
*/
public void destroyImpl() {
if (Worker.instance.isRunning()) {
Worker.instance.pushTask(new WorkerTask() {
/* (non-Javadoc)
* @see org.kalmeo.util.worker.WorkerTask#run()
*/
public boolean run() {
destroyApp(false);
notifyDestroyed();
return true;
}
});
} else {
destroyApp(false);
notifyDestroyed();
}
}
picturebox用它来展示动画(348行)
PopupBox用它来关闭splash的弹出窗口,duration是启动时设置的弹出时间.
/* (non-Javadoc)
* @see org.kalmeo.kuix.widget.Widget#onAdded(org.kalmeo.kuix.widget.Widget)
*/
protected void onAdded(Widget parent) {
if (duration != -1) {
Worker.instance.pushTask(new WorkerTask() {
private long startTime = System.currentTimeMillis();
/* (non-Javadoc)
* @see org.kalmeo.kuix.core.worker.WorkerTask#execute()
*/
public boolean run() {
if ((System.currentTimeMillis() - startTime) > duration) {
remove();
return true;
}
return false;
}
});
}
}
Text用它来,似乎是做走马灯效果.(205行)
TextArea用它在修改文本后,调用onChange方法,不能理解,为什么不直接调用?延时?
/* (non-Javadoc)
* @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable)
*/
public void commandAction(Command command, Displayable displayable) {
if (command == validateCommand) {
String textBoxString = textBox.getString();
boolean changed = textBoxString != null && !textBoxString.equals(getText());
setText(textBoxString);
if (changed && onChange != null) {
Worker.instance.pushTask(new WorkerTask() {
public boolean run() {
Kuix.callActionMethod(Kuix.parseMethod(onChange, TextArea.this));
return true;
}
});
}
}
Display.getDisplay(Kuix.getCanvas().getInitializer().getMIDlet()).setCurrent(Kuix.getCanvas());
}
TextField用来弹出tip
首先呢 我们重写两个按钮事件 一个图片button 一个用文字button
package com.pocketjourney.view;
import com.pocketjourney.tutorials.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Button;
public class TextOnlyButton extends Button {
private int notFocusedTextColor, focusedTextColor, pressedTextColor;
private boolean isTextPressed;
public TextOnlyButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public TextOnlyButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public TextOnlyButton(Context context) {
super(context);
throw new RuntimeException("Valid colors (e.g. #ffffff) must be passed to this class via the XML parameters: pj:textColorNotFocused & pj:textColorFocused.");
}
private void init(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.TextOnlyButton);
String textColorNotFocused = a.getString(R.styleable.TextOnlyButton_textColorNotFocused);
String textColorFocused = a.getString(R.styleable.TextOnlyButton_textColorFocused);
String textColorPressed = a.getString(R.styleable.TextOnlyButton_textColorPressed);
if (textColorNotFocused != null && textColorFocused != null && textColorPressed != null ) {
notFocusedTextColor = a.getColor(R.styleable.TextOnlyButton_textColorNotFocused, 0xFF000000);
focusedTextColor = a.getColor(R.styleable.TextOnlyButton_textColorFocused, 0xFF000000);
pressedTextColor = a.getColor(R.styleable.TextOnlyButton_textColorPressed, 0xFF000000);
} else {
throw new RuntimeException("Valid colors (e.g. #ffffff) must be passed to this class via the XML parameters: pj:textColorNotFocused, pj:textColorFocused, & pj:textColorPressed.");
}
}
public void onDrawBackground(Canvas canvas) {
// Override this method & do nothing. This prevents the parent.onDrawBackground(canvas)
// from drawing the button's background.
}
/**
* Capture mouse press events to update text state.
*/
@Override
public boolean onTouchEvent(MotionEvent event)
{
Log.d("TextOnlyButton",event.getAction()+"");
if (event.getAction() == MotionEvent.ACTION_DOWN) {
isTextPressed = true;
// Request a redraw to update the text color
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
isTextPressed = false;
// Requesting focus doesn't work for some reason. If you find a solution to setting
// the focus, please let me know so I can update the tutorial
requestFocus();
// Request a redraw to update the text color
invalidate();
}
return super.onTouchEvent(event);
}
@Override
public void onDraw(Canvas canvas) {
if (isTextPressed) {
setTextColor(pressedTextColor);
}else if (isFocused()) {
// Since this Button now has no background. We adjust the text color to indicate focus.
setTextColor(focusedTextColor);
} else {
setTextColor(notFocusedTextColor);
}
super.onDraw(canvas);
}
}
package com.pocketjourney.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageButton;
import com.pocketjourney.tutorials.R;
public class ImageOnlyButton extends ImageButton {
int imageResourceNotFocused, imageResourceFocused, imageResourcePressed;
private boolean isButtonPressed;
public ImageOnlyButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public ImageOnlyButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public ImageOnlyButton(Context context) {
super(context);
throw new RuntimeException("Valid image resource IDs must be passed to this class via the XML parameters: pj:resourceNotFocused & pj:resourceFocused.");
}
private void init(AttributeSet attrs)
{
TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.ImageOnlyButton);
String notFocusedColorStr = a.getString(R.styleable.ImageOnlyButton_resourceNotFocused);
String focusedColorStr = a.getString(R.styleable.ImageOnlyButton_resourceFocused);
String pressedColorStr = a.getString(R.styleable.ImageOnlyButton_resourcePressed);
if (notFocusedColorStr != null && focusedColorStr != null && pressedColorStr != null) {
imageResourceFocused = a.getResourceId(R.styleable.ImageOnlyButton_resourceFocused, -1);
imageResourceNotFocused = a.getResourceId(R.styleable.ImageOnlyButton_resourceNotFocused, -1);
imageResourcePressed = a.getResourceId(R.styleable.ImageOnlyButton_resourcePressed, -1);
}
if (imageResourceFocused == -1 || imageResourceNotFocused == -1 || imageResourcePressed == -1) {
throw new RuntimeException("Valid image resource IDs must be passed to this class via the XML parameters: pj:resourceNotFocused, pj:resourceFocused, & pj:resourcePressed.");
}
}
/**
* Capture mouse press events to update text state.
*/
@Override
public boolean onTouchEvent(MotionEvent event)
{
Log.d("TextOnlyButton",event.getAction()+"");
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Request a redraw to update the button color
isButtonPressed = true;
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
isButtonPressed = false;
// Requesting focus doesn't work for some reason. If you find a solution to setting
// the focus, please let me know so I can update the tutorial
// requestFocus();
// Request a redraw to update the button color
invalidate();
}
return super.onTouchEvent(event);
}
@Override
public void onDraw(Canvas canvas) {
if (isButtonPressed) {
setImageResource(imageResourcePressed);
}else if (isFocused()) {
// Since this Button now has no background. We must swap out the image to display
// one that indicates it has focus.
setImageResource(imageResourceFocused);
} else {
setImageResource(imageResourceNotFocused);
}
super.onDraw(canvas);
}
}
这里最主要的是init(AttributeSet attrs) 方法,这里呢引用了资源
也就是自定义的属性,这个属性就是和我们平常一样的android:text一样。首先我们要在这个属性中定义我们添加的资源是什么 这里是整形 也就是id,然后通过上述方法引用 以便我们可以在ondraw里面画出我们的资源。当然text和图片button两个init方法不同 有一个多了一个if的判断 一个没有,多了的一个说明 这个属性是必须设定的 如果不设定就会出错。如果缺少if语句判定那么默认这个属性是可以没有的。
<com.pocketjourney.view.TextOnlyButton
android:id="@+id/text_only_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25px"
android:text="Text Button"
android:background="@drawable/empty"
pj:textColorNotFocused="@drawable/white"
pj:textColorFocused="@drawable/android_orange"
pj:textColorPressed="@drawable/android_yellow"/>
<com.pocketjourney.view.ImageOnlyButton
android:id="@+id/image_only_button"
android:src="/blog_article/@drawable/help/index.html"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15px"
android:background="@drawable/empty"
pj:resourceNotFocused="@drawable/help"
pj:resourceFocused="@drawable/help_focused"
pj:resourcePressed="@drawable/help_pressed"/>
然后呢就可以在主xml中引用我们自写的属性了,这里要注意亮点
第一个 android:background="@drawable/empty"
这个属性我们设置了一个啥都没有的图片以便我们自定义背景
pj是自定一的命名空间是必不可缺少的。
源文件可以从福建里面下载。