diff --git a/res/layout/widgets_full_sheet_search_and_recommendations.xml b/res/layout/widgets_full_sheet_search_and_recommendations.xml index bfce01d148..ce7a682376 100644 --- a/res/layout/widgets_full_sheet_search_and_recommendations.xml +++ b/res/layout/widgets_full_sheet_search_and_recommendations.xml @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - - + diff --git a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java index 7f840776b2..d09cb8a52d 100644 --- a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java +++ b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java @@ -15,6 +15,8 @@ */ package com.android.launcher3.widget.picker; +import android.graphics.Point; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; import android.widget.RelativeLayout; @@ -33,9 +35,11 @@ final class SearchAndRecommendationsScrollController implements RecyclerViewFastScroller.OnFastScrollChangeListener { private final boolean mHasWorkProfile; private final SearchAndRecommendationViewHolder mViewHolder; + private final View mSearchAndRecommendationViewParent; private final WidgetsRecyclerView mPrimaryRecyclerView; private final WidgetsRecyclerView mSearchRecyclerView; private final int mTabsHeight; + private final Point mTempOffset = new Point(); // The following are only non null if mHasWorkProfile is true. @Nullable private final WidgetsRecyclerView mWorkRecyclerView; @@ -62,6 +66,8 @@ final class SearchAndRecommendationsScrollController implements */ private int mCollapsibleHeightForTabs = 0; + private boolean mShouldForwardToRecyclerView = false; + SearchAndRecommendationsScrollController( boolean hasWorkProfile, int tabsHeight, @@ -73,6 +79,8 @@ final class SearchAndRecommendationsScrollController implements @Nullable PersonalWorkPagedView primaryWorkViewPager) { mHasWorkProfile = hasWorkProfile; mViewHolder = viewHolder; + mViewHolder.mContainer.setSearchAndRecommendationScrollController(this); + mSearchAndRecommendationViewParent = (View) mViewHolder.mContainer.getParent(); mPrimaryRecyclerView = primaryRecyclerView; mCurrentRecyclerView = mPrimaryRecyclerView; mWorkRecyclerView = workRecyclerView; @@ -245,6 +253,43 @@ final class SearchAndRecommendationsScrollController implements } } + /** + * Returns {@code true} if a touch event should be intercepted by this controller. + */ + public boolean onInterceptTouchEvent(MotionEvent event) { + calculateMotionEventOffset(mTempOffset); + event.offsetLocation(mTempOffset.x, mTempOffset.y); + try { + mShouldForwardToRecyclerView = mCurrentRecyclerView.onInterceptTouchEvent(event); + return mShouldForwardToRecyclerView; + } finally { + event.offsetLocation(-mTempOffset.x, -mTempOffset.y); + } + } + + /** + * Returns {@code true} if this controller has intercepted and consumed a touch event. + */ + public boolean onTouchEvent(MotionEvent event) { + if (mShouldForwardToRecyclerView) { + calculateMotionEventOffset(mTempOffset); + event.offsetLocation(mTempOffset.x, mTempOffset.y); + try { + return mCurrentRecyclerView.onTouchEvent(event); + } finally { + event.offsetLocation(-mTempOffset.x, -mTempOffset.y); + } + } + return false; + } + + private void calculateMotionEventOffset(Point p) { + p.x = mViewHolder.mContainer.getLeft() - mCurrentRecyclerView.getLeft() + - mSearchAndRecommendationViewParent.getLeft(); + p.y = mViewHolder.mContainer.getTop() - mCurrentRecyclerView.getTop() + - mSearchAndRecommendationViewParent.getTop(); + } + /** private the height, in pixel, + the vertical margins of a given view. */ private static int measureHeightWithVerticalMargins(View view) { if (view.getVisibility() != View.VISIBLE) { diff --git a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsView.java b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsView.java new file mode 100644 index 0000000000..0d7d2b5e78 --- /dev/null +++ b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsView.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 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.launcher3.widget.picker; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.LinearLayout; + +/** + * A {@link LinearLayout} container for holding search and widgets recommendation. + * + *

This class intercepts touch events and dispatch them to the right view. + */ +public class SearchAndRecommendationsView extends LinearLayout { + private SearchAndRecommendationsScrollController mController; + + public SearchAndRecommendationsView(Context context) { + this(context, /* attrs= */ null); + } + + public SearchAndRecommendationsView(Context context, AttributeSet attrs) { + this(context, attrs, /* defStyleAttr= */ 0); + } + + public SearchAndRecommendationsView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, /* defStyleRes= */ 0); + } + + public SearchAndRecommendationsView(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public void setSearchAndRecommendationScrollController( + SearchAndRecommendationsScrollController controller) { + mController = controller; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + return mController.onInterceptTouchEvent(event) || super.onInterceptTouchEvent(event); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return mController.onTouchEvent(event) || super.onTouchEvent(event); + } +} diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java index b4d48562be..b1c5ffcbab 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java +++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java @@ -709,13 +709,14 @@ public class WidgetsFullSheet extends BaseWidgetSheet } final class SearchAndRecommendationViewHolder { - final ViewGroup mContainer; + final SearchAndRecommendationsView mContainer; final View mCollapseHandle; final WidgetsSearchBar mSearchBar; final TextView mHeaderTitle; final WidgetsRecommendationTableLayout mRecommendedWidgetsTable; - SearchAndRecommendationViewHolder(ViewGroup searchAndRecommendationContainer) { + SearchAndRecommendationViewHolder( + SearchAndRecommendationsView searchAndRecommendationContainer) { mContainer = searchAndRecommendationContainer; mCollapseHandle = mContainer.findViewById(R.id.collapse_handle); mSearchBar = mContainer.findViewById(R.id.widgets_search_bar);