ZoomButtonsController.java revision 8d37426c754e9822feaa8c6cc0b7c13e8523e217
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 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 27ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectimport android.util.Log; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewConfiguration; 34c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.view.ViewGroup; 35ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectimport android.view.ViewParent; 36ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectimport android.view.ViewRoot; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View.OnClickListener; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager.LayoutParams; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project/* 42ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Implementation notes: 43ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * - The zoom controls are displayed in their own window. 44ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * (Easier for the client and better performance) 45105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * - This window is never touchable, and by default is not focusable. 46105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * Its rect is quite big (fills horizontally) but has empty space between the 47105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * edges and center. Touches there should be given to the owner. Instead of 48105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * having the window touchable and dispatching these empty touch events to the 49105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * owner, we set the window to not touchable and steal events from owner 50105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * via onTouchListener. 51105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * - To make the buttons clickable, it attaches an OnTouchListener to the owner 52105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * view and does the hit detection locally (attaches when visible, detaches when invisible). 53ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * - When it is focusable, it forwards uninteresting events to the owner view's 54ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * view hierarchy. 55ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 57ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * The {@link ZoomButtonsController} handles showing and hiding the zoom 58105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * controls and positioning it relative to an owner view. It also gives the 59105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * client access to the zoom controls container, allowing for additional 60105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * accessory buttons to be shown in the zoom controls window. 61ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * <p> 62105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * Typically, clients should call {@link #setVisible(boolean) setVisible(true)} 63105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * on a touch down or move (no need to call {@link #setVisible(boolean) 64105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * setVisible(false)} since it will time out on its own). Also, whenever the 65105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * owner cannot be zoomed further, the client should update 66ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * {@link #setZoomInEnabled(boolean)} and {@link #setZoomOutEnabled(boolean)}. 67ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * <p> 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If you are using this with a custom View, please call 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setVisible(boolean) setVisible(false)} from the 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link View#onDetachedFromWindow}. 71105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 73ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectpublic class ZoomButtonsController implements View.OnTouchListener { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "ZoomButtonsController"; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ZOOM_CONTROLS_TIMEOUT = 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int) ViewConfiguration.getZoomControlsTimeout(); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ZOOM_CONTROLS_TOUCH_PADDING = 20; 81ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private int mTouchPaddingScaledSq; 82c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 83470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final Context mContext; 84470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final WindowManager mWindowManager; 85105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private boolean mAutoDismissControls = true; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 88b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * The view that is being zoomed by this zoom controller. 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 90470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final View mOwnerView; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 93ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * The location of the owner view on the screen. This is recalculated 94b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * each time the zoom controller is shown. 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 96470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final int[] mOwnerViewRawLocation = new int[2]; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The container that is added as a window. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 101470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final FrameLayout mContainer; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LayoutParams mContainerLayoutParams; 103470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final int[] mContainerRawLocation = new int[2]; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ZoomControls mControls; 106c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The view (or null) that should receive touch events. This will get set if 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the touch down hits the container. It will be reset on the touch up. 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View mTouchTargetView; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The {@link #mTouchTargetView}'s location in window, set on touch down. 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 115470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final int[] mTouchTargetWindowLocation = new int[2]; 116105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 118b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project * If the zoom controller is dismissed but the user is still in a touch 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * interaction, we set this to true. This will ignore all touch events until 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * up/cancel, and then set the owner's touch listener to null. 121105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * <p> 122105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * Otherwise, the owner view would get mismatched events (i.e., touch move 123105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * even though it never got the touch down.) 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mReleaseTouchListenerOnUp; 126c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 127ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** Whether the container has been added to the window manager. */ 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsVisible; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 130470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final Rect mTempRect = new Rect(); 131470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final int[] mTempIntArray = new int[2]; 132105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnZoomListener mCallback; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When showing the zoom, we add the view as a new window. However, there is 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * logic that needs to know the size of the zoom which is determined after 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it's laid out. Therefore, we must post this logic onto the UI thread so 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it will be exceuted AFTER the layout. This is the logic. 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Runnable mPostedVisibleInitializer; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 143470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final IntentFilter mConfigurationChangedFilter = 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 146ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 147ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Needed to reposition the zoom controls after configuration changes. 148ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 149470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final BroadcastReceiver mConfigurationChangedReceiver = new BroadcastReceiver() { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mIsVisible) return; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(MSG_POST_CONFIGURATION_CHANGED); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendEmptyMessage(MSG_POST_CONFIGURATION_CHANGED); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** When configuration changes, this is called after the UI thread is idle. */ 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_POST_CONFIGURATION_CHANGED = 2; 161b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project /** Used to delay the zoom controller dismissal. */ 162b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project private static final int MSG_DISMISS_ZOOM_CONTROLS = 3; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If setVisible(true) is called and the owner view's window token is null, 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we delay the setVisible(true) call until it is not null. 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_POST_SET_VISIBLE = 4; 168c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 169470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin private final Handler mHandler = new Handler() { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_POST_CONFIGURATION_CHANGED: 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onPostConfigurationChanged(); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 177b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project case MSG_DISMISS_ZOOM_CONTROLS: 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setVisible(false); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 180c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_POST_SET_VISIBLE: 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOwnerView.getWindowToken() == null) { 183ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // Doh, it is still null, just ignore the set visible call 184ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Log.e(TAG, 185b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project "Cannot make the zoom controller visible if the owner view is " + 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "not attached to a window."); 187ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } else { 188ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project setVisible(true); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 196ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 197ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Constructor for the {@link ZoomButtonsController}. 198105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 199ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param ownerView The view that is being zoomed by the zoom controls. The 200ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * zoom controls will be displayed aligned with this view. 201ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 202ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public ZoomButtonsController(View ownerView) { 203ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContext = ownerView.getContext(); 204ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnerView = ownerView; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 207ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mTouchPaddingScaledSq = (int) 208ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project (ZOOM_CONTROLS_TOUCH_PADDING * mContext.getResources().getDisplayMetrics().density); 209ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mTouchPaddingScaledSq *= mTouchPaddingScaledSq; 210105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContainer = createContainer(); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 213c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 214ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 215ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Whether to enable the zoom in control. 216105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 217ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param enabled Whether to enable the zoom in control. 218ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 219b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public void setZoomInEnabled(boolean enabled) { 220b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mControls.setIsZoomInEnabled(enabled); 221b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 222c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 223ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 224ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Whether to enable the zoom out control. 225105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 226ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param enabled Whether to enable the zoom out control. 227ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 228b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public void setZoomOutEnabled(boolean enabled) { 229b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mControls.setIsZoomOutEnabled(enabled); 230b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 231c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 232ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 233ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Sets the delay between zoom callbacks as the user holds a zoom button. 234105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 235ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param speed The delay in milliseconds between zoom callbacks. 236ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 237b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project public void setZoomSpeed(long speed) { 238b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mControls.setZoomSpeed(speed); 239b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 240c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private FrameLayout createContainer() { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 243ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // Controls are positioned BOTTOM | CENTER with respect to the owner view. 244ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project lp.gravity = Gravity.TOP | Gravity.LEFT; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE | 246b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project LayoutParams.FLAG_NOT_FOCUSABLE | 247105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project LayoutParams.FLAG_LAYOUT_NO_LIMITS | 248105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project LayoutParams.FLAG_ALT_FOCUSABLE_IM; 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.height = LayoutParams.WRAP_CONTENT; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.width = LayoutParams.FILL_PARENT; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.type = LayoutParams.TYPE_APPLICATION_PANEL; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.format = PixelFormat.TRANSPARENT; 253c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContainerLayoutParams = lp; 255c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 256ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project FrameLayout container = new Container(mContext); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project container.setLayoutParams(lp); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project container.setMeasureAllChildren(true); 259c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutInflater inflater = (LayoutInflater) mContext 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 262c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project inflater.inflate(com.android.internal.R.layout.zoom_container, container); 263c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mControls.setOnZoomInClickListener(new OnClickListener() { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(View v) { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) mCallback.onZoom(true); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mControls.setOnZoomOutClickListener(new OnClickListener() { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(View v) { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) mCallback.onZoom(false); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return container; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 280c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 281ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 282ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Sets the {@link OnZoomListener} listener that receives callbacks to zoom. 283105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 284ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param listener The listener that will be told to zoom. 285ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 286ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public void setOnZoomListener(OnZoomListener listener) { 287ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mCallback = listener; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 290ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 291ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Sets whether the zoom controls should be focusable. If the controls are 292ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * focusable, then trackball and arrow key interactions are possible. 293ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Otherwise, only touch interactions are possible. 294105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 295ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param focusable Whether the zoom controls should be focusable. 296ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFocusable(boolean focusable) { 298ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int oldFlags = mContainerLayoutParams.flags; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (focusable) { 300c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project mContainerLayoutParams.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContainerLayoutParams.flags |= LayoutParams.FLAG_NOT_FOCUSABLE; 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 304c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 305ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if ((mContainerLayoutParams.flags != oldFlags) && mIsVisible) { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 310ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 311105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * Whether the zoom controls will be automatically dismissed after showing. 312105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 313105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return Whether the zoom controls will be auto dismissed after showing. 314105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project */ 315105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public boolean isAutoDismissed() { 316105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return mAutoDismissControls; 317105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 318105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 319105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** 320105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * Sets whether the zoom controls will be automatically dismissed after 321105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * showing. 322105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project */ 323105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public void setAutoDismissed(boolean autoDismiss) { 324105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (mAutoDismissControls == autoDismiss) return; 325105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mAutoDismissControls = autoDismiss; 326105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 327105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 328105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** 329ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Whether the zoom controls are visible to the user. 330105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 331ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @return Whether the zoom controls are visible to the user. 332ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isVisible() { 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mIsVisible; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 337ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 338ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Sets whether the zoom controls should be visible to the user. 339105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 340ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param visible Whether the zoom controls should be visible to the user. 341ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVisible(boolean visible) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (visible) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOwnerView.getWindowToken() == null) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We need a window token to show ourselves, maybe the owner's 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * window hasn't been created yet but it will have been by the 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * time the looper is idle, so post the setVisible(true) call. 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mHandler.hasMessages(MSG_POST_SET_VISIBLE)) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendEmptyMessage(MSG_POST_SET_VISIBLE); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 356c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsVisible == visible) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsVisible = visible; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (visible) { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContainerLayoutParams.token == null) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContainerLayoutParams.token = mOwnerView.getWindowToken(); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindowManager.addView(mContainer, mContainerLayoutParams); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPostedVisibleInitializer == null) { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPostedVisibleInitializer = new Runnable() { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project refreshPositioningVariables(); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCallback.onVisibilityChanged(true); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 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 mHandler.post(mPostedVisibleInitializer); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Handle configuration changes when visible 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(mConfigurationChangedReceiver, mConfigurationChangedFilter); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Steal touches events from the owner 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnerView.setOnTouchListener(this); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReleaseTouchListenerOnUp = false; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't want to steal any more touches 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTouchTargetView != null) { 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We are still stealing the touch events for this touch 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sequence, so release the touch listener later 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReleaseTouchListenerOnUp = true; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnerView.setOnTouchListener(null); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No longer care about configuration changes 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.unregisterReceiver(mConfigurationChangedReceiver); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWindowManager.removeView(mContainer); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeCallbacks(mPostedVisibleInitializer); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCallback != null) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCallback.onVisibilityChanged(false); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 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 /** 417ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Gets the container that is the parent of the zoom controls. 418ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * <p> 419ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * The client can add other views to this container to link them with the 420ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * zoom controls. 421105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 422ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @return The container of the zoom controls. It will be a layout that 423ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * respects the gravity of a child's layout parameters. 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 425c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public ViewGroup getContainer() { 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mContainer; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 430105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * Gets the view for the zoom controls. 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 432105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * @return The zoom controls view. 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 434105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public View getZoomControls() { 435105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return mControls; 436105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 438105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private void dismissControlsDelayed(int delay) { 439105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (mAutoDismissControls) { 440105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS); 441105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void refreshPositioningVariables() { 446470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin // if the mOwnerView is detached from window then skip. 447470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin if (mOwnerView.getWindowToken() == null) return; 448470681e0ff7a9f629ccfc3a36b51550c5a4d32fcOwen Lin 449ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // Position the zoom controls on the bottom of the owner view. 450ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int ownerHeight = mOwnerView.getHeight(); 451ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int ownerWidth = mOwnerView.getWidth(); 452ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // The gap between the top of the owner and the top of the container 453ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int containerOwnerYOffset = ownerHeight - mContainer.getHeight(); 454ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Calculate the owner view's bounds 456ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mOwnerView.getLocationOnScreen(mOwnerViewRawLocation); 457ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerRawLocation[0] = mOwnerViewRawLocation[0]; 458ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerRawLocation[1] = mOwnerViewRawLocation[1] + containerOwnerYOffset; 459105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 460ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int[] ownerViewWindowLoc = mTempIntArray; 461ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mOwnerView.getLocationInWindow(ownerViewWindowLoc); 462ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 463ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // lp.x and lp.y should be relative to the owner's window top-left 464ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerLayoutParams.x = ownerViewWindowLoc[0]; 465ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerLayoutParams.width = ownerWidth; 466ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mContainerLayoutParams.y = ownerViewWindowLoc[1] + containerOwnerYOffset; 467ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (mIsVisible) { 468ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); 469ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 473ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /* This will only be called when the container has focus. */ 474ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private boolean onContainerKey(KeyEvent event) { 475ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int keyCode = event.getKeyCode(); 476ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (isInterestingKey(keyCode)) { 477105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 478ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_BACK) { 4798d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn if (event.getAction() == KeyEvent.ACTION_DOWN 4808d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn && event.getRepeatCount() == 0) { 4818d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn if (mOwnerView != null) { 4828d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn KeyEvent.DispatcherState ds = mOwnerView.getKeyDispatcherState(); 4838d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn if (ds != null) { 4848d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn ds.startTracking(event, this); 4858d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn } 4868d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn } 4878d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn return true; 4888d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn } else if (event.getAction() == KeyEvent.ACTION_UP 4898d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn && event.isTracking() && !event.isCanceled()) { 4908d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn setVisible(false); 4918d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn return true; 4928d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn } 4938d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn 494ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } else { 495ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 496ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 497105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 498ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // Let the container handle the key 499ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return false; 500105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 501ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } else { 502105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 503ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project ViewRoot viewRoot = getOwnerViewRoot(); 504ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (viewRoot != null) { 505ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project viewRoot.dispatchKey(event); 506ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 507105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 508ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project // We gave the key to the owner, don't let the container handle this key 509ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return true; 510ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 511b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project } 512b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project 513ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private boolean isInterestingKey(int keyCode) { 514ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project switch (keyCode) { 515ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 516ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_UP: 517ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_DOWN: 518ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_LEFT: 519ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_DPAD_RIGHT: 520ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_ENTER: 521ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project case KeyEvent.KEYCODE_BACK: 522ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return true; 523ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project default: 524ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return false; 525ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 526ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 527105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 528ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private ViewRoot getOwnerViewRoot() { 529ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project View rootViewOfOwner = mOwnerView.getRootView(); 530ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (rootViewOfOwner == null) { 531ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return null; 532ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 533105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 534ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project ViewParent parentOfRootView = rootViewOfOwner.getParent(); 535ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (parentOfRootView instanceof ViewRoot) { 536ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return (ViewRoot) parentOfRootView; 537ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } else { 538ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return null; 539ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 540ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 541ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 542ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 543ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @hide The ZoomButtonsController implements the OnTouchListener, but this 544ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * does not need to be shown in its public API. 545ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onTouch(View v, MotionEvent event) { 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int action = event.getAction(); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mReleaseTouchListenerOnUp) { 550b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project // The controls were dismissed but we need to throw away all events until the up 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOwnerView.setOnTouchListener(null); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTouchTargetView(null); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReleaseTouchListenerOnUp = false; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Eat this event 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 562c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View targetView = mTouchTargetView; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (action) { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_DOWN: 567ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project targetView = findViewForTouch((int) event.getRawX(), (int) event.getRawY()); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTouchTargetView(targetView); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_UP: 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_CANCEL: 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setTouchTargetView(null); 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (targetView != null) { 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The upperleft corner of the target view in raw coordinates 579ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int targetViewRawX = mContainerRawLocation[0] + mTouchTargetWindowLocation[0]; 580ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int targetViewRawY = mContainerRawLocation[1] + mTouchTargetWindowLocation[1]; 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MotionEvent containerEvent = MotionEvent.obtain(event); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Convert the motion event into the target view's coordinates (from 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // owner view's coordinates) 585ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project containerEvent.offsetLocation(mOwnerViewRawLocation[0] - targetViewRawX, 586ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project mOwnerViewRawLocation[1] - targetViewRawY); 587ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /* Disallow negative coordinates (which can occur due to 588ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * ZOOM_CONTROLS_TOUCH_PADDING) */ 589105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // These are floats because we need to potentially offset away this exact amount 590105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project float containerX = containerEvent.getX(); 591105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project float containerY = containerEvent.getY(); 592105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (containerX < 0 && containerX > -ZOOM_CONTROLS_TOUCH_PADDING) { 593105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project containerEvent.offsetLocation(-containerX, 0); 594ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 595105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (containerY < 0 && containerY > -ZOOM_CONTROLS_TOUCH_PADDING) { 596105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project containerEvent.offsetLocation(0, -containerY); 597ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean retValue = targetView.dispatchTouchEvent(containerEvent); 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project containerEvent.recycle(); 600105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return retValue; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 603105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return false; 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setTouchTargetView(View view) { 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTouchTargetView = view; 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 610ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project view.getLocationInWindow(mTouchTargetWindowLocation); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the View that should receive a touch at the given coordinates. 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rawX The raw X. 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rawY The raw Y. 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that should receive the touches, or null if there is not one. 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 621ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private View findViewForTouch(int rawX, int rawY) { 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reverse order so the child drawn on top gets first dibs. 623ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int containerCoordsX = rawX - mContainerRawLocation[0]; 624ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int containerCoordsY = rawY - mContainerRawLocation[1]; 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Rect frame = mTempRect; 626ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 627ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project View closestChild = null; 628ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int closestChildDistanceSq = Integer.MAX_VALUE; 629105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mContainer.getChildCount() - 1; i >= 0; i--) { 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child = mContainer.getChildAt(i); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child.getVisibility() != View.VISIBLE) { 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.getHitRect(frame); 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frame.contains(containerCoordsX, containerCoordsY)) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return child; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 640105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 641105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int distanceX; 642105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (containerCoordsX >= frame.left && containerCoordsX <= frame.right) { 643105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project distanceX = 0; 644105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 645105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project distanceX = Math.min(Math.abs(frame.left - containerCoordsX), 646ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project Math.abs(containerCoordsX - frame.right)); 647105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 648105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int distanceY; 649105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (containerCoordsY >= frame.top && containerCoordsY <= frame.bottom) { 650105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project distanceY = 0; 651105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 652105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project distanceY = Math.min(Math.abs(frame.top - containerCoordsY), 653105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Math.abs(containerCoordsY - frame.bottom)); 654105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 655ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project int distanceSq = distanceX * distanceX + distanceY * distanceY; 656105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 657ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if ((distanceSq < mTouchPaddingScaledSq) && 658ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project (distanceSq < closestChildDistanceSq)) { 659ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project closestChild = child; 660ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project closestChildDistanceSq = distanceSq; 661ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 664ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return closestChild; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void onPostConfigurationChanged() { 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project refreshPositioningVariables(); 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 672ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 673ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Interface that will be called when the user performs an interaction that 674ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * triggers some action, for example zooming. 675ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnZoomListener { 677105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 678ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 679ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Called when the zoom controls' visibility changes. 680105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 681ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param visible Whether the zoom controls are visible. 682ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onVisibilityChanged(boolean visible); 684105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 685ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 686ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Called when the owner view needs to be zoomed. 687105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * 688ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * @param zoomIn The direction of the zoom: true to zoom in, false to zoom out. 689ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onZoom(boolean zoomIn); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 692105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 693ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private class Container extends FrameLayout { 694ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public Container(Context context) { 695ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project super(context); 696ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 697ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 698ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /* 699ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * Need to override this to intercept the key events. Otherwise, we 700ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * would attach a key listener to the container but its superclass 701ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * ViewGroup gives it to the focused View instead of calling the key 702ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project * listener, and so we wouldn't get the events. 703ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project */ 704ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project @Override 705ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project public boolean dispatchKeyEvent(KeyEvent event) { 706ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return onContainerKey(event) ? true : super.dispatchKeyEvent(event); 707ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 708ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 709ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 711