John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2016 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.prefabulated.touchlatency; |
| 18 | |
Ian Lake | c694d04 | 2017-07-10 10:44:59 -0700 | [diff] [blame] | 19 | import android.app.Activity; |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 20 | import android.content.Context; |
| 21 | import android.graphics.Canvas; |
| 22 | import android.graphics.Color; |
| 23 | import android.graphics.Paint; |
| 24 | import android.os.CountDownTimer; |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 25 | import android.os.Bundle; |
| 26 | import android.text.method.Touch; |
| 27 | import android.util.AttributeSet; |
| 28 | import android.util.Log; |
| 29 | import android.view.Menu; |
| 30 | import android.view.MenuItem; |
| 31 | import android.view.MotionEvent; |
| 32 | import android.view.View; |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 33 | import android.os.Trace; |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 34 | |
| 35 | import java.util.ArrayList; |
| 36 | import java.util.Collections; |
| 37 | |
| 38 | class TouchLatencyView extends View implements View.OnTouchListener { |
| 39 | private static final String LOG_TAG = "TouchLatency"; |
| 40 | private static final int BACKGROUND_COLOR = 0xFF400080; |
| 41 | private static final int INNER_RADIUS = 70; |
| 42 | private static final int BALL_RADIUS = 100; |
| 43 | |
| 44 | public TouchLatencyView(Context context, AttributeSet attrs) { |
| 45 | super(context, attrs); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 46 | Trace.beginSection("TouchLatencyView constructor"); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 47 | setOnTouchListener(this); |
| 48 | setWillNotDraw(false); |
| 49 | mBluePaint = new Paint(Paint.ANTI_ALIAS_FLAG); |
| 50 | mBluePaint.setColor(0xFF0000FF); |
| 51 | mBluePaint.setStyle(Paint.Style.FILL); |
| 52 | mGreenPaint = new Paint(Paint.ANTI_ALIAS_FLAG); |
| 53 | mGreenPaint.setColor(0xFF00FF00); |
| 54 | mGreenPaint.setStyle(Paint.Style.FILL); |
| 55 | mYellowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); |
| 56 | mYellowPaint.setColor(0xFFFFFF00); |
| 57 | mYellowPaint.setStyle(Paint.Style.FILL); |
| 58 | mRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); |
| 59 | mRedPaint.setColor(0xFFFF0000); |
| 60 | mRedPaint.setStyle(Paint.Style.FILL); |
| 61 | |
| 62 | mTouching = false; |
| 63 | |
| 64 | mBallX = 100.0f; |
| 65 | mBallY = 100.0f; |
| 66 | mVelocityX = 7.0f; |
| 67 | mVelocityY = 7.0f; |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 68 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | @Override |
| 72 | public boolean onTouch(View view, MotionEvent event) { |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 73 | Trace.beginSection("TouchLatencyView onTouch"); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 74 | int action = event.getActionMasked(); |
| 75 | if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) { |
| 76 | mTouching = true; |
| 77 | invalidate(); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 78 | |
| 79 | mTouchX = event.getX(); |
| 80 | mTouchY = event.getY(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 81 | } else if (action == MotionEvent.ACTION_UP) { |
| 82 | mTouching = false; |
| 83 | invalidate(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 84 | } |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 85 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 86 | return true; |
| 87 | } |
| 88 | |
| 89 | private void drawTouch(Canvas canvas) { |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 90 | Trace.beginSection("TouchLatencyView drawTouch"); |
| 91 | |
| 92 | try { |
| 93 | if (!mTouching) { |
| 94 | Log.d(LOG_TAG, "Filling background"); |
| 95 | canvas.drawColor(BACKGROUND_COLOR); |
| 96 | return; |
| 97 | } |
| 98 | |
| 99 | float deltaX = (mTouchX - mLastDrawnX); |
| 100 | float deltaY = (mTouchY - mLastDrawnY); |
| 101 | float scaleFactor = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY) * 1.5f; |
| 102 | |
| 103 | mLastDrawnX = mTouchX; |
| 104 | mLastDrawnY = mTouchY; |
| 105 | |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 106 | canvas.drawColor(BACKGROUND_COLOR); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 107 | canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + 3 * scaleFactor, mRedPaint); |
| 108 | canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + 2 * scaleFactor, mYellowPaint); |
| 109 | canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS + scaleFactor, mGreenPaint); |
| 110 | canvas.drawCircle(mTouchX, mTouchY, INNER_RADIUS, mBluePaint); |
| 111 | } finally { |
| 112 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 113 | } |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | private void drawBall(Canvas canvas) { |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 117 | Trace.beginSection("TouchLatencyView drawBall"); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 118 | int width = canvas.getWidth(); |
| 119 | int height = canvas.getHeight(); |
| 120 | |
| 121 | // Update position |
| 122 | mBallX += mVelocityX; |
| 123 | mBallY += mVelocityY; |
| 124 | |
| 125 | // Clamp and change velocity if necessary |
| 126 | float left = mBallX - BALL_RADIUS; |
| 127 | if (left < 0) { |
| 128 | left = 0; |
| 129 | mVelocityX *= -1; |
| 130 | } |
| 131 | |
| 132 | float top = mBallY - BALL_RADIUS; |
| 133 | if (top < 0) { |
| 134 | top = 0; |
| 135 | mVelocityY *= -1; |
| 136 | } |
| 137 | |
| 138 | float right = mBallX + BALL_RADIUS; |
| 139 | if (right > width) { |
| 140 | right = width; |
| 141 | mVelocityX *= -1; |
| 142 | } |
| 143 | |
| 144 | float bottom = mBallY + BALL_RADIUS; |
| 145 | if (bottom > height) { |
| 146 | bottom = height; |
| 147 | mVelocityY *= -1; |
| 148 | } |
| 149 | |
| 150 | // Draw the ball |
| 151 | canvas.drawColor(BACKGROUND_COLOR); |
| 152 | canvas.drawOval(left, top, right, bottom, mYellowPaint); |
| 153 | invalidate(); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 154 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | @Override |
| 158 | protected void onDraw(Canvas canvas) { |
| 159 | super.onDraw(canvas); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 160 | Trace.beginSection("TouchLatencyView onDraw"); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 161 | if (mMode == 0) { |
| 162 | drawTouch(canvas); |
| 163 | } else { |
| 164 | drawBall(canvas); |
| 165 | } |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 166 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | public void changeMode(MenuItem item) { |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 170 | Trace.beginSection("TouchLatencyView changeMode"); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 171 | final int NUM_MODES = 2; |
| 172 | final String modes[] = {"Touch", "Ball"}; |
| 173 | mMode = (mMode + 1) % NUM_MODES; |
| 174 | invalidate(); |
| 175 | item.setTitle(modes[mMode]); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 176 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | private Paint mBluePaint, mGreenPaint, mYellowPaint, mRedPaint; |
| 180 | private int mMode; |
| 181 | |
| 182 | private boolean mTouching; |
| 183 | private float mTouchX, mTouchY; |
| 184 | private float mLastDrawnX, mLastDrawnY; |
| 185 | |
| 186 | private float mBallX, mBallY; |
| 187 | private float mVelocityX, mVelocityY; |
| 188 | } |
| 189 | |
Ian Lake | c694d04 | 2017-07-10 10:44:59 -0700 | [diff] [blame] | 190 | public class TouchLatencyActivity extends Activity { |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 191 | |
| 192 | @Override |
| 193 | protected void onCreate(Bundle savedInstanceState) { |
| 194 | super.onCreate(savedInstanceState); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 195 | Trace.beginSection("TouchLatencyActivity onCreate"); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 196 | setContentView(R.layout.activity_touch_latency); |
| 197 | |
Alan Viverette | 51efddb | 2017-04-05 10:00:01 -0400 | [diff] [blame] | 198 | mTouchView = findViewById(R.id.canvasView); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 199 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 200 | } |
| 201 | |
| 202 | |
| 203 | @Override |
| 204 | public boolean onCreateOptionsMenu(Menu menu) { |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 205 | Trace.beginSection("TouchLatencyActivity onCreateOptionsMenu"); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 206 | // Inflate the menu; this adds items to the action bar if it is present. |
| 207 | getMenuInflater().inflate(R.menu.menu_touch_latency, menu); |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 208 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 209 | return true; |
| 210 | } |
| 211 | |
| 212 | @Override |
| 213 | public boolean onOptionsItemSelected(MenuItem item) { |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 214 | Trace.beginSection("TouchLatencyActivity onOptionsItemSelected"); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 215 | // Handle action bar item clicks here. The action bar will |
| 216 | // automatically handle clicks on the Home/Up button, so long |
| 217 | // as you specify a parent activity in AndroidManifest.xml. |
| 218 | int id = item.getItemId(); |
| 219 | |
| 220 | //noinspection SimplifiableIfStatement |
| 221 | if (id == R.id.action_settings) { |
| 222 | mTouchView.changeMode(item); |
| 223 | } |
| 224 | |
Carmen Jackson | 286cfb1 | 2018-06-28 15:15:44 -0700 | [diff] [blame] | 225 | Trace.endSection(); |
John Reck | d136ce9 | 2016-08-08 12:25:59 -0700 | [diff] [blame] | 226 | return super.onOptionsItemSelected(item); |
| 227 | } |
| 228 | |
| 229 | private TouchLatencyView mTouchView; |
| 230 | } |