Loading res/layout/widgets_full_sheet_search_and_recommendations.xml +2 −2 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> <LinearLayout <com.android.launcher3.widget.picker.SearchAndRecommendationsView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/search_and_recommendations_container" android:layout_width="match_parent" Loading Loading @@ -49,4 +49,4 @@ android:paddingVertical="@dimen/recommended_widgets_table_vertical_padding" android:layout_marginTop="16dp" android:visibility="gone"/> </LinearLayout> </com.android.launcher3.widget.picker.SearchAndRecommendationsView> src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java +45 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -62,6 +66,8 @@ final class SearchAndRecommendationsScrollController implements */ private int mCollapsibleHeightForTabs = 0; private boolean mShouldForwardToRecyclerView = false; SearchAndRecommendationsScrollController( boolean hasWorkProfile, int tabsHeight, Loading @@ -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; Loading Loading @@ -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) { Loading src/com/android/launcher3/widget/picker/SearchAndRecommendationsView.java 0 → 100644 +62 −0 Original line number Diff line number Diff line /* * 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. * * <p>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); } } src/com/android/launcher3/widget/picker/WidgetsFullSheet.java +3 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading
res/layout/widgets_full_sheet_search_and_recommendations.xml +2 −2 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> <LinearLayout <com.android.launcher3.widget.picker.SearchAndRecommendationsView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/search_and_recommendations_container" android:layout_width="match_parent" Loading Loading @@ -49,4 +49,4 @@ android:paddingVertical="@dimen/recommended_widgets_table_vertical_padding" android:layout_marginTop="16dp" android:visibility="gone"/> </LinearLayout> </com.android.launcher3.widget.picker.SearchAndRecommendationsView>
src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java +45 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -62,6 +66,8 @@ final class SearchAndRecommendationsScrollController implements */ private int mCollapsibleHeightForTabs = 0; private boolean mShouldForwardToRecyclerView = false; SearchAndRecommendationsScrollController( boolean hasWorkProfile, int tabsHeight, Loading @@ -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; Loading Loading @@ -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) { Loading
src/com/android/launcher3/widget/picker/SearchAndRecommendationsView.java 0 → 100644 +62 −0 Original line number Diff line number Diff line /* * 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. * * <p>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); } }
src/com/android/launcher3/widget/picker/WidgetsFullSheet.java +3 −2 Original line number Diff line number Diff line Loading @@ -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); Loading