1 /* 2 * Copyright (C) 2022 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 18 package com.android.wallpaper.picker.customization.ui.section 19 20 import android.content.Context 21 import android.util.AttributeSet 22 import android.view.MotionEvent 23 import android.view.ViewConfiguration 24 import com.android.wallpaper.picker.SectionView 25 import kotlin.math.pow 26 import kotlin.math.sqrt 27 28 class ScreenPreviewView( 29 context: Context, 30 attrs: AttributeSet?, 31 ) : 32 SectionView( 33 context, 34 attrs, 35 ) { 36 37 private var downX = 0f 38 private var downY = 0f 39 onInterceptTouchEventnull40 override fun onInterceptTouchEvent(event: MotionEvent): Boolean { 41 if (event.actionMasked == MotionEvent.ACTION_DOWN) { 42 downX = event.x 43 downY = event.y 44 } 45 46 // We want to intercept clicks so the Carousel MotionLayout child doesn't prevent users from 47 // clicking on the screen preview. 48 if (isClick(event, downX, downY)) { 49 return performClick() 50 } 51 52 return super.onInterceptTouchEvent(event) 53 } 54 55 companion object { isClicknull56 private fun isClick(event: MotionEvent, downX: Float, downY: Float): Boolean { 57 return when { 58 // It's not a click if the event is not an UP action (though it may become one 59 // later, when/if an UP is received). 60 event.actionMasked != MotionEvent.ACTION_UP -> false 61 // It's not a click if too much time has passed between the down and the current 62 // event. 63 gestureElapsedTime(event) > ViewConfiguration.getTapTimeout() -> false 64 // It's not a click if the touch traveled too far. 65 distanceMoved(event, downX, downY) > ViewConfiguration.getTouchSlop() -> false 66 // Otherwise, this is a click! 67 else -> true 68 } 69 } 70 71 /** 72 * Returns the distance that the pointer traveled in the touch gesture the given event is 73 * part of. 74 */ distanceMovednull75 private fun distanceMoved(event: MotionEvent, downX: Float, downY: Float): Float { 76 val deltaX = event.x - downX 77 val deltaY = event.y - downY 78 return sqrt(deltaX.pow(2) + deltaY.pow(2)) 79 } 80 81 /** 82 * Returns the elapsed time since the touch gesture the given event is part of has begun. 83 */ gestureElapsedTimenull84 private fun gestureElapsedTime(event: MotionEvent): Long { 85 return event.eventTime - event.downTime 86 } 87 } 88 } 89