編輯:關於Android編程
下面實現如何通過應用層支持多點觸控操作,對於常規的控件觸控操實現onTouchEvent()方法來處理。同時對onTouchEvent方法的參數MotionEvent進行一些了解。
下面會用兩個應用示例來初步學習一下Android中的多點觸控。
本示例是在SurfaceView中利用Canvas來展示用戶的多點觸控,不過核心技術還是一個常見的方法:onTouchEvent(MotionEvent event)
MotionEvent有以下幾個方法需要大家注意一下,不過了是一些常見的方法,如果你onTouchEvent使用得多的話。
event.getAction() // 獲取觸控動作比如ACTION_DOWN
event.getPointerCount(); // 獲取觸控點的數量,比如2則可能是兩個手指同時按壓屏幕
event.getPointerId(nID); // 對於每個觸控的點的細節,我們可以通過一個循環執行getPointerId方法獲取索引
event.getX(nID); // 獲取第nID個觸控點的x位置
event.getY(nID); // 獲取第nID個點觸控的y位置
event.getPressure(nID); // LCD可以感應出用戶的手指壓力,當然具體的級別由驅動和物理硬件決定的
event.getDownTime() // 按下開始時間
event.getEventTime() // 事件結束時間
event.getEventTime()-event.getDownTime()); // 總共按下時花費時間
public class MTView extends SurfaceView implements SurfaceHolder.Callback { private static final int MAX_TOUCHPOINTS = 10; private static final String START_TEXT = "請隨便觸摸屏幕進行測試"; private Paint textPaint = new Paint(); private Paint touchPaints[] = new Paint[MAX_TOUCHPOINTS]; private int colors[] = new int[MAX_TOUCHPOINTS]; private int width, height; private float scale = 1.0f; public MTView(Context context) { super(context); SurfaceHolder holder = getHolder(); holder.addCallback(this); setFocusable(true); // 確保我們的View能獲得輸入焦點 setFocusableInTouchMode(true); // 確保能接收到觸屏事件 init(); } private void init() { // 初始化10個不同顏色的畫筆 textPaint.setColor(Color.WHITE); colors[0] = Color.BLUE; colors[1] = Color.RED; colors[2] = Color.GREEN; colors[3] = Color.YELLOW; colors[4] = Color.CYAN; colors[5] = Color.MAGENTA; colors[6] = Color.DKGRAY; colors[7] = Color.WHITE; colors[8] = Color.LTGRAY; colors[9] = Color.GRAY; for (int i = 0; i < MAX_TOUCHPOINTS; i++) { touchPaints[i] = new Paint(); touchPaints[i].setColor(colors[i]); } } /** * 處理觸屏事件 */ @Override public boolean onTouchEvent(MotionEvent event) { // 獲得屏幕觸點數量 int pointerCount = event.getPointerCount(); if (pointerCount > MAX_TOUCHPOINTS) { pointerCount = MAX_TOUCHPOINTS; } // 鎖定Canvas,開始進行相應的界面處理 Canvas c = getHolder().lockCanvas(); if (c != null) { c.drawColor(Color.BLACK); if (event.getAction() == MotionEvent.ACTION_UP) { // 當手離開屏幕時,清屏 } else { // 在每一個觸點上繪制一個十字和坐標信息 for (int i = 0; i < pointerCount; i++) { int id = event.getPointerId(i); int x = (int) event.getX(i); int y = (int) event.getY(i); drawCrosshairsAndText(x, y, touchPaints[id], i, id, c); } // 在每一個觸點上繪制一個圓 for (int i = 0; i < pointerCount; i++) { int id = event.getPointerId(i); int x = (int) event.getX(i); int y = (int) event.getY(i); drawCircle(x, y, touchPaints[id], c); } } // 畫完後,unlock getHolder().unlockCanvasAndPost(c); } return true; } /** * 畫十字及坐標信息 * * @param x * @param y * @param paint * @param ptr * @param id * @param c */ private void drawCrosshairsAndText(int x, int y, Paint paint, int ptr, int id, Canvas c) { c.drawLine(0, y, width, y, paint); c.drawLine(x, 0, x, height, paint); int textY = (int) ((15 + 20 * ptr) * scale); c.drawText("x" + ptr + "=" + x, 10 * scale, textY, textPaint); c.drawText("y" + ptr + "=" + y, 70 * scale, textY, textPaint); c.drawText("id" + ptr + "=" + id, width - 55 * scale, textY, textPaint); } /** * 畫圓 * * @param x * @param y * @param paint * @param c */ private void drawCircle(int x, int y, Paint paint, Canvas c) { c.drawCircle(x, y, 40 * scale, paint); } /** * 進入程序時背景畫成黑色,然後把START_TEXT寫到屏幕 */ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { this.width = width; this.height = height; if (width > height) { this.scale = width / 480f; } else { this.scale = height / 480f; } textPaint.setTextSize(14 * scale); Canvas c = getHolder().lockCanvas(); if (c != null) { c.drawColor(Color.BLACK); float tWidth = textPaint.measureText(START_TEXT); c.drawText(START_TEXT, width / 2 - tWidth / 2, height / 2, textPaint); getHolder().unlockCanvasAndPost(c); } } public void surfaceCreated(SurfaceHolder holder) { } public void surfaceDestroyed(SurfaceHolder holder) { } }
使用上也是so easy:
setContentView(new MTView(this));
通過多點觸屏放大或縮小圖像 beforeLenght用來保存前一時間兩點之間的距離 afterLenght用來保存當前時間兩點之間的距離
public void scaleWithFinger(MotionEvent event) { float moveX = event.getX(1) - event.getX(0); float moveY = event.getY(1) - event.getY(0); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: beforeLenght = (float) Math.sqrt((moveX * moveX) + (moveY * moveY)); break; case MotionEvent.ACTION_MOVE: // 得到兩個點之間的長度 afterLenght = (float) Math.sqrt((moveX * moveX) + (moveY * moveY)); float gapLenght = afterLenght - beforeLenght; if (gapLenght == 0) { break; } // 如果當前時間兩點距離大於前一時間兩點距離,則傳0,否則傳1 if (gapLenght > 0) { this.setScale(scale, 0); } else { this.setScale(scale, 1); } beforeLenght = afterLenght; break; } } }
讓圖片跟隨手指觸屏的位置移動 beforeX、Y是用來保存前一位置的坐標 afterX、Y是用來保存當前位置的坐標。它們的差值就是ImageView各坐標的增加或減少值。
public void moveWithFinger(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: beforeX = event.getX(); beforeY = event.getY(); break; case MotionEvent.ACTION_MOVE: afterX = event.getX(); afterY = event.getY(); this.setLocation((int) (afterX - beforeX), (int) (afterY - beforeY)); beforeX = afterX; beforeY = afterY; break; case MotionEvent.ACTION_UP: break; } }
用來放大縮小ImageView 因為圖片是填充ImageView的,所以也就有放大縮小圖片的效果 flag為0是放大圖片,為1是縮小圖片
private void setScale(float temp, int flag) { if (flag == 0) { this.setFrame(this.getLeft() - (int) (temp * this.getWidth()), this.getTop() - (int) (temp * this.getHeight()), this.getRight() + (int) (temp * this.getWidth()), this.getBottom() + (int) (temp * this.getHeight())); } else { this.setFrame(this.getLeft() + (int) (temp * this.getWidth()), this.getTop() + (int) (temp * this.getHeight()), this.getRight() - (int) (temp * this.getWidth()), this.getBottom() - (int) (temp * this.getHeight())); } }
onTouchEvent事件則如下:
public boolean onTouchEvent(MotionEvent event) { if (inView(imageView, event)) { if (event.getPointerCount() == 2) { imageView.scaleWithFinger(event); } else if (event.getPointerCount() == 1) { imageView.moveWithFinger(event); } } return true; }
http://download.csdn.net/detail/u013761665/8719349
在編程中經常會遇到數據庫的操作,而Android系統內置了SQLite,它是一款輕型數據庫,遵守事務ACID的關系型數據庫管理系統,它占用的資源非常低,能夠支持Windo
前段時間剛接觸過android手機開發,對它的事件傳播機制不是很了解,雖然網上也查了相關的資料,但是總覺得理解模模糊糊,似是而非,於是自己就寫個小demo測試了一下。總算
Android 4.0 系統定義了一系列的高效導航方式 (Effective Navigation), 主要包括標簽、下拉列表、以及向上和返回等, 本文介紹如何用 Mon
前一段時間更新了Android Studio,目前最新的穩定版是1.4。更新之後沒看到什麼大的變化。今天去逛官方的更新日志,發現1.4版本著實增加了不少使用的