ZoomButtonsController.java revision ba87e3e6c985e7175152993b5efcc7dd2f0e1c93
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Projectimport android.app.AlertDialog; 20b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Projectimport android.app.Dialog; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 22b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Projectimport android.content.ContentResolver; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 26b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Projectimport android.content.SharedPreferences; 27ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectimport android.graphics.Canvas; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 32b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Projectimport android.os.SystemClock; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 34ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectimport android.util.Log; 35ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectimport android.view.GestureDetector; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewConfiguration; 42c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.view.ViewGroup; 43ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectimport android.view.ViewParent; 44ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectimport android.view.ViewRoot; 45b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Projectimport android.view.Window; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View.OnClickListener; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager.LayoutParams; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 50ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project/* 51ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Implementation notes: 52ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * - The zoom controls are displayed in their own window. 53ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * (Easier for the client and better performance) 54ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * - This window is not touchable, and by default is not focusable. 55ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * - To make the buttons clickable, it attaches a OnTouchListener to the owner 56ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * view and does the hit detection locally. 57ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * - When it is focusable, it forwards uninteresting events to the owner view's 58ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * view hierarchy. 59ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 61ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * The {@link ZoomButtonsController} handles showing and hiding the zoom 62ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * controls relative to an owner view. It also gives the client access to the 63ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * zoom controls container, allowing for additional accessory buttons to be 64ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * shown in the zoom controls window. 65ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * <p> 66ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Typical usage involves the client using the {@link GestureDetector} to 67ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * forward events from 68ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * {@link GestureDetector.OnDoubleTapListener#onDoubleTapEvent(MotionEvent)} to 69ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * {@link #handleDoubleTapEvent(MotionEvent)}. Also, whenever the owner cannot 70ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * be zoomed further, the client should update 71ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * {@link #setZoomInEnabled(boolean)} and {@link #setZoomOutEnabled(boolean)}. 72ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * <p> 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If you are using this with a custom View, please call 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setVisible(boolean) setVisible(false)} from the 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link View#onDetachedFromWindow}. 76ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 79ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectpublic class ZoomButtonsController implements View.OnTouchListener { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "ZoomButtonsController"; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ZOOM_CONTROLS_TIMEOUT = 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int) ViewConfiguration.getZoomControlsTimeout(); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ZOOM_CONTROLS_TOUCH_PADDING = 20; 87ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private int mTouchPaddingScaledSq; 88c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private WindowManager mWindowManager; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 93b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * The view that is being zoomed by this zoom controller. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View mOwnerView; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 98ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * The location of the owner view on the screen. This is recalculated 99b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * each time the zoom controller is shown. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 101ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private int[] mOwnerViewRawLocation = new int[2]; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The container that is added as a window. 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private FrameLayout mContainer; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LayoutParams mContainerLayoutParams; 108ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private int[] mContainerRawLocation = new int[2]; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ZoomControls mControls; 111c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The view (or null) that should receive touch events. This will get set if 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the touch down hits the container. It will be reset on the touch up. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View mTouchTargetView; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The {@link #mTouchTargetView}'s location in window, set on touch down. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 120ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private int[] mTouchTargetWindowLocation = new int[2]; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 122b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * If the zoom controller is dismissed but the user is still in a touch 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * interaction, we set this to true. This will ignore all touch events until 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * up/cancel, and then set the owner's touch listener to null. 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mReleaseTouchListenerOnUp; 127c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 128ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 129ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Whether we are currently in the double-tap gesture, with the second tap 130ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * still being performed (i.e., we're waiting for the second tap's touch up). 131ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 132b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project private boolean mIsSecondTapDown; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 134ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** Whether the container has been added to the window manager. */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsVisible; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Rect mTempRect = new Rect(); 138ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private int[] mTempIntArray = new int[2]; 139ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnZoomListener mCallback; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 143ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * In 1.0, the ZoomControls were to be added to the UI by the client of 144ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * WebView, MapView, etc. We didn't want apps to break, so we return a dummy 145ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * view in place now. 146ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 147ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private InvisibleView mDummyZoomControls; 148ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 149ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When showing the zoom, we add the view as a new window. However, there is 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * logic that needs to know the size of the zoom which is determined after 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it's laid out. Therefore, we must post this logic onto the UI thread so 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it will be exceuted AFTER the layout. This is the logic. 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Runnable mPostedVisibleInitializer; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private IntentFilter mConfigurationChangedFilter = 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 160ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 161ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Needed to reposition the zoom controls after configuration changes. 162ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private BroadcastReceiver mConfigurationChangedReceiver = new BroadcastReceiver() { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mIsVisible) return; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(MSG_POST_CONFIGURATION_CHANGED); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendEmptyMessage(MSG_POST_CONFIGURATION_CHANGED); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 173b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /** 174b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * The setting name that tracks whether we've shown the zoom tutorial. 175b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project */ 176b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project private static final String SETTING_NAME_SHOWN_TUTORIAL = "shown_zoom_tutorial"; 177b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project private static Dialog sTutorialDialog; 178b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** When configuration changes, this is called after the UI thread is idle. */ 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_POST_CONFIGURATION_CHANGED = 2; 181b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /** Used to delay the zoom controller dismissal. */ 182b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project private static final int MSG_DISMISS_ZOOM_CONTROLS = 3; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If setVisible(true) is called and the owner view's window token is null, 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we delay the setVisible(true) call until it is not null. 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_POST_SET_VISIBLE = 4; 188c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Handler mHandler = new Handler() { 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_POST_CONFIGURATION_CHANGED: 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onPostConfigurationChanged(); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 197b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project case MSG_DISMISS_ZOOM_CONTROLS: 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setVisible(false); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 200c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_POST_SET_VISIBLE: 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOwnerView.getWindowToken() == null) { 203ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // Doh, it is still null, just ignore the set visible call 204ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.e(TAG, 205b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project "Cannot make the zoom controller visible if the owner view is " + 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "not attached to a window."); 207ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } else { 208ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project setVisible(true); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 216ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 217ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Constructor for the {@link ZoomButtonsController}. 218ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 219ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param ownerView The view that is being zoomed by the zoom controls. The 220ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * zoom controls will be displayed aligned with this view. 221ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 222ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public ZoomButtonsController(View ownerView) { 223ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContext = ownerView.getContext(); 224ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnerView = ownerView; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 227ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mTouchPaddingScaledSq = (int) 228ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project (ZOOM_CONTROLS_TOUCH_PADDING * mContext.getResources().getDisplayMetrics().density); 229ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mTouchPaddingScaledSq *= mTouchPaddingScaledSq; 230ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContainer = createContainer(); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 233c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 234ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 235ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Whether to enable the zoom in control. 236ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 237ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param enabled Whether to enable the zoom in control. 238ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 239b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public void setZoomInEnabled(boolean enabled) { 240b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mControls.setIsZoomInEnabled(enabled); 241b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 242c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 243ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 244ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Whether to enable the zoom out control. 245ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 246ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param enabled Whether to enable the zoom out control. 247ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 248b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public void setZoomOutEnabled(boolean enabled) { 249b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mControls.setIsZoomOutEnabled(enabled); 250b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 251c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 252ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 253ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Sets the delay between zoom callbacks as the user holds a zoom button. 254ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 255ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param speed The delay in milliseconds between zoom callbacks. 256ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 257b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public void setZoomSpeed(long speed) { 258b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mControls.setZoomSpeed(speed); 259b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 260c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private FrameLayout createContainer() { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 263ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // Controls are positioned BOTTOM | CENTER with respect to the owner view. 264ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project lp.gravity = Gravity.TOP | Gravity.LEFT; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE | 266b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project LayoutParams.FLAG_NOT_FOCUSABLE | 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutParams.FLAG_LAYOUT_NO_LIMITS; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.height = LayoutParams.WRAP_CONTENT; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.width = LayoutParams.FILL_PARENT; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.type = LayoutParams.TYPE_APPLICATION_PANEL; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.format = PixelFormat.TRANSPARENT; 272c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContainerLayoutParams = lp; 274c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 275ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project FrameLayout container = new Container(mContext); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project container.setLayoutParams(lp); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project container.setMeasureAllChildren(true); 278c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutInflater inflater = (LayoutInflater) mContext 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 281c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project inflater.inflate(com.android.internal.R.layout.zoom_container, container); 282c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mControls.setOnZoomInClickListener(new OnClickListener() { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(View v) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) mCallback.onZoom(true); 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mControls.setOnZoomOutClickListener(new OnClickListener() { 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(View v) { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) mCallback.onZoom(false); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return container; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 299c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 300ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 301ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Sets the {@link OnZoomListener} listener that receives callbacks to zoom. 302ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 303ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param listener The listener that will be told to zoom. 304ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 305ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public void setOnZoomListener(OnZoomListener listener) { 306ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mCallback = listener; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 310ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Sets whether the zoom controls should be focusable. If the controls are 311ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * focusable, then trackball and arrow key interactions are possible. 312ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Otherwise, only touch interactions are possible. 313ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 314ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param focusable Whether the zoom controls should be focusable. 315ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFocusable(boolean focusable) { 317ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int oldFlags = mContainerLayoutParams.flags; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (focusable) { 319c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project mContainerLayoutParams.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContainerLayoutParams.flags |= LayoutParams.FLAG_NOT_FOCUSABLE; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 323c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 324ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if ((mContainerLayoutParams.flags != oldFlags) && mIsVisible) { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 330ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Whether the zoom controls are visible to the user. 331ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 332ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @return Whether the zoom controls are visible to the user. 333ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isVisible() { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mIsVisible; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 338ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 339ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Sets whether the zoom controls should be visible to the user. 340ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 341ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param visible Whether the zoom controls should be visible to the user. 342ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVisible(boolean visible) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (visible) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOwnerView.getWindowToken() == null) { 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We need a window token to show ourselves, maybe the owner's 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * window hasn't been created yet but it will have been by the 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * time the looper is idle, so post the setVisible(true) call. 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mHandler.hasMessages(MSG_POST_SET_VISIBLE)) { 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendEmptyMessage(MSG_POST_SET_VISIBLE); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 357c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsVisible == visible) { 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsVisible = visible; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (visible) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContainerLayoutParams.token == null) { 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContainerLayoutParams.token = mOwnerView.getWindowToken(); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindowManager.addView(mContainer, mContainerLayoutParams); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPostedVisibleInitializer == null) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPostedVisibleInitializer = new Runnable() { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project refreshPositioningVariables(); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) { 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCallback.onVisibilityChanged(true); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.post(mPostedVisibleInitializer); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Handle configuration changes when visible 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(mConfigurationChangedReceiver, mConfigurationChangedFilter); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Steal touches events from the owner 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnerView.setOnTouchListener(this); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReleaseTouchListenerOnUp = false; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't want to steal any more touches 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTouchTargetView != null) { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We are still stealing the touch events for this touch 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sequence, so release the touch listener later 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReleaseTouchListenerOnUp = true; 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnerView.setOnTouchListener(null); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No longer care about configuration changes 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.unregisterReceiver(mConfigurationChangedReceiver); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindowManager.removeView(mContainer); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeCallbacks(mPostedVisibleInitializer); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCallback.onVisibilityChanged(false); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 418ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Gets the container that is the parent of the zoom controls. 419ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * <p> 420ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * The client can add other views to this container to link them with the 421ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * zoom controls. 422ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 423ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @return The container of the zoom controls. It will be a layout that 424ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * respects the gravity of a child's layout parameters. 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 426c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public ViewGroup getContainer() { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mContainer; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void dismissControlsDelayed(int delay) { 431b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS); 432b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Should be called by the client for each event belonging to the second tap 437ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * (the down, move, up, and/or cancel events). 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param event The event belonging to the second tap. 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether the event was consumed. 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean handleDoubleTapEvent(MotionEvent event) { 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int action = event.getAction(); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action == MotionEvent.ACTION_DOWN) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int x = (int) event.getX(); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int y = (int) event.getY(); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /* 450b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * This class will consume all events in the second tap (down, 451b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * move(s), up). But, the owner already got the second tap's down, 452b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * so cancel that. Do this before setVisible, since that call 453b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * will set us as a touch listener. 454b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project */ 455b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project MotionEvent cancelEvent = MotionEvent.obtain(event.getDownTime(), 456b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project SystemClock.elapsedRealtime(), 457b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project MotionEvent.ACTION_CANCEL, 0, 0, 0); 458b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mOwnerView.dispatchTouchEvent(cancelEvent); 459b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project cancelEvent.recycle(); 460b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setVisible(true); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project centerPoint(x, y); 463b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mIsSecondTapDown = true; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void refreshPositioningVariables() { 470ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // Position the zoom controls on the bottom of the owner view. 471ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int ownerHeight = mOwnerView.getHeight(); 472ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int ownerWidth = mOwnerView.getWidth(); 473ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // The gap between the top of the owner and the top of the container 474ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int containerOwnerYOffset = ownerHeight - mContainer.getHeight(); 475ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Calculate the owner view's bounds 477ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mOwnerView.getLocationOnScreen(mOwnerViewRawLocation); 478ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerRawLocation[0] = mOwnerViewRawLocation[0]; 479ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerRawLocation[1] = mOwnerViewRawLocation[1] + containerOwnerYOffset; 480ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 481ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int[] ownerViewWindowLoc = mTempIntArray; 482ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mOwnerView.getLocationInWindow(ownerViewWindowLoc); 483ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 484ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // lp.x and lp.y should be relative to the owner's window top-left 485ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerLayoutParams.x = ownerViewWindowLoc[0]; 486ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerLayoutParams.width = ownerWidth; 487ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerLayoutParams.y = ownerViewWindowLoc[1] + containerOwnerYOffset; 488ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (mIsVisible) { 489ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); 490ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 491ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Centers the point (in owner view's coordinates). 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void centerPoint(int x, int y) { 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) { 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCallback.onCenter(x, y); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 503ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /* This will only be called when the container has focus. */ 504ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private boolean onContainerKey(KeyEvent event) { 505ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int keyCode = event.getKeyCode(); 506ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isInterestingKey(keyCode)) { 507ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 508ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_BACK) { 509ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project setVisible(false); 510ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } else { 511ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 512ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 513ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 514ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // Let the container handle the key 515ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return false; 516ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 517ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } else { 518ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 519ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project ViewRoot viewRoot = getOwnerViewRoot(); 520ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (viewRoot != null) { 521ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project viewRoot.dispatchKey(event); 522ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 523ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 524ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // We gave the key to the owner, don't let the container handle this key 525ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return true; 526ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 527b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 528b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 529ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private boolean isInterestingKey(int keyCode) { 530ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project switch (keyCode) { 531ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 532ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_UP: 533ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_DOWN: 534ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_LEFT: 535ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_RIGHT: 536ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_ENTER: 537ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_BACK: 538ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return true; 539ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project default: 540ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return false; 541ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 542ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 543ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 544ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private ViewRoot getOwnerViewRoot() { 545ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project View rootViewOfOwner = mOwnerView.getRootView(); 546ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (rootViewOfOwner == null) { 547ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return null; 548ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 549ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 550ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project ViewParent parentOfRootView = rootViewOfOwner.getParent(); 551ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (parentOfRootView instanceof ViewRoot) { 552ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return (ViewRoot) parentOfRootView; 553ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } else { 554ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return null; 555ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 556ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 557ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 558ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 559ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @hide The ZoomButtonsController implements the OnTouchListener, but this 560ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * does not need to be shown in its public API. 561ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onTouch(View v, MotionEvent event) { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int action = event.getAction(); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 565b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // Consume all events during the second-tap interaction (down, move, up/cancel) 566b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project boolean consumeEvent = mIsSecondTapDown; 567b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if ((action == MotionEvent.ACTION_UP) || (action == MotionEvent.ACTION_CANCEL)) { 568b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // The second tap can no longer be down 569b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mIsSecondTapDown = false; 570b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 571c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mReleaseTouchListenerOnUp) { 573b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // The controls were dismissed but we need to throw away all events until the up 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnerView.setOnTouchListener(null); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTouchTargetView(null); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReleaseTouchListenerOnUp = false; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Eat this event 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 585c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View targetView = mTouchTargetView; 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (action) { 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_DOWN: 590ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project targetView = findViewForTouch((int) event.getRawX(), (int) event.getRawY()); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTouchTargetView(targetView); 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_UP: 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_CANCEL: 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTouchTargetView(null); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (targetView != null) { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The upperleft corner of the target view in raw coordinates 602ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int targetViewRawX = mContainerRawLocation[0] + mTouchTargetWindowLocation[0]; 603ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int targetViewRawY = mContainerRawLocation[1] + mTouchTargetWindowLocation[1]; 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MotionEvent containerEvent = MotionEvent.obtain(event); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Convert the motion event into the target view's coordinates (from 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // owner view's coordinates) 608ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project containerEvent.offsetLocation(mOwnerViewRawLocation[0] - targetViewRawX, 609ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mOwnerViewRawLocation[1] - targetViewRawY); 610ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /* Disallow negative coordinates (which can occur due to 611ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * ZOOM_CONTROLS_TOUCH_PADDING) */ 612ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (containerEvent.getX() < 0) { 613ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project containerEvent.offsetLocation(-containerEvent.getX(), 0); 614ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 615ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (containerEvent.getY() < 0) { 616ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project containerEvent.offsetLocation(0, -containerEvent.getY()); 617ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean retValue = targetView.dispatchTouchEvent(containerEvent); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project containerEvent.recycle(); 620b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project return retValue || consumeEvent; 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 623b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project return consumeEvent; 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setTouchTargetView(View view) { 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTouchTargetView = view; 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 630ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project view.getLocationInWindow(mTouchTargetWindowLocation); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the View that should receive a touch at the given coordinates. 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rawX The raw X. 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rawY The raw Y. 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that should receive the touches, or null if there is not one. 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 641ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private View findViewForTouch(int rawX, int rawY) { 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reverse order so the child drawn on top gets first dibs. 643ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int containerCoordsX = rawX - mContainerRawLocation[0]; 644ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int containerCoordsY = rawY - mContainerRawLocation[1]; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Rect frame = mTempRect; 646ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 647ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project View closestChild = null; 648ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int closestChildDistanceSq = Integer.MAX_VALUE; 649ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mContainer.getChildCount() - 1; i >= 0; i--) { 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child = mContainer.getChildAt(i); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child.getVisibility() != View.VISIBLE) { 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.getHitRect(frame); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frame.contains(containerCoordsX, containerCoordsY)) { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return child; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 660ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 661ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int distanceX = Math.min(Math.abs(frame.left - containerCoordsX), 662ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Math.abs(containerCoordsX - frame.right)); 663ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int distanceY = Math.min(Math.abs(frame.top - containerCoordsY), 664ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Math.abs(containerCoordsY - frame.bottom)); 665ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int distanceSq = distanceX * distanceX + distanceY * distanceY; 666ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 667ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if ((distanceSq < mTouchPaddingScaledSq) && 668ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project (distanceSq < closestChildDistanceSq)) { 669ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project closestChild = child; 670ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project closestChildDistanceSq = distanceSq; 671ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 674ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return closestChild; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void onPostConfigurationChanged() { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project refreshPositioningVariables(); 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 682b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /* 683b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * This is static so Activities can call this instead of the Views 684b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * (Activities usually do not have a reference to the ZoomButtonsController 685b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * instance.) 686b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project */ 687b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /** 688b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * Shows a "tutorial" (some text) to the user teaching her the new zoom 689b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * invocation method. Must call from the main thread. 690b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * <p> 691b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * It checks the global system setting to ensure this has not been seen 692b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * before. Furthermore, if the application does not have privilege to write 693b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * to the system settings, it will store this bit locally in a shared 694b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * preference. 695b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * 696b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * @hide This should only be used by our main apps--browser, maps, and 697b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * gallery 698b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project */ 699b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public static void showZoomTutorialOnce(Context context) { 700ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 701ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // TODO: remove this code, but to hit the weekend build, just never show 702ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (true) return; 703ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 704b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project ContentResolver cr = context.getContentResolver(); 705b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) { 706b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project return; 707b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 708b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 709b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); 710b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (sp.getInt(SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) { 711b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project return; 712b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 713b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 714b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (sTutorialDialog != null && sTutorialDialog.isShowing()) { 715b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sTutorialDialog.dismiss(); 716b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 717b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 718b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project LayoutInflater layoutInflater = 719b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 720b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project TextView textView = (TextView) layoutInflater.inflate( 721b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project com.android.internal.R.layout.alert_dialog_simple_text, null) 722b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project .findViewById(android.R.id.text1); 723b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project textView.setText(com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short); 724c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 725b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sTutorialDialog = new AlertDialog.Builder(context) 726b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project .setView(textView) 727b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project .setIcon(0) 728b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project .create(); 729b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 730b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Window window = sTutorialDialog.getWindow(); 731b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); 732b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND | 733b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project WindowManager.LayoutParams.FLAG_BLUR_BEHIND); 734b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 735b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); 736b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 737b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sTutorialDialog.show(); 738b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 739b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 740b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /** @hide Should only be used by Android platform apps */ 741b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public static void finishZoomTutorial(Context context, boolean userNotified) { 742b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (sTutorialDialog == null) return; 743b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 744b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sTutorialDialog.dismiss(); 745b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sTutorialDialog = null; 746b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 747b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // Record that they have seen the tutorial 748b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project if (userNotified) { 749b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project try { 750b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Settings.System.putInt(context.getContentResolver(), SETTING_NAME_SHOWN_TUTORIAL, 751b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 1); 752b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } catch (SecurityException e) { 753b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /* 754b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * The app does not have permission to clear this global flag, make 755b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * sure the user does not see the message when he comes back to this 756b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * same app at least. 757b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project */ 758b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); 759b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project sp.edit().putInt(SETTING_NAME_SHOWN_TUTORIAL, 1).commit(); 760b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 761b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 762b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 763b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 764b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /** @hide Should only be used by Android platform apps */ 765b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public void finishZoomTutorial() { 766b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project finishZoomTutorial(mContext, true); 767b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 768b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 769ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** @hide Should only be used only be WebView and MapView */ 770ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public View getDummyZoomControls() { 771ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (mDummyZoomControls == null) { 772ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mDummyZoomControls = new InvisibleView(mContext); 773ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 774ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return mDummyZoomControls; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 776ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 777ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 778ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Interface that will be called when the user performs an interaction that 779ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * triggers some action, for example zooming. 780ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnZoomListener { 782ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 783ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Called when the given point should be centered. The point will be in 784ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * owner view coordinates. 785ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 786ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param x The x of the point. 787ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param y The y of the point. 788ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onCenter(int x, int y); 790ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 791ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 792ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Called when the zoom controls' visibility changes. 793ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 794ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param visible Whether the zoom controls are visible. 795ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onVisibilityChanged(boolean visible); 797ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 798ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 799ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Called when the owner view needs to be zoomed. 800ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * 801ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param zoomIn The direction of the zoom: true to zoom in, false to zoom out. 802ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onZoom(boolean zoomIn); 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 805ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 806ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private class Container extends FrameLayout { 807ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public Container(Context context) { 808ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project super(context); 809ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 810ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 811ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /* 812ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Need to override this to intercept the key events. Otherwise, we 813ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * would attach a key listener to the container but its superclass 814ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * ViewGroup gives it to the focused View instead of calling the key 815ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * listener, and so we wouldn't get the events. 816ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 817ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project @Override 818ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public boolean dispatchKeyEvent(KeyEvent event) { 819ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return onContainerKey(event) ? true : super.dispatchKeyEvent(event); 820ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 821ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 822ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 823ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 824ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * An InvisibleView is an invisible, zero-sized View for backwards 825ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * compatibility 826ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 827ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private final class InvisibleView extends View { 828ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 829ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private InvisibleView(Context context) { 830ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project super(context); 831ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project setVisibility(GONE); 832ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 833ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 834ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project @Override 835ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 836ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project setMeasuredDimension(0, 0); 837ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 838ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 839ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project @Override 840ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public void draw(Canvas canvas) { 841ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 842ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 843ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project @Override 844ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project protected void dispatchDraw(Canvas canvas) { 845ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 846ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 847ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 849