Loading res/values/dimens.xml +3 −2 Original line number Diff line number Diff line Loading @@ -50,8 +50,6 @@ <dimen name="apps_container_width">0dp</dimen> <dimen name="apps_container_height">0dp</dimen> <dimen name="apps_container_inset">8dp</dimen> <!-- Note: This needs to match the fixed insets for the search box --> <dimen name="apps_container_fixed_bounds_inset">8dp</dimen> <dimen name="apps_grid_view_start_margin">52dp</dimen> <dimen name="apps_grid_section_y_offset">8dp</dimen> <dimen name="apps_view_row_height">64dp</dimen> Loading @@ -62,6 +60,9 @@ <dimen name="apps_view_fast_scroll_popup_size">64dp</dimen> <dimen name="apps_view_fast_scroll_text_size">40dp</dimen> <!-- Note: This needs to match the fixed insets for the search box. --> <dimen name="container_fixed_bounds_inset">8dp</dimen> <!-- AllApps/Customize/AppsCustomize --> <dimen name="app_icon_size">48dp</dimen> <dimen name="apps_customize_horizontal_padding">0dp</dimen> Loading src/com/android/launcher3/AppsContainerRecyclerView.java +2 −38 Original line number Diff line number Diff line Loading @@ -30,23 +30,15 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import com.android.launcher3.util.Thunk; import java.util.List; /** * A RecyclerView with custom fastscroll support. This is the main container for the all apps * icons. */ public class AppsContainerRecyclerView extends RecyclerView implements RecyclerView.OnItemTouchListener { public class AppsContainerRecyclerView extends BaseContainerRecyclerView { private static final float FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR = 1.5f; private static final int SCROLL_DELTA_THRESHOLD = 4; /** Keeps the last known scrolling delta/velocity along y-axis. */ @Thunk int mDy = 0; private float mDeltaThreshold; private AlphabeticalAppsList mApps; private int mNumAppsPerRow; Loading @@ -66,7 +58,6 @@ public class AppsContainerRecyclerView extends RecyclerView private int mScrollbarWidth; private int mScrollbarMinHeight; private int mScrollbarInset; private RecyclerView.OnScrollListener mScrollListenerProxy; public AppsContainerRecyclerView(Context context) { this(context, null); Loading Loading @@ -100,21 +91,6 @@ public class AppsContainerRecyclerView extends RecyclerView mScrollbarInset = res.getDimensionPixelSize(R.dimen.apps_view_fast_scroll_scrubber_touch_inset); setFastScrollerAlpha(getFastScrollerAlpha()); mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD; ScrollListener listener = new ScrollListener(); setOnScrollListener(listener); } private class ScrollListener extends RecyclerView.OnScrollListener { public ScrollListener() { } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { mDy = dy; mScrollListenerProxy.onScrolled(recyclerView, dx, dy); } } /** Loading @@ -131,13 +107,6 @@ public class AppsContainerRecyclerView extends RecyclerView mNumAppsPerRow = rowSize; } /** * Sets an additional scroll listener, not necessary in master support lib. */ public void setOnScrollListenerProxy(RecyclerView.OnScrollListener listener) { mScrollListenerProxy = listener; } /** * Sets the fast scroller alpha. */ Loading Loading @@ -187,10 +156,6 @@ public class AppsContainerRecyclerView extends RecyclerView handleTouchEvent(ev); } public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { // DO NOT REMOVE, NEEDED IMPLEMENTATION FOR M BUILDS } /** * Handles the touch event and determines whether to show the fast scroller (or updates it if * it is already showing). Loading @@ -206,8 +171,7 @@ public class AppsContainerRecyclerView extends RecyclerView // Keep track of the down positions mDownX = mLastX = x; mDownY = mLastY = y; if ((Math.abs(mDy) < mDeltaThreshold && getScrollState() != RecyclerView.SCROLL_STATE_IDLE)) { if (shouldStopScroll(ev)) { stopScroll(); } break; Loading src/com/android/launcher3/AppsContainerView.java +71 −102 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.view.ViewConfiguration; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher3.util.Thunk; Loading @@ -40,10 +39,10 @@ import java.util.List; /** * The all apps list view container. * The all apps view container. */ public class AppsContainerView extends FrameLayout implements DragSource, Insettable, TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable, View.OnTouchListener, public class AppsContainerView extends BaseContainerView implements DragSource, Insettable, TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable, View.OnTouchListener, View.OnClickListener, View.OnLongClickListener { public static final boolean GRID_MERGE_SECTIONS = true; Loading Loading @@ -73,13 +72,9 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett private int mNumAppsPerRow; private Point mLastTouchDownPos = new Point(-1, -1); private Point mLastTouchPos = new Point(); private Rect mInsets = new Rect(); private Rect mFixedBounds = new Rect(); private int mContentMarginStart; // Normal container insets private int mContainerInset; // Fixed bounds container insets private int mFixedBoundsContainerInset; // RecyclerView scroll position @Thunk int mRecyclerViewScrollY; Loading @@ -99,8 +94,6 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett mContainerInset = context.getResources().getDimensionPixelSize( R.dimen.apps_container_inset); mFixedBoundsContainerInset = context.getResources().getDimensionPixelSize( R.dimen.apps_container_fixed_bounds_inset); mLauncher = (Launcher) context; mNumAppsPerRow = grid.appsViewNumCols; mApps = new AlphabeticalAppsList(context, mNumAppsPerRow); Loading Loading @@ -146,8 +139,8 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett */ public void hideHeaderBar() { mHeaderView.setVisibility(View.GONE); updateBackgrounds(); updatePaddings(); onUpdateBackgrounds(); onUpdatePaddings(); } /** Loading Loading @@ -225,46 +218,81 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett if (mItemDecoration != null) { mAppsRecyclerView.addItemDecoration(mItemDecoration); } updateBackgrounds(); updatePaddings(); onUpdateBackgrounds(); onUpdatePaddings(); } @Override public void setInsets(Rect insets) { mInsets.set(insets); updatePaddings(); } /** * Sets the fixed bounds for this Apps view. */ public void setFixedBounds(Context context, Rect fixedBounds) { if (!fixedBounds.isEmpty() && !fixedBounds.equals(mFixedBounds)) { protected void onFixedBoundsUpdated() { // Update the number of items in the grid LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); if (grid.updateAppsViewNumCols(context.getResources(), fixedBounds.width())) { if (grid.updateAppsViewNumCols(getContext().getResources(), mFixedBounds.width())) { mNumAppsPerRow = grid.appsViewNumCols; mAppsRecyclerView.setNumAppsPerRow(mNumAppsPerRow); mAdapter.setNumAppsPerRow(mNumAppsPerRow); mApps.setNumAppsPerRow(mNumAppsPerRow); } } /** * Update the padding of the Apps view and children. To ensure that the RecyclerView has the * full width to handle touches right to the edge of the screen, we only apply the top and * bottom padding to the AppsContainerView and then the left/right padding on the RecyclerView * itself. In particular, the left/right padding is applied to the background of the view, * and then additionally inset by the start margin. */ @Override protected void onUpdatePaddings() { boolean isRtl = (getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL); boolean hasSearchBar = (mSearchBarEditView != null) && (mSearchBarEditView.getVisibility() == View.VISIBLE); mFixedBounds.set(fixedBounds); if (Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION) { mFixedBounds.top = mInsets.top; mFixedBounds.bottom = getMeasuredHeight(); if (mFixedBounds.isEmpty()) { // If there are no fixed bounds, then use the default padding and insets setPadding(mInsets.left, mContainerInset + mInsets.top, mInsets.right, mContainerInset + mInsets.bottom); } else { // If there are fixed bounds, then we update the padding to reflect the fixed bounds. setPadding(mFixedBounds.left, mFixedBounds.top, getMeasuredWidth() - mFixedBounds.right, mInsets.bottom); } // Update the apps recycler view, inset it by the container inset as well int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; if (isRtl) { mAppsRecyclerView.setPadding(inset, inset, inset + mContentMarginStart, inset); } else { mAppsRecyclerView.setPadding(inset + mContentMarginStart, inset, inset, inset); } // Post the updates since they can trigger a relayout, and this call can be triggered from // a layout pass itself. post(new Runnable() { @Override public void run() { updateBackgrounds(); updatePaddings(); // Update the header bar if (hasSearchBar) { LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mHeaderView.getLayoutParams(); lp.leftMargin = lp.rightMargin = inset; } }); } /** * Update the background of the Apps view and children. */ @Override protected void onUpdateBackgrounds() { int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; boolean hasSearchBar = (mSearchBarEditView != null) && (mSearchBarEditView.getVisibility() == View.VISIBLE); // Update the background of the reveal view and list to be inset with the fixed bound // insets instead of the default insets mAppsRecyclerView.setBackground(new InsetDrawable( getContext().getResources().getDrawable( hasSearchBar ? R.drawable.apps_list_search_bg : R.drawable.apps_list_bg), inset, 0, inset, 0)); getRevealView().setBackground(new InsetDrawable( getContext().getResources().getDrawable(R.drawable.apps_reveal_bg), inset, 0, inset, 0)); } @Override Loading Loading @@ -530,65 +558,6 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett return false; } /** * Update the padding of the Apps view and children. To ensure that the RecyclerView has the * full width to handle touches right to the edge of the screen, we only apply the top and * bottom padding to the AppsContainerView and then the left/right padding on the RecyclerView * itself. In particular, the left/right padding is applied to the background of the view, * and then additionally inset by the start margin. */ private void updatePaddings() { boolean isRtl = (getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL); boolean hasSearchBar = (mSearchBarEditView != null) && (mSearchBarEditView.getVisibility() == View.VISIBLE); if (mFixedBounds.isEmpty()) { // If there are no fixed bounds, then use the default padding and insets setPadding(mInsets.left, mContainerInset + mInsets.top, mInsets.right, mContainerInset + mInsets.bottom); } else { // If there are fixed bounds, then we update the padding to reflect the fixed bounds. setPadding(mFixedBounds.left, mFixedBounds.top + mFixedBoundsContainerInset, getMeasuredWidth() - mFixedBounds.right, mInsets.bottom + mFixedBoundsContainerInset); } // Update the apps recycler view int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; if (isRtl) { mAppsRecyclerView.setPadding(inset, inset, inset + mContentMarginStart, inset); } else { mAppsRecyclerView.setPadding(inset + mContentMarginStart, inset, inset, inset); } // Update the header if (hasSearchBar) { LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mHeaderView.getLayoutParams(); lp.leftMargin = lp.rightMargin = inset; } } /** * Update the background of the Apps view and children. */ private void updateBackgrounds() { int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; boolean hasSearchBar = (mSearchBarEditView != null) && (mSearchBarEditView.getVisibility() == View.VISIBLE); // Update the background of the reveal view and list to be inset with the fixed bound // insets instead of the default insets mAppsRecyclerView.setBackground(new InsetDrawable( getContext().getResources().getDrawable( hasSearchBar ? R.drawable.apps_list_search_bg : R.drawable.apps_list_bg), inset, 0, inset, 0)); getRevealView().setBackground(new InsetDrawable( getContext().getResources().getDrawable(R.drawable.apps_reveal_bg), inset, 0, inset, 0)); } /** * Shows the search field. */ Loading src/com/android/launcher3/BaseContainerRecyclerView.java 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.MotionEvent; import com.android.launcher3.util.Thunk; /** * A base {@link RecyclerView}, which will NOT intercept a touch sequence unless the scrolling * velocity is below a predefined threshold. */ public class BaseContainerRecyclerView extends RecyclerView implements RecyclerView.OnItemTouchListener { private static final int SCROLL_DELTA_THRESHOLD_DP = 4; /** Keeps the last known scrolling delta/velocity along y-axis. */ @Thunk int mDy = 0; private float mDeltaThreshold; private RecyclerView.OnScrollListener mScrollListenerProxy; public BaseContainerRecyclerView(Context context) { this(context, null); } public BaseContainerRecyclerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BaseContainerRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD_DP; ScrollListener listener = new ScrollListener(); setOnScrollListener(listener); } private class ScrollListener extends OnScrollListener { public ScrollListener() { // Do nothing } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { mDy = dy; if (mScrollListenerProxy != null) { mScrollListenerProxy.onScrolled(recyclerView, dx, dy); } } } /** * Sets an additional scroll listener, only needed for LMR1 version of the support lib. */ public void setOnScrollListenerProxy(RecyclerView.OnScrollListener listener) { mScrollListenerProxy = listener; } @Override protected void onFinishInflate() { super.onFinishInflate(); addOnItemTouchListener(this); } @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) { if (shouldStopScroll(ev)) { stopScroll(); } return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent ev) { // Do nothing. } public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { // DO NOT REMOVE, NEEDED IMPLEMENTATION FOR M BUILDS } /** * Returns whether this {@link MotionEvent} should trigger the scroll to be stopped. */ protected boolean shouldStopScroll(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { if ((Math.abs(mDy) < mDeltaThreshold && getScrollState() != RecyclerView.SCROLL_STATE_IDLE)) { // now the touch events are being passed to the {@link WidgetCell} until the // touch sequence goes over the touch slop. return true; } } return false; } } No newline at end of file src/com/android/launcher3/BaseContainerView.java 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.widget.FrameLayout; /** * A base container view, which supports resizing. */ public class BaseContainerView extends FrameLayout implements Insettable { protected Rect mInsets = new Rect(); protected Rect mFixedBounds = new Rect(); protected int mFixedBoundsContainerInset; public BaseContainerView(Context context) { this(context, null); } public BaseContainerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BaseContainerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mFixedBoundsContainerInset = context.getResources().getDimensionPixelSize( R.dimen.container_fixed_bounds_inset); } @Override final public void setInsets(Rect insets) { mInsets.set(insets); onUpdateBackgrounds(); onUpdatePaddings(); } /** * Sets the fixed bounds for this container view. */ final public void setFixedBounds(Rect fixedBounds) { if (!fixedBounds.isEmpty() && !fixedBounds.equals(mFixedBounds)) { mFixedBounds.set(fixedBounds); if (Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION) { mFixedBounds.top = mInsets.top; mFixedBounds.bottom = getMeasuredHeight(); } // To ensure that the child RecyclerView has the full width to handle touches right to // the edge of the screen, we only apply the top and bottom padding to the bounds mFixedBounds.inset(0, mFixedBoundsContainerInset); onFixedBoundsUpdated(); } // Post the updates since they can trigger a relayout, and this call can be triggered from // a layout pass itself. post(new Runnable() { @Override public void run() { onUpdateBackgrounds(); onUpdatePaddings(); } }); } /** * Update the UI in response to a change in the fixed bounds. */ protected void onFixedBoundsUpdated() { // Do nothing } /** * Update the paddings in response to a change in the bounds or insets. */ protected void onUpdatePaddings() { // Do nothing } /** * Update the backgrounds in response to a change in the bounds or insets. */ protected void onUpdateBackgrounds() { // Do nothing } } No newline at end of file Loading
res/values/dimens.xml +3 −2 Original line number Diff line number Diff line Loading @@ -50,8 +50,6 @@ <dimen name="apps_container_width">0dp</dimen> <dimen name="apps_container_height">0dp</dimen> <dimen name="apps_container_inset">8dp</dimen> <!-- Note: This needs to match the fixed insets for the search box --> <dimen name="apps_container_fixed_bounds_inset">8dp</dimen> <dimen name="apps_grid_view_start_margin">52dp</dimen> <dimen name="apps_grid_section_y_offset">8dp</dimen> <dimen name="apps_view_row_height">64dp</dimen> Loading @@ -62,6 +60,9 @@ <dimen name="apps_view_fast_scroll_popup_size">64dp</dimen> <dimen name="apps_view_fast_scroll_text_size">40dp</dimen> <!-- Note: This needs to match the fixed insets for the search box. --> <dimen name="container_fixed_bounds_inset">8dp</dimen> <!-- AllApps/Customize/AppsCustomize --> <dimen name="app_icon_size">48dp</dimen> <dimen name="apps_customize_horizontal_padding">0dp</dimen> Loading
src/com/android/launcher3/AppsContainerRecyclerView.java +2 −38 Original line number Diff line number Diff line Loading @@ -30,23 +30,15 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import com.android.launcher3.util.Thunk; import java.util.List; /** * A RecyclerView with custom fastscroll support. This is the main container for the all apps * icons. */ public class AppsContainerRecyclerView extends RecyclerView implements RecyclerView.OnItemTouchListener { public class AppsContainerRecyclerView extends BaseContainerRecyclerView { private static final float FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR = 1.5f; private static final int SCROLL_DELTA_THRESHOLD = 4; /** Keeps the last known scrolling delta/velocity along y-axis. */ @Thunk int mDy = 0; private float mDeltaThreshold; private AlphabeticalAppsList mApps; private int mNumAppsPerRow; Loading @@ -66,7 +58,6 @@ public class AppsContainerRecyclerView extends RecyclerView private int mScrollbarWidth; private int mScrollbarMinHeight; private int mScrollbarInset; private RecyclerView.OnScrollListener mScrollListenerProxy; public AppsContainerRecyclerView(Context context) { this(context, null); Loading Loading @@ -100,21 +91,6 @@ public class AppsContainerRecyclerView extends RecyclerView mScrollbarInset = res.getDimensionPixelSize(R.dimen.apps_view_fast_scroll_scrubber_touch_inset); setFastScrollerAlpha(getFastScrollerAlpha()); mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD; ScrollListener listener = new ScrollListener(); setOnScrollListener(listener); } private class ScrollListener extends RecyclerView.OnScrollListener { public ScrollListener() { } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { mDy = dy; mScrollListenerProxy.onScrolled(recyclerView, dx, dy); } } /** Loading @@ -131,13 +107,6 @@ public class AppsContainerRecyclerView extends RecyclerView mNumAppsPerRow = rowSize; } /** * Sets an additional scroll listener, not necessary in master support lib. */ public void setOnScrollListenerProxy(RecyclerView.OnScrollListener listener) { mScrollListenerProxy = listener; } /** * Sets the fast scroller alpha. */ Loading Loading @@ -187,10 +156,6 @@ public class AppsContainerRecyclerView extends RecyclerView handleTouchEvent(ev); } public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { // DO NOT REMOVE, NEEDED IMPLEMENTATION FOR M BUILDS } /** * Handles the touch event and determines whether to show the fast scroller (or updates it if * it is already showing). Loading @@ -206,8 +171,7 @@ public class AppsContainerRecyclerView extends RecyclerView // Keep track of the down positions mDownX = mLastX = x; mDownY = mLastY = y; if ((Math.abs(mDy) < mDeltaThreshold && getScrollState() != RecyclerView.SCROLL_STATE_IDLE)) { if (shouldStopScroll(ev)) { stopScroll(); } break; Loading
src/com/android/launcher3/AppsContainerView.java +71 −102 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.view.ViewConfiguration; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher3.util.Thunk; Loading @@ -40,10 +39,10 @@ import java.util.List; /** * The all apps list view container. * The all apps view container. */ public class AppsContainerView extends FrameLayout implements DragSource, Insettable, TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable, View.OnTouchListener, public class AppsContainerView extends BaseContainerView implements DragSource, Insettable, TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable, View.OnTouchListener, View.OnClickListener, View.OnLongClickListener { public static final boolean GRID_MERGE_SECTIONS = true; Loading Loading @@ -73,13 +72,9 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett private int mNumAppsPerRow; private Point mLastTouchDownPos = new Point(-1, -1); private Point mLastTouchPos = new Point(); private Rect mInsets = new Rect(); private Rect mFixedBounds = new Rect(); private int mContentMarginStart; // Normal container insets private int mContainerInset; // Fixed bounds container insets private int mFixedBoundsContainerInset; // RecyclerView scroll position @Thunk int mRecyclerViewScrollY; Loading @@ -99,8 +94,6 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett mContainerInset = context.getResources().getDimensionPixelSize( R.dimen.apps_container_inset); mFixedBoundsContainerInset = context.getResources().getDimensionPixelSize( R.dimen.apps_container_fixed_bounds_inset); mLauncher = (Launcher) context; mNumAppsPerRow = grid.appsViewNumCols; mApps = new AlphabeticalAppsList(context, mNumAppsPerRow); Loading Loading @@ -146,8 +139,8 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett */ public void hideHeaderBar() { mHeaderView.setVisibility(View.GONE); updateBackgrounds(); updatePaddings(); onUpdateBackgrounds(); onUpdatePaddings(); } /** Loading Loading @@ -225,46 +218,81 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett if (mItemDecoration != null) { mAppsRecyclerView.addItemDecoration(mItemDecoration); } updateBackgrounds(); updatePaddings(); onUpdateBackgrounds(); onUpdatePaddings(); } @Override public void setInsets(Rect insets) { mInsets.set(insets); updatePaddings(); } /** * Sets the fixed bounds for this Apps view. */ public void setFixedBounds(Context context, Rect fixedBounds) { if (!fixedBounds.isEmpty() && !fixedBounds.equals(mFixedBounds)) { protected void onFixedBoundsUpdated() { // Update the number of items in the grid LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); if (grid.updateAppsViewNumCols(context.getResources(), fixedBounds.width())) { if (grid.updateAppsViewNumCols(getContext().getResources(), mFixedBounds.width())) { mNumAppsPerRow = grid.appsViewNumCols; mAppsRecyclerView.setNumAppsPerRow(mNumAppsPerRow); mAdapter.setNumAppsPerRow(mNumAppsPerRow); mApps.setNumAppsPerRow(mNumAppsPerRow); } } /** * Update the padding of the Apps view and children. To ensure that the RecyclerView has the * full width to handle touches right to the edge of the screen, we only apply the top and * bottom padding to the AppsContainerView and then the left/right padding on the RecyclerView * itself. In particular, the left/right padding is applied to the background of the view, * and then additionally inset by the start margin. */ @Override protected void onUpdatePaddings() { boolean isRtl = (getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL); boolean hasSearchBar = (mSearchBarEditView != null) && (mSearchBarEditView.getVisibility() == View.VISIBLE); mFixedBounds.set(fixedBounds); if (Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION) { mFixedBounds.top = mInsets.top; mFixedBounds.bottom = getMeasuredHeight(); if (mFixedBounds.isEmpty()) { // If there are no fixed bounds, then use the default padding and insets setPadding(mInsets.left, mContainerInset + mInsets.top, mInsets.right, mContainerInset + mInsets.bottom); } else { // If there are fixed bounds, then we update the padding to reflect the fixed bounds. setPadding(mFixedBounds.left, mFixedBounds.top, getMeasuredWidth() - mFixedBounds.right, mInsets.bottom); } // Update the apps recycler view, inset it by the container inset as well int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; if (isRtl) { mAppsRecyclerView.setPadding(inset, inset, inset + mContentMarginStart, inset); } else { mAppsRecyclerView.setPadding(inset + mContentMarginStart, inset, inset, inset); } // Post the updates since they can trigger a relayout, and this call can be triggered from // a layout pass itself. post(new Runnable() { @Override public void run() { updateBackgrounds(); updatePaddings(); // Update the header bar if (hasSearchBar) { LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mHeaderView.getLayoutParams(); lp.leftMargin = lp.rightMargin = inset; } }); } /** * Update the background of the Apps view and children. */ @Override protected void onUpdateBackgrounds() { int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; boolean hasSearchBar = (mSearchBarEditView != null) && (mSearchBarEditView.getVisibility() == View.VISIBLE); // Update the background of the reveal view and list to be inset with the fixed bound // insets instead of the default insets mAppsRecyclerView.setBackground(new InsetDrawable( getContext().getResources().getDrawable( hasSearchBar ? R.drawable.apps_list_search_bg : R.drawable.apps_list_bg), inset, 0, inset, 0)); getRevealView().setBackground(new InsetDrawable( getContext().getResources().getDrawable(R.drawable.apps_reveal_bg), inset, 0, inset, 0)); } @Override Loading Loading @@ -530,65 +558,6 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett return false; } /** * Update the padding of the Apps view and children. To ensure that the RecyclerView has the * full width to handle touches right to the edge of the screen, we only apply the top and * bottom padding to the AppsContainerView and then the left/right padding on the RecyclerView * itself. In particular, the left/right padding is applied to the background of the view, * and then additionally inset by the start margin. */ private void updatePaddings() { boolean isRtl = (getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL); boolean hasSearchBar = (mSearchBarEditView != null) && (mSearchBarEditView.getVisibility() == View.VISIBLE); if (mFixedBounds.isEmpty()) { // If there are no fixed bounds, then use the default padding and insets setPadding(mInsets.left, mContainerInset + mInsets.top, mInsets.right, mContainerInset + mInsets.bottom); } else { // If there are fixed bounds, then we update the padding to reflect the fixed bounds. setPadding(mFixedBounds.left, mFixedBounds.top + mFixedBoundsContainerInset, getMeasuredWidth() - mFixedBounds.right, mInsets.bottom + mFixedBoundsContainerInset); } // Update the apps recycler view int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; if (isRtl) { mAppsRecyclerView.setPadding(inset, inset, inset + mContentMarginStart, inset); } else { mAppsRecyclerView.setPadding(inset + mContentMarginStart, inset, inset, inset); } // Update the header if (hasSearchBar) { LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mHeaderView.getLayoutParams(); lp.leftMargin = lp.rightMargin = inset; } } /** * Update the background of the Apps view and children. */ private void updateBackgrounds() { int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset; boolean hasSearchBar = (mSearchBarEditView != null) && (mSearchBarEditView.getVisibility() == View.VISIBLE); // Update the background of the reveal view and list to be inset with the fixed bound // insets instead of the default insets mAppsRecyclerView.setBackground(new InsetDrawable( getContext().getResources().getDrawable( hasSearchBar ? R.drawable.apps_list_search_bg : R.drawable.apps_list_bg), inset, 0, inset, 0)); getRevealView().setBackground(new InsetDrawable( getContext().getResources().getDrawable(R.drawable.apps_reveal_bg), inset, 0, inset, 0)); } /** * Shows the search field. */ Loading
src/com/android/launcher3/BaseContainerRecyclerView.java 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.MotionEvent; import com.android.launcher3.util.Thunk; /** * A base {@link RecyclerView}, which will NOT intercept a touch sequence unless the scrolling * velocity is below a predefined threshold. */ public class BaseContainerRecyclerView extends RecyclerView implements RecyclerView.OnItemTouchListener { private static final int SCROLL_DELTA_THRESHOLD_DP = 4; /** Keeps the last known scrolling delta/velocity along y-axis. */ @Thunk int mDy = 0; private float mDeltaThreshold; private RecyclerView.OnScrollListener mScrollListenerProxy; public BaseContainerRecyclerView(Context context) { this(context, null); } public BaseContainerRecyclerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BaseContainerRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD_DP; ScrollListener listener = new ScrollListener(); setOnScrollListener(listener); } private class ScrollListener extends OnScrollListener { public ScrollListener() { // Do nothing } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { mDy = dy; if (mScrollListenerProxy != null) { mScrollListenerProxy.onScrolled(recyclerView, dx, dy); } } } /** * Sets an additional scroll listener, only needed for LMR1 version of the support lib. */ public void setOnScrollListenerProxy(RecyclerView.OnScrollListener listener) { mScrollListenerProxy = listener; } @Override protected void onFinishInflate() { super.onFinishInflate(); addOnItemTouchListener(this); } @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) { if (shouldStopScroll(ev)) { stopScroll(); } return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent ev) { // Do nothing. } public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { // DO NOT REMOVE, NEEDED IMPLEMENTATION FOR M BUILDS } /** * Returns whether this {@link MotionEvent} should trigger the scroll to be stopped. */ protected boolean shouldStopScroll(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { if ((Math.abs(mDy) < mDeltaThreshold && getScrollState() != RecyclerView.SCROLL_STATE_IDLE)) { // now the touch events are being passed to the {@link WidgetCell} until the // touch sequence goes over the touch slop. return true; } } return false; } } No newline at end of file
src/com/android/launcher3/BaseContainerView.java 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.widget.FrameLayout; /** * A base container view, which supports resizing. */ public class BaseContainerView extends FrameLayout implements Insettable { protected Rect mInsets = new Rect(); protected Rect mFixedBounds = new Rect(); protected int mFixedBoundsContainerInset; public BaseContainerView(Context context) { this(context, null); } public BaseContainerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BaseContainerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mFixedBoundsContainerInset = context.getResources().getDimensionPixelSize( R.dimen.container_fixed_bounds_inset); } @Override final public void setInsets(Rect insets) { mInsets.set(insets); onUpdateBackgrounds(); onUpdatePaddings(); } /** * Sets the fixed bounds for this container view. */ final public void setFixedBounds(Rect fixedBounds) { if (!fixedBounds.isEmpty() && !fixedBounds.equals(mFixedBounds)) { mFixedBounds.set(fixedBounds); if (Launcher.DISABLE_ALL_APPS_SEARCH_INTEGRATION) { mFixedBounds.top = mInsets.top; mFixedBounds.bottom = getMeasuredHeight(); } // To ensure that the child RecyclerView has the full width to handle touches right to // the edge of the screen, we only apply the top and bottom padding to the bounds mFixedBounds.inset(0, mFixedBoundsContainerInset); onFixedBoundsUpdated(); } // Post the updates since they can trigger a relayout, and this call can be triggered from // a layout pass itself. post(new Runnable() { @Override public void run() { onUpdateBackgrounds(); onUpdatePaddings(); } }); } /** * Update the UI in response to a change in the fixed bounds. */ protected void onFixedBoundsUpdated() { // Do nothing } /** * Update the paddings in response to a change in the bounds or insets. */ protected void onUpdatePaddings() { // Do nothing } /** * Update the backgrounds in response to a change in the bounds or insets. */ protected void onUpdateBackgrounds() { // Do nothing } } No newline at end of file