1 /* 2 * Copyright (C) 2017 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.googlecode.android_scripting; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.view.GestureDetector; 23 import android.view.MotionEvent; 24 import android.view.View; 25 import android.view.GestureDetector.SimpleOnGestureListener; 26 import android.view.View.OnTouchListener; 27 28 import com.googlecode.android_scripting.activity.InterpreterManager; 29 import com.googlecode.android_scripting.activity.LogcatViewer; 30 import com.googlecode.android_scripting.activity.ScriptManager; 31 import com.googlecode.android_scripting.activity.TriggerManager; 32 33 import java.util.ArrayList; 34 import java.util.HashMap; 35 import java.util.Iterator; 36 import java.util.List; 37 import java.util.Map; 38 39 public class ActivityFlinger { 40 41 private static final int SWIPE_MIN_DISTANCE = 120; 42 private static final int SWIPE_MAX_OFF_PATH = 100; 43 private static final int SWIPE_THRESHOLD_VELOCITY = 200; 44 45 private static class ActivityTransition { 46 Class<? extends Activity> mLeft; 47 Class<? extends Activity> mRight; 48 49 public ActivityTransition(Class<? extends Activity> left, Class<? extends Activity> right) { 50 mLeft = left; 51 mRight = right; 52 } 53 } 54 55 private static Map<Class<?>, ActivityTransition> mActivityTransitions = 56 new HashMap<Class<?>, ActivityTransition>(); 57 58 private ActivityFlinger() { 59 // Utility class. 60 } 61 62 static { 63 List<Class<? extends Activity>> entries = new ArrayList<Class<? extends Activity>>(); 64 entries.add(ScriptManager.class); 65 entries.add(InterpreterManager.class); 66 entries.add(TriggerManager.class); 67 entries.add(LogcatViewer.class); 68 69 Class<? extends Activity> left = null; 70 Class<? extends Activity> current = null; 71 Class<? extends Activity> right = null; 72 73 for (Iterator<Class<? extends Activity>> it = entries.iterator(); it.hasNext() 74 || current != null;) { 75 if (current == null) { 76 current = it.next(); 77 } 78 if (it.hasNext()) { 79 right = it.next(); 80 } else { 81 right = null; 82 } 83 mActivityTransitions.put(current, new ActivityTransition(left, right)); 84 left = current; 85 current = right; 86 } 87 } 88 89 public static void attachView(View view, Context context) { 90 final LeftRightFlingListener mListener = new LeftRightFlingListener(); 91 final GestureDetector mGestureDetector = new GestureDetector(mListener); 92 ActivityTransition transition = mActivityTransitions.get(context.getClass()); 93 if (transition.mLeft != null) { 94 mListener.mLeftRunnable = new StartActivityRunnable(context, transition.mLeft); 95 } 96 if (transition.mRight != null) { 97 mListener.mRightRunnable = new StartActivityRunnable(context, transition.mRight); 98 } 99 view.setOnTouchListener(new OnTouchListener() { 100 @Override 101 public boolean onTouch(View v, MotionEvent event) { 102 return mGestureDetector.onTouchEvent(event); 103 } 104 }); 105 } 106 107 private static class StartActivityRunnable implements Runnable { 108 109 private final Context mContext; 110 private final Class<?> mActivityClass; 111 112 private StartActivityRunnable(Context context, Class<?> activity) { 113 mContext = context; 114 mActivityClass = activity; 115 } 116 117 @Override 118 public void run() { 119 Intent intent = new Intent(mContext, mActivityClass); 120 mContext.startActivity(intent); 121 } 122 } 123 124 private static class LeftRightFlingListener extends SimpleOnGestureListener { 125 Runnable mLeftRunnable; 126 Runnable mRightRunnable; 127 128 @Override 129 public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { 130 if (Math.abs(event1.getY() - event2.getY()) > SWIPE_MAX_OFF_PATH) { 131 return false; 132 } 133 if (event1.getX() - event2.getX() > SWIPE_MIN_DISTANCE 134 && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 135 if (mRightRunnable != null) { 136 mRightRunnable.run(); 137 } 138 } else if (event2.getX() - event1.getX() > SWIPE_MIN_DISTANCE 139 && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 140 if (mLeftRunnable != null) { 141 mLeftRunnable.run(); 142 } 143 } else { 144 return super.onFling(event1, event2, velocityX, velocityY); 145 } 146 return true; 147 } 148 } 149 } 150