/* * 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; } }