Merge "First pass of the Launcher Overlay interface / impl" into ub-now-queens
This commit is contained in:
commit
24e18aea81
|
@ -88,7 +88,25 @@
|
|||
android:stateNotNeeded="true"
|
||||
android:theme="@style/Theme"
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
android:screenOrientation="nosensor">
|
||||
android:screenOrientation="nosensor"
|
||||
android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.HOME" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.MONKEY"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.android.launcher3.LauncherExtension"
|
||||
android:launchMode="singleTask"
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:stateNotNeeded="true"
|
||||
android:theme="@style/Theme"
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
android:screenOrientation="nosensor"
|
||||
android:enabled="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.HOME" />
|
||||
|
|
|
@ -63,4 +63,11 @@
|
|||
android:layout_height="match_parent"
|
||||
android:visibility="invisible" />
|
||||
</com.android.launcher3.DragLayer>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/launcher_overlay_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:inflatedId="@+id/launcher_overlay"
|
||||
android:layout="@layout/launcher_overlay" />
|
||||
</FrameLayout>
|
||||
|
|
|
@ -83,4 +83,11 @@
|
|||
android:layout_height="match_parent"
|
||||
android:visibility="invisible" />
|
||||
</com.android.launcher3.DragLayer>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/launcher_overlay_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:inflatedId="@+id/launcher_overlay"
|
||||
android:layout="@layout/launcher_overlay" />
|
||||
</FrameLayout>
|
||||
|
|
|
@ -82,4 +82,12 @@
|
|||
android:layout_height="match_parent"
|
||||
android:visibility="invisible" />
|
||||
</com.android.launcher3.DragLayer>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/launcher_overlay_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:inflatedId="@+id/launcher_overlay"
|
||||
android:layout="@layout/launcher_overlay" />
|
||||
|
||||
</FrameLayout>
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 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.
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 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.
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/search_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#ff00ff00"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/search_box"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="36dp"
|
||||
android:background="#ffff0000" />
|
||||
</FrameLayout>
|
|
@ -89,6 +89,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
|
|||
private Drawable mLeftHoverDrawableActive;
|
||||
private Drawable mRightHoverDrawableActive;
|
||||
|
||||
private boolean mBlockTouches = false;
|
||||
|
||||
/**
|
||||
* Used to create a new DragLayer from XML.
|
||||
*
|
||||
|
@ -185,11 +187,19 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
|
|||
return false;
|
||||
}
|
||||
|
||||
public void setBlockTouch(boolean block) {
|
||||
mBlockTouches = block;
|
||||
}
|
||||
|
||||
private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
|
||||
Rect hitRect = new Rect();
|
||||
int x = (int) ev.getX();
|
||||
int y = (int) ev.getY();
|
||||
|
||||
if (mBlockTouches) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (AppWidgetResizeFrame child: mResizeFrames) {
|
||||
child.getHitRect(hitRect);
|
||||
if (hitRect.contains(x, y)) {
|
||||
|
@ -332,6 +342,10 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
|
|||
int x = (int) ev.getX();
|
||||
int y = (int) ev.getY();
|
||||
|
||||
if (mBlockTouches) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
if (handleTouchDown(ev, false)) {
|
||||
return true;
|
||||
|
|
|
@ -86,6 +86,7 @@ import android.view.View.OnClickListener;
|
|||
import android.view.View.OnLongClickListener;
|
||||
import android.view.ViewAnimationUtils;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewStub;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
@ -228,6 +229,10 @@ public class Launcher extends Activity
|
|||
|
||||
private boolean mIsSafeModeEnabled;
|
||||
|
||||
LauncherOverlayCallbacks mLauncherOverlayCallbacks = new LauncherOverlayCallbacksImpl();
|
||||
LauncherOverlay mLauncherOverlay;
|
||||
ViewGroup mLauncherOverlayView;
|
||||
|
||||
static final int APPWIDGET_HOST_ID = 1024;
|
||||
public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
|
||||
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
|
||||
|
@ -507,6 +512,13 @@ public class Launcher extends Activity
|
|||
|
||||
if (mLauncherCallbacks != null) {
|
||||
mLauncherCallbacks.onCreate(savedInstanceState);
|
||||
if (mLauncherCallbacks.hasLauncherOverlay()) {
|
||||
ViewStub stub = (ViewStub) findViewById(R.id.launcher_overlay_stub);
|
||||
mLauncherOverlayView = (ViewGroup) stub.inflate();
|
||||
mLauncherOverlay = mLauncherCallbacks.setLauncherOverlayView(mLauncherOverlayView,
|
||||
mLauncherOverlayCallbacks);
|
||||
mWorkspace.setLauncherOverlay(mLauncherOverlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1145,6 +1157,84 @@ public class Launcher extends Activity
|
|||
boolean isScrollingAllowed();
|
||||
}
|
||||
|
||||
public interface LauncherOverlay {
|
||||
|
||||
/**
|
||||
* Touch interaction leading to overscroll has begun
|
||||
*/
|
||||
public void onScrollInteractionBegin();
|
||||
|
||||
/**
|
||||
* Touch interaction related to overscroll has ended
|
||||
*/
|
||||
public void onScrollInteractionEnd();
|
||||
|
||||
/**
|
||||
* Scroll progress, between 0 and 100, when the user scrolls beyond the leftmost
|
||||
* screen (or in the case of RTL, the rightmost screen).
|
||||
*/
|
||||
public void onScrollChange(int progress, boolean rtl);
|
||||
|
||||
/**
|
||||
* Screen has stopped scrolling
|
||||
*/
|
||||
public void onScrollSettled();
|
||||
|
||||
/**
|
||||
* This method can be called by the Launcher in order to force the LauncherOverlay
|
||||
* to exit fully immersive mode.
|
||||
*/
|
||||
public void forceExitFullImmersion();
|
||||
}
|
||||
|
||||
public interface LauncherOverlayCallbacks {
|
||||
/**
|
||||
* This method indicates whether a call to {@link #enterFullImmersion()} will succeed,
|
||||
* however it doesn't modify any state within the launcher.
|
||||
*/
|
||||
public boolean canEnterFullImmersion();
|
||||
|
||||
/**
|
||||
* Should be called to tell Launcher that the LauncherOverlay will take over interaction,
|
||||
* eg. by occupying the full screen and handling all touch events.
|
||||
*
|
||||
* @return true if Launcher allows the LauncherOverlay to become fully immersive. In this
|
||||
* case, Launcher will modify any necessary state and assumes the overlay is
|
||||
* handling all interaction. If false, the LauncherOverlay should cancel any
|
||||
*
|
||||
*/
|
||||
public boolean enterFullImmersion();
|
||||
|
||||
/**
|
||||
* Must be called when exiting fully immersive mode. Indicates to Launcher that it has
|
||||
* full control over UI and state.
|
||||
*/
|
||||
public void exitFullImmersion();
|
||||
}
|
||||
|
||||
class LauncherOverlayCallbacksImpl implements LauncherOverlayCallbacks {
|
||||
|
||||
@Override
|
||||
public boolean canEnterFullImmersion() {
|
||||
return mState == State.WORKSPACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enterFullImmersion() {
|
||||
if (mState == State.WORKSPACE) {
|
||||
// When fully immersed, disregard any touches which fall through.
|
||||
mDragLayer.setBlockTouch(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitFullImmersion() {
|
||||
mDragLayer.setBlockTouch(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasSettings() {
|
||||
if (mLauncherCallbacks != null) {
|
||||
return mLauncherCallbacks.hasSettings();
|
||||
|
@ -4084,11 +4174,8 @@ public class Launcher extends Activity
|
|||
}
|
||||
|
||||
public View getQsbBar() {
|
||||
if (mLauncherCallbacks != null) {
|
||||
View qsb = mLauncherCallbacks.getQsbBar();
|
||||
if (qsb != null) {
|
||||
return qsb;
|
||||
}
|
||||
if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
|
||||
return mLauncherCallbacks.getQsbBar();
|
||||
}
|
||||
|
||||
if (mQsb == null) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.graphics.Rect;
|
|||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
|
@ -86,4 +87,22 @@ public interface LauncherCallbacks {
|
|||
public boolean overrideWallpaperDimensions();
|
||||
public boolean isLauncherPreinstalled();
|
||||
|
||||
/**
|
||||
* Returning true will immediately result in a call to {@link #setLauncherOverlayView(ViewGroup,
|
||||
* com.android.launcher3.Launcher.LauncherOverlayCallbacks)}.
|
||||
*
|
||||
* @return true if this launcher extension will provide an overlay
|
||||
*/
|
||||
public boolean hasLauncherOverlay();
|
||||
|
||||
/**
|
||||
* Handshake to establish an overlay relationship
|
||||
*
|
||||
* @param overlayView Full screen overlay ViewGroup into which custom views can be placed.
|
||||
* @param callbacks A set of callbacks provided by Launcher in relation to the overlay
|
||||
* @return an interface used to make requests and notify the Launcher in relation to the overlay
|
||||
*/
|
||||
public Launcher.LauncherOverlay setLauncherOverlayView(ViewGroup overlayView,
|
||||
Launcher.LauncherOverlayCallbacks callbacks);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,354 @@
|
|||
package com.android.launcher3;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.Animator.AnimatorListener;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class represents a very trivial LauncherExtension. It primarily serves as a simple
|
||||
* class to exercise the LauncherOverlay interface.
|
||||
*/
|
||||
public class LauncherExtension extends Launcher {
|
||||
|
||||
//------ Activity methods -------//
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
setLauncherCallbacks(new LauncherExtensionCallbacks());
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
public class LauncherExtensionCallbacks implements LauncherCallbacks {
|
||||
|
||||
LauncherExtensionOverlay mLauncherOverlay = new LauncherExtensionOverlay();
|
||||
|
||||
@Override
|
||||
public void preOnCreate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preOnResume() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostCreate(Bundle savedInstanceState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHomeIntent() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleBackPressed() {
|
||||
if (mLauncherOverlay.isOverlayPanelShowing()) {
|
||||
mLauncherOverlay.hideOverlayPanel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLauncherProviderChange() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishBindingItems(boolean upgradePath) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickAllAppsButton(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindAllApplications(ArrayList<AppInfo> apps) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickFolderIcon(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickAppShortcut(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickPagedViewIcon(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickWallpaperPicker(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickSettingsButton(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickAddWidgetButton(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSwitch(View newPage, int newPageIndex) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorkspaceLockedChanged() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragStarted(View view) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteractionBegin() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteractionEnd() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceDisableVoiceButtonProxy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean providesSearch() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startSearch(String initialQuery, boolean selectInitialQuery,
|
||||
Bundle appSearchData, Rect sourceBounds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startVoice() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomContentToLeft() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateCustomContentContainer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getQsbBar() {
|
||||
return mLauncherOverlay.getSearchBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getFirstRunActivity() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFirstRunActivity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDismissableIntroScreen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getIntroScreen() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldMoveToDefaultScreenOnHomeIntent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSettings() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName getWallpaperPickerComponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overrideWallpaperDimensions() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLauncherPreinstalled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLauncherOverlay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LauncherOverlay setLauncherOverlayView(ViewGroup overlayView,
|
||||
LauncherOverlayCallbacks callbacks) {
|
||||
|
||||
mLauncherOverlay.setOverlayCallbacks(callbacks);
|
||||
mLauncherOverlay.setOverlayView(overlayView);
|
||||
|
||||
return mLauncherOverlay;
|
||||
}
|
||||
|
||||
class LauncherExtensionOverlay implements LauncherOverlay {
|
||||
LauncherOverlayCallbacks mLauncherOverlayCallbacks;
|
||||
ViewGroup mOverlayView;
|
||||
View mSearchBox;
|
||||
View mSearchOverlay;
|
||||
boolean mShowOverlayFeedback;
|
||||
int mProgress;
|
||||
boolean mOverlayPanelShowing;
|
||||
|
||||
@Override
|
||||
public void onScrollInteractionBegin() {
|
||||
if (mLauncherOverlayCallbacks.canEnterFullImmersion()) {
|
||||
mShowOverlayFeedback = true;
|
||||
updatePanelOffset(0);
|
||||
mSearchOverlay.setVisibility(View.VISIBLE);
|
||||
mSearchOverlay.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollChange(int progress, boolean rtl) {
|
||||
mProgress = progress;
|
||||
if (mShowOverlayFeedback) {
|
||||
updatePanelOffset(progress);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePanelOffset(int progress) {
|
||||
int panelWidth = mSearchOverlay.getMeasuredWidth();
|
||||
int offset = (int) ((progress / 100f) * panelWidth);
|
||||
mSearchOverlay.setTranslationX(- panelWidth + offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollInteractionEnd() {
|
||||
if (mProgress > 25 && mLauncherOverlayCallbacks.enterFullImmersion()) {
|
||||
ObjectAnimator oa = LauncherAnimUtils.ofFloat(mSearchOverlay, "translationX", 0);
|
||||
oa.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator arg0) {
|
||||
mSearchOverlay.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
}
|
||||
});
|
||||
oa.start();
|
||||
mOverlayPanelShowing = true;
|
||||
mShowOverlayFeedback = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollSettled() {
|
||||
if (mShowOverlayFeedback) {
|
||||
mSearchOverlay.setVisibility(View.INVISIBLE);
|
||||
mSearchOverlay.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
}
|
||||
mShowOverlayFeedback = false;
|
||||
mProgress = 0;
|
||||
}
|
||||
|
||||
public void hideOverlayPanel() {
|
||||
mLauncherOverlayCallbacks.exitFullImmersion();
|
||||
mSearchOverlay.setVisibility(View.INVISIBLE);
|
||||
mOverlayPanelShowing = false;
|
||||
}
|
||||
|
||||
public boolean isOverlayPanelShowing() {
|
||||
return mOverlayPanelShowing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceExitFullImmersion() {
|
||||
hideOverlayPanel();
|
||||
}
|
||||
|
||||
public void setOverlayView(ViewGroup overlayView) {
|
||||
mOverlayView = (ViewGroup) getLayoutInflater().inflate(
|
||||
R.layout.launcher_overlay_example, overlayView);
|
||||
mSearchOverlay = mOverlayView.findViewById(R.id.search_overlay);
|
||||
mSearchBox = mOverlayView.findViewById(R.id.search_box);
|
||||
}
|
||||
|
||||
public View getSearchBox() {
|
||||
return mSearchBox;
|
||||
}
|
||||
|
||||
public void setOverlayCallbacks(LauncherOverlayCallbacks callbacks) {
|
||||
mLauncherOverlayCallbacks = callbacks;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -204,6 +204,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
|
||||
protected boolean mAllowLongPress = true;
|
||||
|
||||
private boolean mWasInOverscroll = false;
|
||||
|
||||
// Page Indicator
|
||||
private int mPageIndicatorViewId;
|
||||
private PageIndicator mPageIndicator;
|
||||
|
@ -625,6 +627,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
|
||||
// a method that subclasses can override to add behavior
|
||||
protected void onPageEndMoving() {
|
||||
mWasInOverscroll = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -663,6 +666,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
if (isXBeforeFirstPage) {
|
||||
super.scrollTo(0, y);
|
||||
if (mAllowOverScroll) {
|
||||
mWasInOverscroll = true;
|
||||
if (isRtl) {
|
||||
overScroll(x - mMaxScrollX);
|
||||
} else {
|
||||
|
@ -672,6 +676,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
} else if (isXAfterLastPage) {
|
||||
super.scrollTo(mMaxScrollX, y);
|
||||
if (mAllowOverScroll) {
|
||||
mWasInOverscroll = true;
|
||||
if (isRtl) {
|
||||
overScroll(x);
|
||||
} else {
|
||||
|
@ -679,6 +684,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (mWasInOverscroll) {
|
||||
overScroll(0);
|
||||
mWasInOverscroll = false;
|
||||
}
|
||||
mOverScrollX = x;
|
||||
super.scrollTo(x, y);
|
||||
}
|
||||
|
@ -1513,6 +1522,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
mLastMotionXRemainder = 0;
|
||||
mTouchX = getViewportOffsetX() + getScrollX();
|
||||
mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
|
||||
onScrollInteractionBegin();
|
||||
pageBeginMoving();
|
||||
}
|
||||
}
|
||||
|
@ -1752,6 +1762,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
mActivePointerId = ev.getPointerId(0);
|
||||
|
||||
if (mTouchState == TOUCH_STATE_SCROLLING) {
|
||||
onScrollInteractionBegin();
|
||||
pageBeginMoving();
|
||||
}
|
||||
break;
|
||||
|
@ -1940,6 +1951,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
getScrollY(), vX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
|
||||
invalidate();
|
||||
}
|
||||
onScrollInteractionEnd();
|
||||
} else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
|
||||
// at this point we have not moved beyond the touch slop
|
||||
// (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
|
||||
|
@ -2025,6 +2037,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
|||
mActivePointerId = INVALID_POINTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered by scrolling via touch
|
||||
*/
|
||||
protected void onScrollInteractionBegin() {
|
||||
}
|
||||
|
||||
protected void onScrollInteractionEnd() {
|
||||
}
|
||||
|
||||
protected void onUnhandledTap(MotionEvent ev) {
|
||||
((Launcher) getContext()).onClick(this);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.android.launcher3;
|
|||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
@ -37,7 +38,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
|
|||
private static final int sTransitionOutDuration = 175;
|
||||
|
||||
private ObjectAnimator mDropTargetBarAnim;
|
||||
private ObjectAnimator mQSBSearchBarAnim;
|
||||
private ValueAnimator mQSBSearchBarAnim;
|
||||
private static final AccelerateInterpolator sAccelerateInterpolator =
|
||||
new AccelerateInterpolator();
|
||||
|
||||
|
@ -70,28 +71,38 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
|
|||
mInfoDropTarget.setLauncher(launcher);
|
||||
mDeleteDropTarget.setLauncher(launcher);
|
||||
mQSBSearchBar = launcher.getQsbBar();
|
||||
if (mEnableDropDownDropTargets) {
|
||||
mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
|
||||
-mBarHeight);
|
||||
if (mQSBSearchBar != null) {
|
||||
if (mEnableDropDownDropTargets) {
|
||||
mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
|
||||
-mBarHeight);
|
||||
} else {
|
||||
mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
|
||||
}
|
||||
setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
|
||||
} else {
|
||||
mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
|
||||
// Create a no-op animation of the search bar is null
|
||||
mQSBSearchBarAnim = ValueAnimator.ofFloat(0, 0);
|
||||
mQSBSearchBarAnim.setDuration(sTransitionInDuration);
|
||||
}
|
||||
setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
|
||||
}
|
||||
|
||||
private void prepareStartAnimation(View v) {
|
||||
// Enable the hw layers before the animation starts (will be disabled in the onAnimationEnd
|
||||
// callback below)
|
||||
v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
if (v != null) {
|
||||
v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupAnimation(ObjectAnimator anim, final View v) {
|
||||
private void setupAnimation(ValueAnimator anim, final View v) {
|
||||
anim.setInterpolator(sAccelerateInterpolator);
|
||||
anim.setDuration(sTransitionInDuration);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
v.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
if (v != null) {
|
||||
v.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -145,9 +156,9 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
|
|||
mQSBSearchBarAnim.reverse();
|
||||
} else {
|
||||
mQSBSearchBarAnim.cancel();
|
||||
if (mEnableDropDownDropTargets) {
|
||||
if (mQSBSearchBar != null && mEnableDropDownDropTargets) {
|
||||
mQSBSearchBar.setTranslationY(0);
|
||||
} else {
|
||||
} else if (mQSBSearchBar != null) {
|
||||
mQSBSearchBar.setAlpha(1f);
|
||||
}
|
||||
}
|
||||
|
@ -161,9 +172,9 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
|
|||
mQSBSearchBarAnim.start();
|
||||
} else {
|
||||
mQSBSearchBarAnim.cancel();
|
||||
if (mEnableDropDownDropTargets) {
|
||||
if (mQSBSearchBar != null && mEnableDropDownDropTargets) {
|
||||
mQSBSearchBar.setTranslationY(-mBarHeight);
|
||||
} else {
|
||||
} else if (mQSBSearchBar != null) {
|
||||
mQSBSearchBar.setAlpha(0f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ import android.widget.TextView;
|
|||
|
||||
import com.android.launcher3.FolderIcon.FolderRingAnimator;
|
||||
import com.android.launcher3.Launcher.CustomContentCallbacks;
|
||||
import com.android.launcher3.Launcher.LauncherOverlay;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.compat.PackageInstallerCompat;
|
||||
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
|
||||
|
@ -289,6 +290,12 @@ public class Workspace extends SmoothPagedView
|
|||
private boolean mDeferDropAfterUninstall;
|
||||
private boolean mUninstallSuccessful;
|
||||
|
||||
// State related to Launcher Overlay
|
||||
LauncherOverlay mLauncherOverlay;
|
||||
boolean mScrollInteractionBegan;
|
||||
boolean mStartedSendingScrollEvents;
|
||||
boolean mShouldSendPageSettled;
|
||||
|
||||
private final Runnable mBindPages = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -1249,6 +1256,58 @@ public class Workspace extends SmoothPagedView
|
|||
stripEmptyScreens();
|
||||
mStripScreensOnPageStopMoving = false;
|
||||
}
|
||||
|
||||
if (mShouldSendPageSettled) {
|
||||
mLauncherOverlay.onScrollSettled();
|
||||
mShouldSendPageSettled = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void onScrollInteractionBegin() {
|
||||
super.onScrollInteractionEnd();
|
||||
mScrollInteractionBegan = true;
|
||||
}
|
||||
|
||||
protected void onScrollInteractionEnd() {
|
||||
super.onScrollInteractionEnd();
|
||||
mScrollInteractionBegan = false;
|
||||
if (mStartedSendingScrollEvents) {
|
||||
mStartedSendingScrollEvents = false;
|
||||
mLauncherOverlay.onScrollInteractionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
public void setLauncherOverlay(LauncherOverlay overlay) {
|
||||
mLauncherOverlay = overlay;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void overScroll(float amount) {
|
||||
boolean isRtl = isLayoutRtl();
|
||||
boolean shouldOverScroll = (amount <= 0 && (!hasCustomContent() || isRtl)) ||
|
||||
(amount >= 0 && (!hasCustomContent() || !isRtl));
|
||||
|
||||
boolean shouldScrollOverlay = (amount <= 0 && mLauncherOverlay != null && !isRtl) ||
|
||||
(amount >= 0 && mLauncherOverlay != null && isRtl);
|
||||
|
||||
if (shouldScrollOverlay) {
|
||||
if (!mStartedSendingScrollEvents && mScrollInteractionBegan) {
|
||||
mStartedSendingScrollEvents = true;
|
||||
mLauncherOverlay.onScrollInteractionBegin();
|
||||
mShouldSendPageSettled = true;
|
||||
}
|
||||
int screenSize = getViewportWidth();
|
||||
float f = (amount / screenSize);
|
||||
|
||||
int progress = (int) Math.abs((f * 100));
|
||||
|
||||
mLauncherOverlay.onScrollChange(progress, isRtl);
|
||||
} else if (shouldOverScroll) {
|
||||
dampedOverScroll(amount);
|
||||
mOverScrollEffect = acceleratedOverFactor(amount);
|
||||
} else {
|
||||
mOverScrollEffect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1710,18 +1769,6 @@ public class Workspace extends SmoothPagedView
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void overScroll(float amount) {
|
||||
boolean shouldOverScroll = (amount < 0 && (!hasCustomContent() || isLayoutRtl())) ||
|
||||
(amount > 0 && (!hasCustomContent() || !isLayoutRtl()));
|
||||
if (shouldOverScroll) {
|
||||
dampedOverScroll(amount);
|
||||
mOverScrollEffect = acceleratedOverFactor(amount);
|
||||
} else {
|
||||
mOverScrollEffect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mWindowToken = getWindowToken();
|
||||
|
@ -2353,10 +2400,6 @@ public class Workspace extends SmoothPagedView
|
|||
.alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
|
||||
hotseatAlpha.addListener(new AlphaUpdateListener(hotseat));
|
||||
|
||||
Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
|
||||
.alpha(finalSearchBarAlpha).withLayer();
|
||||
searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
|
||||
|
||||
Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel)
|
||||
.alpha(finalOverviewPanelAlpha).withLayer();
|
||||
overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
|
||||
|
@ -2364,11 +2407,9 @@ public class Workspace extends SmoothPagedView
|
|||
// For animation optimations, we may need to provide the Launcher transition
|
||||
// with a set of views on which to force build layers in certain scenarios.
|
||||
hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
if (layerViews != null) {
|
||||
layerViews.add(hotseat);
|
||||
layerViews.add(searchBar);
|
||||
layerViews.add(overviewPanel);
|
||||
}
|
||||
|
||||
|
@ -2385,11 +2426,21 @@ public class Workspace extends SmoothPagedView
|
|||
overviewPanelAlpha.setDuration(duration);
|
||||
pageIndicatorAlpha.setDuration(duration);
|
||||
hotseatAlpha.setDuration(duration);
|
||||
searchBarAlpha.setDuration(duration);
|
||||
|
||||
if (searchBar != null) {
|
||||
Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
|
||||
.alpha(finalSearchBarAlpha).withLayer();
|
||||
searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
|
||||
searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
if (layerViews != null) {
|
||||
layerViews.add(searchBar);
|
||||
}
|
||||
searchBarAlpha.setDuration(duration);
|
||||
anim.play(searchBarAlpha);
|
||||
}
|
||||
|
||||
anim.play(overviewPanelAlpha);
|
||||
anim.play(hotseatAlpha);
|
||||
anim.play(searchBarAlpha);
|
||||
anim.play(pageIndicatorAlpha);
|
||||
anim.setStartDelay(delay);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue