1 /*
2  * Copyright (C) 2020 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.deskclock
18 
19 import android.content.Context
20 import android.util.AttributeSet
21 import android.view.MotionEvent
22 import android.view.View
23 import androidx.viewpager.widget.ViewPager
24 
25 class VerticalViewPager @JvmOverloads constructor(
26     context: Context,
27     attrs: AttributeSet? = null
28 ) : ViewPager(context, attrs) {
29     init {
30         init()
31     }
32 
33     /**
34      * @return `false` since a vertical view pager can never be scrolled horizontally
35      */
canScrollHorizontallynull36     override fun canScrollHorizontally(direction: Int): Boolean = false
37 
38     /**
39      * @return `true` iff a normal view pager would support horizontal scrolling at this time
40      */
41     override fun canScrollVertically(direction: Int): Boolean {
42         return super.canScrollHorizontally(direction)
43     }
44 
initnull45     private fun init() {
46         // Make page transit vertical
47         setPageTransformer(true, VerticalPageTransformer())
48         // Get rid of the overscroll drawing that happens on the left and right (the ripple)
49         setOverScrollMode(View.OVER_SCROLL_NEVER)
50     }
51 
onInterceptTouchEventnull52     override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
53         val toIntercept: Boolean = super.onInterceptTouchEvent(flipXY(ev))
54         // Return MotionEvent to normal
55         flipXY(ev)
56         return toIntercept
57     }
58 
onTouchEventnull59     override fun onTouchEvent(ev: MotionEvent): Boolean {
60         val toHandle: Boolean = super.onTouchEvent(flipXY(ev))
61         // Return MotionEvent to normal
62         flipXY(ev)
63         return toHandle
64     }
65 
flipXYnull66     private fun flipXY(ev: MotionEvent): MotionEvent {
67         val width: Float = width.toFloat()
68         val height: Float = height.toFloat()
69 
70         val x = ev.y / height * width
71         val y = ev.x / width * height
72 
73         ev.setLocation(x, y)
74 
75         return ev
76     }
77 
78     private class VerticalPageTransformer : ViewPager.PageTransformer {
transformPagenull79         override fun transformPage(view: View, position: Float) {
80             val pageWidth = view.width
81             val pageHeight = view.height
82             when {
83                 position < -1 -> {
84                     // This page is way off-screen to the left.
85                     view.alpha = 0f
86                 }
87                 position <= 1 -> {
88                     view.alpha = 1f
89                     // Counteract the default slide transition
90                     view.translationX = pageWidth * -position
91                     // set Y position to swipe in from top
92                     val yPosition = position * pageHeight
93                     view.translationY = yPosition
94                 }
95                 else -> {
96                     // This page is way off-screen to the right.
97                     view.alpha = 0f
98                 }
99             }
100         }
101     }
102 }