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.android.systemui.screenshot; 18 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.graphics.Canvas; 22 import android.graphics.Color; 23 import android.graphics.Paint; 24 import android.graphics.Point; 25 import android.graphics.PorterDuff; 26 import android.graphics.PorterDuffXfermode; 27 import android.graphics.Rect; 28 import android.util.AttributeSet; 29 import android.view.MotionEvent; 30 import android.view.View; 31 32 import java.util.function.Consumer; 33 34 /** 35 * Draws a selection rectangle while taking screenshot 36 */ 37 public class ScreenshotSelectorView extends View { 38 private Point mStartPoint; 39 private Rect mSelectionRect; 40 private final Paint mPaintSelection, mPaintBackground; 41 42 private Consumer<Rect> mOnScreenshotSelected; 43 ScreenshotSelectorView(Context context)44 public ScreenshotSelectorView(Context context) { 45 this(context, null); 46 } 47 ScreenshotSelectorView(Context context, @Nullable AttributeSet attrs)48 public ScreenshotSelectorView(Context context, @Nullable AttributeSet attrs) { 49 super(context, attrs); 50 mPaintBackground = new Paint(Color.BLACK); 51 mPaintBackground.setAlpha(160); 52 mPaintSelection = new Paint(Color.TRANSPARENT); 53 mPaintSelection.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 54 55 setOnTouchListener((v, event) -> { 56 switch (event.getAction()) { 57 case MotionEvent.ACTION_DOWN: 58 startSelection((int) event.getX(), (int) event.getY()); 59 return true; 60 case MotionEvent.ACTION_MOVE: 61 updateSelection((int) event.getX(), (int) event.getY()); 62 return true; 63 case MotionEvent.ACTION_UP: 64 setVisibility(View.GONE); 65 final Rect rect = getSelectionRect(); 66 if (mOnScreenshotSelected != null 67 && rect != null 68 && rect.width() != 0 && rect.height() != 0) { 69 mOnScreenshotSelected.accept(rect); 70 } 71 stopSelection(); 72 return true; 73 } 74 return false; 75 }); 76 } 77 78 @Override draw(Canvas canvas)79 public void draw(Canvas canvas) { 80 canvas.drawRect(mLeft, mTop, mRight, mBottom, mPaintBackground); 81 if (mSelectionRect != null) { 82 canvas.drawRect(mSelectionRect, mPaintSelection); 83 } 84 } 85 setOnScreenshotSelected(Consumer<Rect> onScreenshotSelected)86 void setOnScreenshotSelected(Consumer<Rect> onScreenshotSelected) { 87 mOnScreenshotSelected = onScreenshotSelected; 88 } 89 stop()90 void stop() { 91 if (getSelectionRect() != null) { 92 stopSelection(); 93 } 94 } 95 startSelection(int x, int y)96 private void startSelection(int x, int y) { 97 mStartPoint = new Point(x, y); 98 mSelectionRect = new Rect(x, y, x, y); 99 } 100 updateSelection(int x, int y)101 private void updateSelection(int x, int y) { 102 if (mSelectionRect != null) { 103 mSelectionRect.left = Math.min(mStartPoint.x, x); 104 mSelectionRect.right = Math.max(mStartPoint.x, x); 105 mSelectionRect.top = Math.min(mStartPoint.y, y); 106 mSelectionRect.bottom = Math.max(mStartPoint.y, y); 107 invalidate(); 108 } 109 } 110 getSelectionRect()111 private Rect getSelectionRect() { 112 return mSelectionRect; 113 } 114 stopSelection()115 private void stopSelection() { 116 mStartPoint = null; 117 mSelectionRect = null; 118 } 119 } 120