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