1 /* 2 * Copyright (C) 2021 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.car.rotaryplayground; 18 19 import static com.android.car.ui.utils.RotaryConstants.BOTTOM_BOUND_OFFSET_FOR_NUDGE; 20 import static com.android.car.ui.utils.RotaryConstants.LEFT_BOUND_OFFSET_FOR_NUDGE; 21 import static com.android.car.ui.utils.RotaryConstants.RIGHT_BOUND_OFFSET_FOR_NUDGE; 22 import static com.android.car.ui.utils.RotaryConstants.TOP_BOUND_OFFSET_FOR_NUDGE; 23 24 import android.content.Context; 25 import android.graphics.Canvas; 26 import android.graphics.Color; 27 import android.graphics.Paint; 28 import android.os.Bundle; 29 import android.util.AttributeSet; 30 import android.view.SurfaceView; 31 import android.view.accessibility.AccessibilityNodeInfo; 32 33 import androidx.annotation.Nullable; 34 35 /** 36 * A SurfaceView that allows to set its perceived bounds for the purposes of finding the nudge 37 * target. 38 */ 39 public class CustomSurfaceView extends SurfaceView { 40 41 /** 42 * The offset (in pixels) of the SurfaceView's bounds for the purposes of finding the nudge 43 * target. 44 */ 45 private int mLeftOffset; 46 private int mRightOffset; 47 private int mTopOffset; 48 private int mBottomOffset; 49 CustomSurfaceView(Context context)50 public CustomSurfaceView(Context context) { 51 super(context); 52 } 53 CustomSurfaceView(Context context, @Nullable AttributeSet attrs)54 public CustomSurfaceView(Context context, @Nullable AttributeSet attrs) { 55 super(context, attrs); 56 } 57 CustomSurfaceView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)58 public CustomSurfaceView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 59 super(context, attrs, defStyleAttr); 60 } 61 CustomSurfaceView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)62 public CustomSurfaceView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, 63 int defStyleRes) { 64 super(context, attrs, defStyleAttr, defStyleRes); 65 } 66 67 /** 68 * Sets the offset (in pixels) of the SurfaceView's bounds. 69 * <p> 70 * It only affects the perceived bounds for the purposes of finding the nudge target. 71 * This doesn't affect the view's bounds. This method should only be used when this view 72 * overlaps other focusable views so that nudge targeting is ambiguous. 73 */ setBoundsOffset(int left, int top, int right, int bottom)74 public void setBoundsOffset(int left, int top, int right, int bottom) { 75 mLeftOffset = left; 76 mTopOffset = top; 77 mRightOffset = right; 78 mBottomOffset = bottom; 79 } 80 81 @Override onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)82 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 83 super.onInitializeAccessibilityNodeInfo(info); 84 if (mLeftOffset == 0 && mTopOffset == 0 && mRightOffset == 0 && mBottomOffset == 0) { 85 return; 86 } 87 Bundle bundle = info.getExtras(); 88 bundle.putInt(LEFT_BOUND_OFFSET_FOR_NUDGE, mLeftOffset); 89 bundle.putInt(RIGHT_BOUND_OFFSET_FOR_NUDGE, mRightOffset); 90 bundle.putInt(TOP_BOUND_OFFSET_FOR_NUDGE, mTopOffset); 91 bundle.putInt(BOTTOM_BOUND_OFFSET_FOR_NUDGE, mBottomOffset); 92 } 93 94 @Override onDraw(Canvas canvas)95 protected void onDraw(Canvas canvas) { 96 super.onDraw(canvas); 97 98 // Draw a text for demonstration purpose. 99 Paint paint = new Paint(); 100 paint.setColor(Color.BLACK); 101 paint.setTextSize(40); 102 canvas.drawText("SurfaceView", 400, 200, paint); 103 } 104 } 105