
这是API Demo中的一个例子,效果图如上,代码如下:
public class TouchPaint extends Activity{
/**Used as a pluse to gradually fade the contents of the window*/
private static final int FADE_MSG = 1;
/**Menu ID for the command to clear the window*/
private static final int CLEAR_ID = Menu.FIRST;
/**Menu ID for the command to toggle fading*/
private static final int FADE_ID = Menu.FIRST + 1;
/**How often to fade the contents of the window(in ms)*/
private static final int FADE_DELAY = 100;
/**The view responsible for drawing the window*/
private TouchPaintView mTouchPaintView;
/**Is fading mode enabled?*/
private boolean mFading;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mTouchPaintView = new TouchPaintView(this);
setContentView(mTouchPaintView);
mTouchPaintView.requestFocus();
mFading = savedInstanceState != null ? savedInstanceState.getBoolean("fading", true) : true;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
outState.putBoolean("fading", true);
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
if(mFading){
startFading();
}
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
stopFading();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, CLEAR_ID, 0, "Clear");
menu.add(0, FADE_ID, 0, "Fade");
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case CLEAR_ID:
mTouchPaintView.clear();
break;
case FADE_ID:
mFading = !mFading;
if(mFading){
stopFading();
}else {
startFading();
}
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
private void stopFading() {
mHandler.removeMessages(FADE_MSG);
}
private void startFading() {
mHandler.removeMessages(FADE_MSG);
mHandler.sendMessageDelayed(mHandler.obtainMessage(FADE_MSG), FADE_DELAY);
}
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
//Upon receiving the fade pulse,we have the view perform a
//fade and then enqueue a new message to pulse at the desired next time
case FADE_MSG:
mTouchPaintView.fade();
mHandler.sendEmptyMessageDelayed(FADE_MSG, FADE_DELAY);
break;
default:
break;
}
};
};
}
class TouchPaintView extends View{
private static final int FADE_ALPHA = 0x06;
private static final int MAX_FADE_STEPS = 256/FADE_ALPHA + 4;
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mPaint;
private Paint mFadePaint;
private Rect mRect = new Rect();
private boolean mCurDown;
private int mCurX;
private int mCurY;
private float mCurPressure;
private float mCurSize;
private int mCurWidth;
private int mFadeStepsIndex = MAX_FADE_STEPS;
public TouchPaintView(Context context) {
super(context);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setARGB(255, 255, 255, 255);
mFadePaint = new Paint();
mFadePaint.setDither(true);
mFadePaint.setARGB(FADE_ALPHA, 0, 0, 0);
}
public void clear() {
if (null != mCanvas) {
mPaint.setARGB(0xff, 0, 0, 0);
//Fill the entire canvas' bitmap (restricted to the current clip) with the specified paint.
//This is equivalent (but faster) to drawing an infinitely large rectangle with the specified paint.
mCanvas.drawPaint(mPaint);
invalidate();
mFadeStepsIndex = MAX_FADE_STEPS;
}
}
public void fade() {
if (null != mCanvas &&mFadeStepsIndex <= MAX_FADE_STEPS) {
mCanvas.drawPaint(mFadePaint);
invalidate();
mFadeStepsIndex++;
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
int curW = mBitmap != null ? mBitmap.getWidth() : 0;
int curH = mBitmap != null ? mBitmap.getHeight() : 0;
if (curW > w && curH > h) {
return;
}
if (curW < w) {
curW = w;
}
if (curH <h) {
curH = h;
}
Bitmap newBitmap = Bitmap.createBitmap(curW, curH, Bitmap.Config.RGB_565);
Canvas newCanvas = new Canvas();
//Specify a bitmap for the canvas to draw into.
newCanvas.setBitmap(newBitmap);
mBitmap = newBitmap;
mCanvas = newCanvas;
mFadeStepsIndex = MAX_FADE_STEPS;
}
@Override
protected void onDraw(Canvas canvas) {
if (null != mBitmap) {
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
mCurDown = (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE);
int N = event.getPointerCount();
for (int i = 0; i < N; i++) {
drawCircle(event.getHistoricalX(i), event.getHistoricalY(i),
event.getHistoricalPressure(i), event.getHistoricalSize(i));
}
drawCircle(event.getX(), event.getY(), event.getPressure(), event.getSize());
return true;
}
private void drawCircle(float x, float y, float pressure, float size){
mCurX = (int)x;
mCurY = (int)y;
mCurPressure = pressure;
mCurSize = size;
mCurWidth = (int)(mCurSize*(getWidth()/3));
if(mCurWidth < 1){
mCurWidth = 1;
}
if (mCurDown && null != mBitmap) {
int pressureLevel = (int)(mCurPressure * 255);
mPaint.setARGB(pressureLevel, 255, 255, 255);
mCanvas.drawCircle(mCurX, mCurY, mCurWidth, mPaint);
mRect.set(mCurX - mCurWidth -2, mCurY - mCurWidth -2,
mCurX + mCurWidth +2, mCurY + mCurWidth +2);
invalidate(mRect);
}
mFadeStepsIndex = 0;
}
}备注一:
理解这个程序的关键是明白Bitmap、Canvas、Paint之间的关系。
Bitmap mBitmap = Bitmap.createBitmap(curW, curH, Bitmap.Config.RGB_565);
Canvas mCanvas = new Canvas();
//Specify a bitmap for the canvas to draw into.
mCanvas.setBitmap(mBitmap);这里就可以理解为这个mCanvas和mBitmap绑定了,我以后用mCanvas画的东西都是画到mBitmap上的,然后不管之前是画的什么最后在onDraw的时候,我只要画出这个bitmap就可以了,即使画这个mBitmap的不是原来的mCanvas,因为我的mBitmap上已经有mCanvas画上的东西了。
@Override
protected void onDraw(Canvas canvas) {
if (null != mBitmap) {
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
}
}备注二:
在程序中我可以清空整个画布的内容,也可以设置是是否渐变的效果,这都是通过设置mCanvas的Paint来实现的
public void clear() {
if (null != mCanvas) {
mPaint.setARGB(0xff, 0, 0, 0);
//Fill the entire canvas' bitmap (restricted to the current clip) with the specified paint.
//This is equivalent (but faster) to drawing an infinitely large rectangle with the specified paint.
mCanvas.drawPaint(mPaint);
invalidate();
mFadeStepsIndex = MAX_FADE_STEPS;
}
}
public void fade() {
if (null != mCanvas &&mFadeStepsIndex <= MAX_FADE_STEPS) {
mCanvas.drawPaint(mFadePaint);
invalidate();
mFadeStepsIndex++;
}
}以上面的清空画布为例:当将画笔设置成透明黑色mPaint.setARGB(0xff, 0, 0, 0);,然后mCanvas.drawPaint(mPaint);,关键弄明白API中的解释:
//Fill the entire canvas' bitmap (restricted to the current clip) with the specified paint.
//This is equivalent (but faster) to drawing an infinitely large rectangle with the specified paint.
mCanvas.drawPaint(mPaint);
也就是将mCanvas的bitmap设置成指定画笔,下面的渐变效果也是这样设置的
本文介绍了一个利用触摸事件实现窗口淡入淡出效果的示例应用,包括如何使用视图类进行绘图、窗口清理及渐变模式切换。
513

被折叠的 条评论
为什么被折叠?



