Merge "Make common base class to update container bounds and to handle scroll logic." into ub-launcher3-burnaby
This commit is contained in:
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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).
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
@@ -146,8 +139,8 @@ public class AppsContainerView extends FrameLayout implements DragSource, Insett
|
||||
*/
|
||||
public void hideHeaderBar() {
|
||||
mHeaderView.setVisibility(View.GONE);
|
||||
updateBackgrounds();
|
||||
updatePaddings();
|
||||
onUpdateBackgrounds();
|
||||
onUpdatePaddings();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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();
|
||||
protected void onFixedBoundsUpdated() {
|
||||
// Update the number of items in the grid
|
||||
LauncherAppState app = LauncherAppState.getInstance();
|
||||
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
|
||||
if (grid.updateAppsViewNumCols(getContext().getResources(), mFixedBounds.width())) {
|
||||
mNumAppsPerRow = grid.appsViewNumCols;
|
||||
mAppsRecyclerView.setNumAppsPerRow(mNumAppsPerRow);
|
||||
mAdapter.setNumAppsPerRow(mNumAppsPerRow);
|
||||
mApps.setNumAppsPerRow(mNumAppsPerRow);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fixed bounds for this Apps view.
|
||||
* 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.
|
||||
*/
|
||||
public void setFixedBounds(Context context, Rect fixedBounds) {
|
||||
if (!fixedBounds.isEmpty() && !fixedBounds.equals(mFixedBounds)) {
|
||||
// Update the number of items in the grid
|
||||
LauncherAppState app = LauncherAppState.getInstance();
|
||||
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
|
||||
if (grid.updateAppsViewNumCols(context.getResources(), fixedBounds.width())) {
|
||||
mNumAppsPerRow = grid.appsViewNumCols;
|
||||
mAppsRecyclerView.setNumAppsPerRow(mNumAppsPerRow);
|
||||
mAdapter.setNumAppsPerRow(mNumAppsPerRow);
|
||||
mApps.setNumAppsPerRow(mNumAppsPerRow);
|
||||
}
|
||||
@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);
|
||||
}
|
||||
// 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 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);
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
@@ -528,7 +528,8 @@ public class Launcher extends Activity
|
||||
if (LOGD) {
|
||||
Log.d(TAG, "onAllAppsBoundsChanged(Rect): " + bounds);
|
||||
}
|
||||
mAppsView.setFixedBounds(Launcher.this, bounds);
|
||||
mAppsView.setFixedBounds(bounds);
|
||||
mWidgetsView.setFixedBounds(bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,26 +17,13 @@
|
||||
package com.android.launcher3.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.BaseContainerRecyclerView;
|
||||
|
||||
/**
|
||||
* The widgets recycler view container.
|
||||
* <p>
|
||||
* Overwritten to NOT intercept a touch sequence that started when the {@link RecycleView}
|
||||
* scrolling slowing down below the internally defined threshold.
|
||||
*/
|
||||
public class WidgetsContainerRecyclerView extends RecyclerView
|
||||
implements RecyclerView.OnItemTouchListener {
|
||||
|
||||
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;
|
||||
public class WidgetsContainerRecyclerView extends BaseContainerRecyclerView {
|
||||
|
||||
public WidgetsContainerRecyclerView(Context context) {
|
||||
this(context, null);
|
||||
@@ -48,47 +35,6 @@ public class WidgetsContainerRecyclerView extends RecyclerView
|
||||
|
||||
public WidgetsContainerRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
addOnItemTouchListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(RecyclerView rv, 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.
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,9 @@ import android.support.v7.widget.RecyclerView.State;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.launcher3.BaseContainerView;
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DeleteDropTarget;
|
||||
import com.android.launcher3.DragController;
|
||||
@@ -55,8 +54,8 @@ import java.util.ArrayList;
|
||||
/**
|
||||
* The widgets list view container.
|
||||
*/
|
||||
public class WidgetsContainerView extends FrameLayout implements Insettable,
|
||||
View.OnLongClickListener, View.OnClickListener, DragSource{
|
||||
public class WidgetsContainerView extends BaseContainerView
|
||||
implements View.OnLongClickListener, View.OnClickListener, DragSource{
|
||||
|
||||
private static final String TAG = "WidgetsContainerView";
|
||||
private static final boolean DEBUG = false;
|
||||
@@ -129,6 +128,7 @@ public class WidgetsContainerView extends FrameLayout implements Insettable,
|
||||
});
|
||||
mPadding.set(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
|
||||
getPaddingBottom());
|
||||
onUpdatePaddings();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -364,13 +364,17 @@ public class WidgetsContainerView extends FrameLayout implements Insettable,
|
||||
// Container rendering related.
|
||||
//
|
||||
|
||||
/*
|
||||
* @see Insettable#setInsets(Rect)
|
||||
*/
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
setPadding(mPadding.left + insets.left, mPadding.top + insets.top,
|
||||
mPadding.right + insets.right, mPadding.bottom + insets.bottom);
|
||||
protected void onUpdatePaddings() {
|
||||
if (mFixedBounds.isEmpty()) {
|
||||
// If there are no fixed bounds, then use the default padding and insets
|
||||
setPadding(mPadding.left + mInsets.left, mPadding.top + mInsets.top,
|
||||
mPadding.right + mInsets.right, mPadding.bottom + 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user