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 }