1596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang/* 2596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * Copyright (C) 2014 The Android Open Source Project 3596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * 4596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * Licensed under the Apache License, Version 2.0 (the "License"); 5596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * you may not use this file except in compliance with the License. 6596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * You may obtain a copy of the License at 7596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * 8596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * http://www.apache.org/licenses/LICENSE-2.0 9596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * 10596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * Unless required by applicable law or agreed to in writing, software 11596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * distributed under the License is distributed on an "AS IS" BASIS, 12596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * See the License for the specific language governing permissions and 14596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang * limitations under the License. 15596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang */ 16596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 17596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhangpackage com.android.deskclock; 18596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 19596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhangimport android.content.Context; 20596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhangimport android.support.v4.view.ViewPager; 21596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhangimport android.util.AttributeSet; 22596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhangimport android.view.MotionEvent; 23596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhangimport android.view.View; 24596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 25596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhangpublic class VerticalViewPager extends ViewPager { 26596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 27596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang public VerticalViewPager(Context context) { 2883ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout this(context, null); 29596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang } 30596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 31596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang public VerticalViewPager(Context context, AttributeSet attrs) { 32596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang super(context, attrs); 33596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang init(); 34596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang } 35596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 3666db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux /** 3766db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux * @return {@code false} since a vertical view pager can never be scrolled horizontally 3866db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux */ 3966db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux @Override 4066db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux public boolean canScrollHorizontally(int direction) { 4166db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux return false; 4266db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux } 4366db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux 4466db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux /** 4566db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux * @return {@code true} iff a normal view pager would support horizontal scrolling at this time 4666db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux */ 4766db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux @Override 4866db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux public boolean canScrollVertically(int direction) { 4966db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux return super.canScrollHorizontally(direction); 5066db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux } 5166db5cbb9bb60749c18056813a29288005df1ffbJames Lemieux 52596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang private void init() { 53596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang // Make page transit vertical 5483ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout setPageTransformer(true, new VerticalPageTransformer()); 55596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang // Get rid of the overscroll drawing that happens on the left and right (the ripple) 56596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang setOverScrollMode(View.OVER_SCROLL_NEVER); 57596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang } 58596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 59596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang @Override 6087f4b763f206cca755e7ce03baf3ef33c33be29eSean Stout public boolean onInterceptTouchEvent(MotionEvent ev) { 6183ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout final boolean toIntercept = super.onInterceptTouchEvent(flipXY(ev)); 6283ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout // Return MotionEvent to normal 6383ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout flipXY(ev); 6483ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout return toIntercept; 6587f4b763f206cca755e7ce03baf3ef33c33be29eSean Stout } 6687f4b763f206cca755e7ce03baf3ef33c33be29eSean Stout 6787f4b763f206cca755e7ce03baf3ef33c33be29eSean Stout @Override 68596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang public boolean onTouchEvent(MotionEvent ev) { 6983ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout final boolean toHandle = super.onTouchEvent(flipXY(ev)); 7083ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout // Return MotionEvent to normal 7183ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout flipXY(ev); 7283ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout return toHandle; 73596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang } 74596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 7583ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout private MotionEvent flipXY(MotionEvent ev) { 7683ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout final float width = getWidth(); 7783ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout final float height = getHeight(); 7883ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout 7983ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout final float x = (ev.getY() / height) * width; 8083ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout final float y = (ev.getX() / width) * height; 8183ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout 8283ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout ev.setLocation(x, y); 8383ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout 8483ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout return ev; 85596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang } 86596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang 8783ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout private static final class VerticalPageTransformer implements ViewPager.PageTransformer { 8883ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout @Override 8983ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout public void transformPage(View view, float position) { 9083ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout final int pageWidth = view.getWidth(); 9183ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout final int pageHeight = view.getHeight(); 9283ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout if (position < -1) { 9383ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout // This page is way off-screen to the left. 9483ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout view.setAlpha(0); 9583ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout } else if (position <= 1) { 9683ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout view.setAlpha(1); 9783ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout // Counteract the default slide transition 9883ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout view.setTranslationX(pageWidth * -position); 9983ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout // set Y position to swipe in from top 10083ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout float yPosition = position * pageHeight; 10183ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout view.setTranslationY(yPosition); 10283ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout } else { 10383ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout // This page is way off-screen to the right. 10483ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout view.setAlpha(0); 10583ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout } 10683ebe1bc7a3c3b592e6acbd475dc701bf5f8c4a6Sean Stout } 107596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang } 108596d8dc712f18192354f44b1ee9c91a09296bd82rachelzhang} 109