Adds ability to use LauncherPreviewRenderer in Sandbox.
This is mostly a proof-of-concept for future use and tweaks as desired by UX. The idea is to better replicate the actual UI. Screenshot: https://drive.google.com/file/d/1EGDgcrSH2QZuSh6P3zWLBl6L8Xd-gtFY/view?usp=sharing Bug: 148542211 Change-Id: Ibed4b8118346ef72599463c9fd6a2f71166993fd
This commit is contained in:
parent
7144004c56
commit
9e754b008d
|
@ -13,7 +13,8 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.android.quickstep.interaction.RootSandboxLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/colorBackground">
|
||||
|
@ -93,11 +94,11 @@
|
|||
style="@style/TextAppearance.GestureTutorial.Feedback"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/gesture_tutorial_fragment_action_button"
|
||||
android:layout_below="@id/gesture_tutorial_fragment_titles_container"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end"
|
||||
android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end"
|
||||
android:layout_marginBottom="10dp"/>
|
||||
android:layout_marginTop="40dp"/>
|
||||
|
||||
<!-- android:stateListAnimator="@null" removes shadow and normal on click behavior (increase
|
||||
of elevation and shadow) which is replaced by ripple effect in android:foreground -->
|
||||
|
@ -126,4 +127,4 @@
|
|||
android:background="@null"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:stateListAnimator="@null"/>
|
||||
</RelativeLayout>
|
||||
</com.android.quickstep.interaction.RootSandboxLayout>
|
|
@ -143,6 +143,10 @@ public class EdgeBackGestureHandler implements OnTouchListener {
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean onInterceptTouch(MotionEvent motionEvent) {
|
||||
return isWithinTouchRegion((int) motionEvent.getX(), (int) motionEvent.getY());
|
||||
}
|
||||
|
||||
private boolean isWithinTouchRegion(int x, int y) {
|
||||
// Disallow if too far from the edge
|
||||
if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) {
|
||||
|
|
|
@ -250,6 +250,12 @@ public class NavBarGestureHandler implements OnTouchListener,
|
|||
return intercepted;
|
||||
}
|
||||
|
||||
boolean onInterceptTouch(MotionEvent event) {
|
||||
return mAssistantLeftRegion.contains(event.getX(), event.getY())
|
||||
|| mAssistantRightRegion.contains(event.getX(), event.getY())
|
||||
|| event.getY() >= mDisplaySize.y - mBottomGestureHeight;
|
||||
}
|
||||
|
||||
protected void onMotionPauseDetected() {
|
||||
VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2020 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.quickstep.interaction;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
/** Root layout that TutorialFragment uses to intercept motion events. */
|
||||
public class RootSandboxLayout extends RelativeLayout {
|
||||
public RootSandboxLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public RootSandboxLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public RootSandboxLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent motionEvent) {
|
||||
return ((TutorialFragment) FragmentManager.findFragment(this))
|
||||
.onInterceptTouch(motionEvent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2020 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.quickstep.interaction;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||
|
||||
/** Renders a fake Launcher for use in the Sandbox. */
|
||||
class SandboxLauncherRenderer extends LauncherPreviewRenderer {
|
||||
SandboxLauncherRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) {
|
||||
super(context, idp, migrated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShowRealLauncherPreview() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShowQsb() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View.OnLongClickListener getWorkspaceChildOnLongClickListener() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
final TextView mTitleTextView;
|
||||
final TextView mSubtitleTextView;
|
||||
final TextView mFeedbackView;
|
||||
final View mLauncherView;
|
||||
final ClipIconView mFakeIconView;
|
||||
final View mFakeTaskView;
|
||||
final View mRippleView;
|
||||
|
@ -68,6 +69,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view);
|
||||
mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view);
|
||||
mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
|
||||
mLauncherView = tutorialFragment.getLauncherView();
|
||||
mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view);
|
||||
mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view);
|
||||
mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view);
|
||||
|
@ -162,8 +164,10 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
|
||||
if (isComplete()) {
|
||||
hideHandCoachingAnimation();
|
||||
mLauncherView.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
showHandCoachingAnimation();
|
||||
mLauncherView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import androidx.annotation.Nullable;
|
|||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.interaction.TutorialController.TutorialType;
|
||||
|
||||
|
@ -45,6 +46,7 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
TutorialHandAnimation mHandCoachingAnimation;
|
||||
EdgeBackGestureHandler mEdgeBackGestureHandler;
|
||||
NavBarGestureHandler mNavBarGestureHandler;
|
||||
private View mLauncherView;
|
||||
|
||||
public static TutorialFragment newInstance(TutorialType tutorialType) {
|
||||
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
|
||||
|
@ -114,8 +116,11 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
return insets;
|
||||
});
|
||||
mRootView.setOnTouchListener(this);
|
||||
mHandCoachingAnimation = new TutorialHandAnimation(getContext(), mRootView,
|
||||
getHandAnimationResId());
|
||||
mHandCoachingAnimation =
|
||||
new TutorialHandAnimation(getContext(), mRootView, getHandAnimationResId());
|
||||
InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(getContext());
|
||||
mLauncherView = new SandboxLauncherRenderer(getContext(), dp, true).getRenderedView();
|
||||
((ViewGroup) mRootView).addView(mLauncherView, 0);
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
|
@ -133,11 +138,17 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
// Note: Using logical or to ensure both functions get called.
|
||||
// Note: Using logical-or to ensure both functions get called.
|
||||
return mEdgeBackGestureHandler.onTouch(view, motionEvent)
|
||||
| mNavBarGestureHandler.onTouch(view, motionEvent);
|
||||
}
|
||||
|
||||
boolean onInterceptTouch(MotionEvent motionEvent) {
|
||||
// Note: Using logical-or to ensure both functions get called.
|
||||
return mEdgeBackGestureHandler.onInterceptTouch(motionEvent)
|
||||
| mNavBarGestureHandler.onInterceptTouch(motionEvent);
|
||||
}
|
||||
|
||||
void onAttachedToWindow() {
|
||||
mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
|
||||
}
|
||||
|
@ -168,6 +179,10 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
return mRootView;
|
||||
}
|
||||
|
||||
View getLauncherView() {
|
||||
return mLauncherView;
|
||||
}
|
||||
|
||||
TutorialHandAnimation getHandAnimation() {
|
||||
return mHandCoachingAnimation;
|
||||
}
|
||||
|
|
|
@ -323,11 +323,8 @@ public class CellLayout extends ViewGroup {
|
|||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (mTouchHelper != null
|
||||
|| (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return mTouchHelper != null
|
||||
|| (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev));
|
||||
}
|
||||
|
||||
public void enableHardwareLayer(boolean hasLayer) {
|
||||
|
|
|
@ -130,12 +130,16 @@ public interface WorkspaceLayoutManager {
|
|||
}
|
||||
|
||||
child.setHapticFeedbackEnabled(false);
|
||||
child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
|
||||
child.setOnLongClickListener(getWorkspaceChildOnLongClickListener());
|
||||
if (child instanceof DropTarget) {
|
||||
onAddDropTarget((DropTarget) child);
|
||||
}
|
||||
}
|
||||
|
||||
default View.OnLongClickListener getWorkspaceChildOnLongClickListener() {
|
||||
return ItemLongClickListener.INSTANCE_WORKSPACE;
|
||||
}
|
||||
|
||||
Hotseat getHotseat();
|
||||
|
||||
CellLayout getScreenWithId(int screenId);
|
||||
|
|
|
@ -513,8 +513,7 @@ public class LauncherPreviewRenderer extends ContextThemeWrapper
|
|||
}
|
||||
|
||||
// Setup search view
|
||||
SearchUiManager searchUiManager =
|
||||
mRootView.findViewById(R.id.search_container_all_apps);
|
||||
SearchUiManager searchUiManager = mRootView.findViewById(R.id.search_container_all_apps);
|
||||
mRootView.findViewById(R.id.apps_view).setTranslationY(
|
||||
mDp.heightPx - searchUiManager.getScrollRangeDelta(mInsets));
|
||||
ViewGroup searchView = (ViewGroup) searchUiManager;
|
||||
|
|
Loading…
Reference in New Issue