1 /* 2 * Copyright (C) 2008 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.calculator2; 18 19 import android.content.Context; 20 import android.util.AttributeSet; 21 import android.view.GestureDetector; 22 import android.view.MotionEvent; 23 import android.view.View; 24 import android.view.animation.AccelerateDecelerateInterpolator; 25 import android.view.animation.Animation; 26 import android.view.animation.Animation.AnimationListener; 27 import android.view.animation.TranslateAnimation; 28 import android.widget.FrameLayout; 29 30 class PanelSwitcher extends FrameLayout implements AnimationListener { 31 private static final int MAJOR_MOVE = 60; 32 private static final int ANIM_DURATION = 400; 33 34 private GestureDetector mGestureDetector; 35 private int mCurrentView; 36 private View mChildren[] = new View[0]; 37 38 private int mWidth; 39 private TranslateAnimation inLeft; 40 private TranslateAnimation outLeft; 41 42 private TranslateAnimation inRight; 43 private TranslateAnimation outRight; 44 45 private static final int LEFT = 1; 46 private static final int RIGHT = 2; 47 private int mPreviousMove; 48 49 public interface Listener { onChange()50 void onChange(); 51 } 52 53 private Listener mListener; 54 PanelSwitcher(Context context, AttributeSet attrs)55 public PanelSwitcher(Context context, AttributeSet attrs) { 56 super(context, attrs); 57 mCurrentView = 0; 58 mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { 59 @Override 60 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 61 float velocityY) { 62 int dx = (int) (e2.getX() - e1.getX()); 63 64 // don't accept the fling if it's too short 65 // as it may conflict with a button push 66 if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.abs(velocityY)) { 67 if (velocityX > 0) { 68 moveRight(); 69 } else { 70 moveLeft(); 71 } 72 return true; 73 } else { 74 return false; 75 } 76 } 77 }); 78 } 79 setListener(Listener listener)80 public void setListener(Listener listener) { 81 this.mListener = listener; 82 } 83 setCurrentIndex(int current)84 void setCurrentIndex(int current) { 85 boolean changed = mCurrentView != current; 86 mCurrentView = current; 87 updateCurrentView(); 88 if (changed && mListener != null) { 89 mListener.onChange(); 90 } 91 } 92 updateCurrentView()93 private void updateCurrentView() { 94 for (int i = mChildren.length-1; i >= 0 ; --i) { 95 mChildren[i].setVisibility(i==mCurrentView ? View.VISIBLE : View.GONE); 96 } 97 } 98 99 @Override onSizeChanged(int w, int h, int oldW, int oldH)100 public void onSizeChanged(int w, int h, int oldW, int oldH) { 101 mWidth = w; 102 inLeft = new TranslateAnimation(mWidth, 0, 0, 0); 103 inLeft.setAnimationListener(this); 104 outLeft = new TranslateAnimation(0, -mWidth, 0, 0); 105 inRight = new TranslateAnimation(-mWidth, 0, 0, 0); 106 inRight.setAnimationListener(this); 107 outRight = new TranslateAnimation(0, mWidth, 0, 0); 108 109 inLeft.setDuration(ANIM_DURATION); 110 outLeft.setDuration(ANIM_DURATION); 111 inRight.setDuration(ANIM_DURATION); 112 outRight.setDuration(ANIM_DURATION); 113 } 114 115 @Override onFinishInflate()116 protected void onFinishInflate() { 117 int count = getChildCount(); 118 mChildren = new View[count]; 119 for (int i = 0; i < count; ++i) { 120 mChildren[i] = getChildAt(i); 121 } 122 updateCurrentView(); 123 } 124 125 @Override onTouchEvent(MotionEvent event)126 public boolean onTouchEvent(MotionEvent event) { 127 mGestureDetector.onTouchEvent(event); 128 return true; 129 } 130 131 @Override onInterceptTouchEvent(MotionEvent event)132 public boolean onInterceptTouchEvent(MotionEvent event) { 133 return mGestureDetector.onTouchEvent(event); 134 } 135 moveLeft()136 void moveLeft() { 137 // <-- 138 if (mCurrentView < mChildren.length - 1 && mPreviousMove != LEFT) { 139 mChildren[mCurrentView+1].setVisibility(View.VISIBLE); 140 mChildren[mCurrentView+1].startAnimation(inLeft); 141 mChildren[mCurrentView].startAnimation(outLeft); 142 mChildren[mCurrentView].setVisibility(View.GONE); 143 144 mCurrentView++; 145 mPreviousMove = LEFT; 146 } 147 } 148 moveRight()149 void moveRight() { 150 // --> 151 if (mCurrentView > 0 && mPreviousMove != RIGHT) { 152 mChildren[mCurrentView-1].setVisibility(View.VISIBLE); 153 mChildren[mCurrentView-1].startAnimation(inRight); 154 mChildren[mCurrentView].startAnimation(outRight); 155 mChildren[mCurrentView].setVisibility(View.GONE); 156 157 mCurrentView--; 158 mPreviousMove = RIGHT; 159 } 160 } 161 getCurrentIndex()162 int getCurrentIndex() { 163 return mCurrentView; 164 } 165 166 @Override onAnimationRepeat(Animation animation)167 public void onAnimationRepeat(Animation animation) { 168 } 169 170 @Override onAnimationStart(Animation animation)171 public void onAnimationStart(Animation animation) { 172 } 173 174 @Override onAnimationEnd(Animation animation)175 public void onAnimationEnd(Animation animation) { 176 if (mListener != null) { 177 mListener.onChange(); 178 } 179 } 180 } 181