Android Api Demos登顶之路(九十一)Graphics-->TouchPaint
来源:互联网 发布:html5网页小游戏源码 编辑:程序博客网 时间:2024/05/29 06:32
/* * 这个demon可以和Graphics->FingerPaint一起对比理解,只不过在本例中应用了多点触控, * 通过MotionEvent的一系列统方法检测触摸屏的压力和接触区域的大小等信息,以实现绘制出一些 * 特殊的效果。在本例中我们对原来的demon进行简化,只针对现在最常用的触摸屏手机进行演示。 */public class MainActivity extends Activity { private boolean isDrawSplat; private boolean fading; private static final int[] COLORS = new int[] { Color.BLACK, Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE, Color.MAGENTA, }; private static final int BACKGROUND_COLOR = Color.WHITE; private SampleView mView; private static final int MSG_FADE = 1; private static final int CLEAR_ID = Menu.FIRST; private static final int FADE_ID = Menu.FIRST+1; private static final int DRAWSPLAT_ID = Menu.FIRST+2; private static final int FADE_DELAY = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mView=new SampleView(this); setContentView(mView); mView.requestFocus(); if(savedInstanceState!=null){ fading=savedInstanceState.getBoolean("fading",true); }else{ fading=true; } } //创建菜单 @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0,CLEAR_ID,0,"Clear"); menu.add(0,FADE_ID,0,"Fade").setCheckable(true); menu.add(0,DRAWSPLAT_ID,0,"Drawsplat"); return super.onCreateOptionsMenu(menu); } @Override public boolean onPrepareOptionsMenu(Menu menu) { menu.findItem(FADE_ID).setChecked(fading); return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case CLEAR_ID: mView.clear(); return true; case FADE_ID: fading=!fading; if(fading){ startFading(); }else{ stopFading(); } return true; case DRAWSPLAT_ID: isDrawSplat=true; mView.invalidate(); return true; default: return super.onOptionsItemSelected(item); } } private Handler mHandler=new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case MSG_FADE: mView.fade(); sheduleFade(); break; default: super.handleMessage(msg); break; } }; }; private void stopFading() { mHandler.removeMessages(MSG_FADE); } private void startFading() { mHandler.removeMessages(MSG_FADE); sheduleFade(); } private void sheduleFade() { mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_FADE), FADE_DELAY); } @Override protected void onResume() { super.onResume(); if(fading){ startFading(); } } @Override protected void onPause() { super.onPause(); stopFading(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean("fading", fading); } private class SampleView extends View { private Paint mPaint; private Paint mFadePaint; private Bitmap mBitmap; private Canvas mCanvas; private Random mRandom = new Random(); private static final int SPLAT_VECTORS = 40; private static final int FADE_ALPHA = 0x010; private static final int MAX_FADE_STEPS = 256 / FADE_ALPHA + 14; private int mFadeSteps = MAX_FADE_STEPS; public SampleView(Context context) { super(context); setFocusable(true); setFocusableInTouchMode(true); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); int index = (int) (mRandom.nextFloat() * COLORS.length); mPaint.setColor(COLORS[index]); mFadePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mFadePaint.setColor(BACKGROUND_COLOR); mFadePaint.setAlpha(FADE_ALPHA); //System.out.println("MAX_FADE_STEPS:" + MAX_FADE_STEPS); } // 清除绘图板中的内容 public void clear() { if (mCanvas != null) { mPaint.setColor(BACKGROUND_COLOR); // 用背景色刷新画布 mCanvas.drawPaint(mPaint); invalidate(); mFadeSteps = MAX_FADE_STEPS; } } /* * 当选择fade菜单时将实现渐隐效果,通过一次次使用透明度为FADE_ALPHA颜色为背景色的画笔不断刷新 * 画布,共刷新MAX_FADE_STEPS次来实现逐渐褪色的效果 */ public void fade() { if (mCanvas != null && mFadeSteps < MAX_FADE_STEPS) { mCanvas.drawPaint(mFadePaint); invalidate(); mFadeSteps++; } } // 当屏幕尺寸变化时使画板占满屏幕 @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.ARGB_8888); Canvas newCanvas = new Canvas(); newCanvas.setBitmap(newBitmap); if (mBitmap != null) { newCanvas.drawBitmap(mBitmap, 0, 0, null); } mBitmap = newBitmap; mCanvas = newCanvas; // 初始化mFadeSteps mFadeSteps = MAX_FADE_STEPS; } @Override protected void onDraw(Canvas canvas) { if (mBitmap != null) { canvas.drawBitmap(mBitmap, 0, 0, null); } } @Override public boolean onTouchEvent(MotionEvent event) { // 返回执行的动作,例如按下触摸屏或者划动 int action = event.getActionMasked(); if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE || action == MotionEvent.ACTION_HOVER_MOVE) { // 当执行滑动动作时,返回可用的运动位置的数目。因为系统根据手指移动的距离来判定 // Move动作,该返回值即为即在判定为是一次滑动动作时在手指移动的距离内记录的点的 // 数量,我们可以遍历这些点并获取到这些点的信息。也可以理解为返回历史触摸区域的大小 int N = event.getHistorySize(); // System.out.println("N:"+N); // 获取触控点的个数 int p = event.getPointerCount(); for (int i = 0; i < N; i++) { for (int j = 0; j < p; j++) { paint(event.getHistoricalX(j, i), event.getHistoricalY( j, i), event.getHistoricalPressure(j, i), event.getHistoricalTouchMajor(j, i), event.getHistoricalTouchMinor(j, i), event.getHistoricalOrientation(j, i), event.getHistoricalAxisValue( MotionEvent.AXIS_DISTANCE, j, i), event.getHistoricalAxisValue( MotionEvent.AXIS_TILT, j, i)); } } for (int j = 0; j < p; j++) { paint(// 获取当前触点的坐标 event.getX(j), event.getY(j), // 获取当前触点的压力值 event.getPressure(j), // 获取接触区域(定义为一个椭圆形)长轴的长度 event.getTouchMajor(j), // 接触区域短轴的长度 event.getTouchMinor(j), // 以垂直方向为准接触区域按顺时针方向偏向的弧度值 event.getOrientation(j), // 获取动作事件的距离 event.getAxisValue(MotionEvent.AXIS_DISTANCE, j), // 获取动作事件的倾斜度 event.getAxisValue(MotionEvent.AXIS_TILT, j)); } } return true; } private void paint(float x, float y, float pressure, float major, float minor, float orientation, float distace, float tilt) { if (mBitmap != null) { // 如果接触区域的大小不可用,则使用默认大小 if (major <= 0 || minor <= 0) { major = minor = 16; } } if (isDrawSplat == true) { mPaint.setAlpha(64); drawSplat(mCanvas, x, y, orientation, distace, tilt, mPaint); }else{ mPaint.setAlpha(Math.min((int)(pressure * 128), 255)); drawOval(mCanvas, x, y, major, minor, orientation, mPaint); } mFadeSteps=0; invalidate(); } private RectF reusableOvalRect=new RectF(); private void drawOval(Canvas canvas, float x, float y, float major, float minor, float orientation, Paint paint) { canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.rotate((float) (orientation*180/Math.PI), x, y); reusableOvalRect.left=x-minor/2; reusableOvalRect.right=x+minor/2; reusableOvalRect.top=y-major/2; reusableOvalRect.bottom=y+major/2; canvas.drawOval(reusableOvalRect, mPaint); canvas.restore(); } // 定义具有扩散效果的画笔图案 private void drawSplat(Canvas canvas, float x, float y, float orientation, float distance, float tilt, Paint paint) { float z = distance * 2 + 10; // Calculate the center of the spray. float nx = (float) (Math.sin(orientation) * Math.sin(tilt)); float ny = (float) (-Math.cos(orientation) * Math.sin(tilt)); float nz = (float) Math.cos(tilt); if (nz < 0.05) { return; } float cd = z / nz; float cx = nx * cd; float cy = ny * cd; for (int i = 0; i < SPLAT_VECTORS; i++) { double direction = mRandom.nextDouble() * Math.PI * 2; double dispersion = mRandom.nextGaussian() * 0.2; double vx = Math.cos(direction) * dispersion; double vy = Math.sin(direction) * dispersion; double vz = 1; // Apply the nozzle tilt angle. double temp = vy; vy = temp * Math.cos(tilt) - vz * Math.sin(tilt); vz = temp * Math.sin(tilt) + vz * Math.cos(tilt); // Apply the nozzle orientation angle. temp = vx; vx = temp * Math.cos(orientation) - vy * Math.sin(orientation); vy = temp * Math.sin(orientation) + vy * Math.cos(orientation); // Determine where the paint will hit the surface. if (vz < 0.05) { continue; } float pd = (float) (z / vz); float px = (float) (vx * pd); float py = (float) (vy * pd); // Throw some paint at this location, relative to the center of // the spray. mCanvas.drawCircle(x + px - cx, y + py - cy, 1.0f, paint); } } }}
0 0
- Android Api Demos登顶之路(九十一)Graphics-->TouchPaint
- Android Api Demos登顶之路(六十五)Graphics-->AlphaBitmap
- Android Api Demos登顶之路(六十七)Graphics-->Arcs
- Android Api Demos登顶之路(六十八)Graphics-->DecodeBitmap
- Android Api Demos登顶之路(七十一)Graphics-->Cliping
- Android Api Demos登顶之路(七十三)Graphics-->Compass
- Android Api Demos登顶之路(七十四)Graphics-->CreateBitmap
- Android Api Demos登顶之路(七十五)Graphics-->GradientDrawable
- Android Api Demos登顶之路(七十六)Graphics-->ShapeDrawable
- Android Api Demos登顶之路(七十七)Graphics-->FingerPaint
- Android Api Demos登顶之路(七十八)Graphics-->MeansureText
- Android Api Demos登顶之路(七十九)Graphics-->PathEffects
- Android Api Demos登顶之路(八十)Graphics-->PathFillTypes
- Android Api Demos登顶之路(八十一)Graphics-->Patterns
- Android Api Demos登顶之路(八十二)Graphics-->Picture
- Android Api Demos登顶之路(八十三)Graphics-->Point
- Android Api Demos登顶之路(八十四)Graphics-->PolyToPoly
- Android Api Demos登顶之路(八十五)Graphics-->PurgeableBitmap
- GoF 种设计模式
- 浅谈方法重写 super
- 面试10大算法汇总以及常见题目解答
- spring mvc拦截器和<mvc:annotation-driven />的详解
- gradle--第十五章 使用文件3
- Android Api Demos登顶之路(九十一)Graphics-->TouchPaint
- 23种经典设计模式UML类图汇总
- 文件编辑器vim--vim使用技巧
- null的数据类型
- JVM内存管理的机制
- LibSVM在x64windows下的安装与初次使用
- cvWaitKey函数说明
- Redis大冒险
- 1154 能量项链