| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.systemui.statusbar; |
| |
| import android.app.StatusBarManager; |
| import android.content.res.Resources; |
| import android.graphics.RectF; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import com.android.systemui.R; |
| |
| public class DelegateViewHelper { |
| private View mDelegateView; |
| private View mSourceView; |
| private BaseStatusBar mBar; |
| private int[] mTempPoint = new int[2]; |
| private float[] mDownPoint = new float[2]; |
| private float mTriggerThreshhold; |
| private boolean mPanelShowing; |
| |
| RectF mInitialTouch = new RectF(); |
| private boolean mStarted; |
| private boolean mSwapXY = false; |
| private boolean mDisabled; |
| |
| public DelegateViewHelper(View sourceView) { |
| setSourceView(sourceView); |
| } |
| |
| public void setDelegateView(View view) { |
| mDelegateView = view; |
| } |
| |
| public void setBar(BaseStatusBar phoneStatusBar) { |
| mBar = phoneStatusBar; |
| } |
| |
| public boolean onInterceptTouchEvent(MotionEvent event) { |
| if (mSourceView == null || mDelegateView == null || mBar.shouldDisableNavbarGestures()) { |
| return false; |
| } |
| |
| mSourceView.getLocationOnScreen(mTempPoint); |
| final float sourceX = mTempPoint[0]; |
| final float sourceY = mTempPoint[1]; |
| |
| final int action = event.getAction(); |
| switch (action) { |
| case MotionEvent.ACTION_DOWN: |
| mPanelShowing = mDelegateView.getVisibility() == View.VISIBLE; |
| mDownPoint[0] = event.getX(); |
| mDownPoint[1] = event.getY(); |
| mStarted = mInitialTouch.contains(mDownPoint[0] + sourceX, mDownPoint[1] + sourceY); |
| break; |
| } |
| |
| if (!mStarted) { |
| return false; |
| } |
| |
| if (!mDisabled && !mPanelShowing && action == MotionEvent.ACTION_MOVE) { |
| final int historySize = event.getHistorySize(); |
| for (int k = 0; k < historySize + 1; k++) { |
| float x = k < historySize ? event.getHistoricalX(k) : event.getX(); |
| float y = k < historySize ? event.getHistoricalY(k) : event.getY(); |
| final float distance = mSwapXY ? (mDownPoint[0] - x) : (mDownPoint[1] - y); |
| if (distance > mTriggerThreshhold) { |
| mBar.showSearchPanel(); |
| mPanelShowing = true; |
| break; |
| } |
| } |
| } |
| |
| if (action == MotionEvent.ACTION_DOWN) { |
| mBar.setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, true); |
| } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { |
| mBar.setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, false); |
| } |
| |
| mDelegateView.getLocationOnScreen(mTempPoint); |
| final float delegateX = mTempPoint[0]; |
| final float delegateY = mTempPoint[1]; |
| |
| float deltaX = sourceX - delegateX; |
| float deltaY = sourceY - delegateY; |
| event.offsetLocation(deltaX, deltaY); |
| mDelegateView.dispatchTouchEvent(event); |
| event.offsetLocation(-deltaX, -deltaY); |
| return mPanelShowing; |
| } |
| |
| public void setSourceView(View view) { |
| mSourceView = view; |
| if (mSourceView != null) { |
| Resources r = mSourceView.getContext().getResources(); |
| mTriggerThreshhold = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance); |
| } |
| } |
| |
| /** |
| * Selects the initial touch region based on a list of views. This is meant to be called by |
| * a container widget on children over which the initial touch should be detected. Note this |
| * will compute a minimum bound that contains all specified views. |
| * |
| * @param views |
| */ |
| public void setInitialTouchRegion(View ... views) { |
| RectF bounds = new RectF(); |
| int p[] = new int[2]; |
| for (int i = 0; i < views.length; i++) { |
| View view = views[i]; |
| if (view == null) continue; |
| view.getLocationOnScreen(p); |
| if (i == 0) { |
| bounds.set(p[0], p[1], p[0] + view.getWidth(), p[1] + view.getHeight()); |
| } else { |
| bounds.union(p[0], p[1], p[0] + view.getWidth(), p[1] + view.getHeight()); |
| } |
| } |
| mInitialTouch.set(bounds); |
| } |
| |
| /** |
| * When rotation is set to NO_SENSOR, then this allows swapping x/y for gesture detection |
| * @param swap |
| */ |
| public void setSwapXY(boolean swap) { |
| mSwapXY = swap; |
| } |
| |
| public void setDisabled(boolean disabled) { |
| mDisabled = disabled; |
| } |
| } |