FloatingHeaderHandler refactored into custom view FloatingHeaderView.
No logical change. Change-Id: I9a6dadb151872abe9915e96833af530ca08ddb8e
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
|
||||
<include layout="@layout/all_apps_fast_scroller" />
|
||||
|
||||
<RelativeLayout
|
||||
<com.android.launcher3.allapps.FloatingHeaderView
|
||||
android:id="@+id/all_apps_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -73,7 +73,7 @@
|
||||
android:textColor="@color/all_apps_tab_text"
|
||||
android:background="?android:attr/selectableItemBackground"/>
|
||||
</com.android.launcher3.views.SlidingTabStrip>
|
||||
</RelativeLayout>
|
||||
</com.android.launcher3.allapps.FloatingHeaderView>
|
||||
|
||||
<!-- Note: we are reusing/repurposing a system attribute for search layout, because of a
|
||||
platform bug, which prevents using custom attributes in <include> tag -->
|
||||
|
||||
@@ -85,8 +85,7 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
private SearchUiManager mSearchUiManager;
|
||||
private View mSearchContainer;
|
||||
private InterceptingViewPager mViewPager;
|
||||
private ViewGroup mHeader;
|
||||
private FloatingHeaderHandler mFloatingHeaderHandler;
|
||||
private FloatingHeaderView mHeader;
|
||||
private TabsPagerAdapter mTabsPagerAdapter;
|
||||
|
||||
private SpannableStringBuilder mSearchQueryBuilder = null;
|
||||
@@ -234,8 +233,8 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
for (int i = 0; i < mAH.length; i++) {
|
||||
updatePromiseAppProgress(app, mAH[i].recyclerView);
|
||||
}
|
||||
if (mFloatingHeaderHandler != null) {
|
||||
updatePromiseAppProgress(app, mFloatingHeaderHandler.getContentView());
|
||||
if (isHeaderVisible()) {
|
||||
updatePromiseAppProgress(app, mHeader.getPredictionRow());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,8 +285,8 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
mAH[i].recyclerView.scrollToTop();
|
||||
}
|
||||
}
|
||||
if (mFloatingHeaderHandler != null) {
|
||||
mFloatingHeaderHandler.reset();
|
||||
if (isHeaderVisible()) {
|
||||
mHeader.reset();
|
||||
}
|
||||
// Reset the search bar and base recycler view after transitioning home
|
||||
mSearchUiManager.reset();
|
||||
@@ -309,7 +308,6 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
});
|
||||
|
||||
mHeader = findViewById(R.id.all_apps_header);
|
||||
mFloatingHeaderHandler = new FloatingHeaderHandler(mHeader);
|
||||
rebindAdapters(mUsingTabs);
|
||||
|
||||
mSearchContainer = findViewById(R.id.search_container_all_apps);
|
||||
@@ -447,7 +445,6 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
if (FeatureFlags.ALL_APPS_PREDICTION_ROW_VIEW) {
|
||||
setupHeader();
|
||||
} else {
|
||||
mFloatingHeaderHandler = null;
|
||||
mHeader.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
@@ -501,7 +498,7 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
@Override
|
||||
public void onPageSelected(int pos) {
|
||||
tabs.updateTabTextColor(pos);
|
||||
mFloatingHeaderHandler.setMainActive(pos == 0);
|
||||
mHeader.setMainActive(pos == 0);
|
||||
applyTouchDelegate();
|
||||
if (mAH[pos].recyclerView != null) {
|
||||
mAH[pos].recyclerView.bindFastScrollbar();
|
||||
@@ -524,14 +521,16 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
}
|
||||
|
||||
public void setPredictedApps(List<ComponentKeyMapper<AppInfo>> apps) {
|
||||
if (mFloatingHeaderHandler != null) {
|
||||
mFloatingHeaderHandler.getContentView().setPredictedApps(apps);
|
||||
if (isHeaderVisible()) {
|
||||
mHeader.getPredictionRow().setPredictedApps(apps);
|
||||
}
|
||||
mAH[AdapterHolder.MAIN].appsList.setPredictedApps(apps);
|
||||
boolean hasPredictions = !apps.isEmpty();
|
||||
if (mHasPredictions != hasPredictions) {
|
||||
mHasPredictions = hasPredictions;
|
||||
setupHeader();
|
||||
if (FeatureFlags.ALL_APPS_PREDICTION_ROW_VIEW) {
|
||||
setupHeader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -547,12 +546,12 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
return mUsingTabs;
|
||||
}
|
||||
|
||||
public FloatingHeaderHandler getFloatingHeaderHandler() {
|
||||
return mFloatingHeaderHandler;
|
||||
public FloatingHeaderView getFloatingHeaderView() {
|
||||
return mHeader;
|
||||
}
|
||||
|
||||
private void setupHeader() {
|
||||
if (mFloatingHeaderHandler == null) {
|
||||
if (mHeader == null) {
|
||||
return;
|
||||
}
|
||||
mHeader.setVisibility(View.VISIBLE);
|
||||
@@ -565,8 +564,8 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
}
|
||||
AllAppsRecyclerView mainRV = mAH[AdapterHolder.MAIN].recyclerView;
|
||||
AllAppsRecyclerView workRV = mAH[AdapterHolder.WORK].recyclerView;
|
||||
mFloatingHeaderHandler.setup(mainRV, workRV, contentHeight);
|
||||
mFloatingHeaderHandler.getContentView().setup(mAH[AdapterHolder.MAIN].adapter,
|
||||
mHeader.setup(mainRV, workRV, contentHeight);
|
||||
mHeader.getPredictionRow().setup(mAH[AdapterHolder.MAIN].adapter,
|
||||
mComponentToAppMap, mNumPredictedAppsPerRow);
|
||||
|
||||
int padding = contentHeight;
|
||||
@@ -584,7 +583,7 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
mAH[i].adapter.setLastSearchQuery(query);
|
||||
}
|
||||
boolean hasQuery = !TextUtils.isEmpty(query);
|
||||
if (mFloatingHeaderHandler != null && mUsingTabs && hasQuery) {
|
||||
if (mUsingTabs && hasQuery) {
|
||||
mSearchModeWhileUsingTabs = true;
|
||||
rebindAdapters(false); // hide tabs
|
||||
} else if (mSearchModeWhileUsingTabs && !hasQuery) {
|
||||
@@ -630,12 +629,16 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
|
||||
public List<AppInfo> getPredictedApps() {
|
||||
if (mUsingTabs) {
|
||||
return mFloatingHeaderHandler.getContentView().getPredictedApps();
|
||||
return mHeader.getPredictionRow().getPredictedApps();
|
||||
} else {
|
||||
return mAH[AdapterHolder.MAIN].appsList.getPredictedApps();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHeaderVisible() {
|
||||
return mHeader != null && mHeader.getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
public class AdapterHolder {
|
||||
public static final int MAIN = 0;
|
||||
public static final int WORK = 1;
|
||||
@@ -685,8 +688,8 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
? paddingTopForTabs : padding.top;
|
||||
recyclerView.setPadding(padding.left, paddingTop, padding.right, padding.bottom);
|
||||
}
|
||||
if (mFloatingHeaderHandler != null) {
|
||||
mFloatingHeaderHandler.getContentView()
|
||||
if (isHeaderVisible()) {
|
||||
mHeader.getPredictionRow()
|
||||
.setPadding(padding.left, 0 , padding.right, 0);
|
||||
}
|
||||
}
|
||||
@@ -698,8 +701,8 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
|
||||
}
|
||||
adapter.setNumAppsPerRow(mNumAppsPerRow);
|
||||
appsList.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow);
|
||||
if (mFloatingHeaderHandler != null) {
|
||||
mFloatingHeaderHandler.getContentView()
|
||||
if (isHeaderVisible()) {
|
||||
mHeader.getPredictionRow()
|
||||
.setNumAppsPerRow(mNumPredictedAppsPerRow);
|
||||
}
|
||||
}
|
||||
|
||||
+61
-51
@@ -15,30 +15,65 @@
|
||||
*/
|
||||
package com.android.launcher3.allapps;
|
||||
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
|
||||
public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
|
||||
implements ValueAnimator.AnimatorUpdateListener {
|
||||
public class FloatingHeaderView extends RelativeLayout implements
|
||||
ValueAnimator.AnimatorUpdateListener {
|
||||
|
||||
private static final boolean SHOW_PREDICTIONS_ONLY_ON_TOP = true;
|
||||
|
||||
private final View mHeaderView;
|
||||
private final PredictionRowView mPredictionRow;
|
||||
private final ViewGroup mTabLayout;
|
||||
private final View mDivider;
|
||||
private final Rect mClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
|
||||
private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
if (SHOW_PREDICTIONS_ONLY_ON_TOP) {
|
||||
return;
|
||||
}
|
||||
if (!mTopOnlyMode && newState == RecyclerView.SCROLL_STATE_IDLE
|
||||
&& mTranslationY != -mMaxTranslation && mTranslationY != 0) {
|
||||
float scroll = Math.abs(getCurrentScroll());
|
||||
boolean expand = scroll > mMaxTranslation
|
||||
? Math.abs(mTranslationY) < mMaxTranslation / 2 : true;
|
||||
setExpanded(expand);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(RecyclerView rv, int dx, int dy) {
|
||||
boolean isMainRV = rv == mMainRV;
|
||||
if (isMainRV != mMainRVActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAnimator.isStarted()) {
|
||||
mAnimator.cancel();
|
||||
}
|
||||
|
||||
int current = - (isMainRV
|
||||
? mMainRV.getCurrentScrollY()
|
||||
: mWorkRV.getCurrentScrollY());
|
||||
moved(current);
|
||||
apply();
|
||||
}
|
||||
};
|
||||
|
||||
private PredictionRowView mPredictionRow;
|
||||
private ViewGroup mTabLayout;
|
||||
private View mDivider;
|
||||
private AllAppsRecyclerView mMainRV;
|
||||
private AllAppsRecyclerView mWorkRV;
|
||||
private boolean mTopOnlyMode;
|
||||
@@ -50,15 +85,24 @@ public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
|
||||
private int mWorkScrolledY;
|
||||
private boolean mMainRVActive;
|
||||
|
||||
public FloatingHeaderHandler(@NonNull ViewGroup header) {
|
||||
mHeaderView = header;
|
||||
mTabLayout = header.findViewById(R.id.tabs);
|
||||
mDivider = header.findViewById(R.id.divider);
|
||||
mPredictionRow = header.findViewById(R.id.header_content);
|
||||
public FloatingHeaderView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mTabLayout = findViewById(R.id.tabs);
|
||||
mDivider = findViewById(R.id.divider);
|
||||
mPredictionRow = findViewById(R.id.header_content);
|
||||
}
|
||||
|
||||
public void setup(@NonNull AllAppsRecyclerView personalRV, @Nullable AllAppsRecyclerView workRV,
|
||||
int predictionRowHeight) {
|
||||
int predictionRowHeight) {
|
||||
mTopOnlyMode = workRV == null;
|
||||
mTabLayout.setVisibility(mTopOnlyMode ? View.GONE : View.VISIBLE);
|
||||
mPredictionRow.getLayoutParams().height = predictionRowHeight;
|
||||
@@ -71,13 +115,13 @@ public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
|
||||
|
||||
private AllAppsRecyclerView setupRV(AllAppsRecyclerView old, AllAppsRecyclerView updated) {
|
||||
if (old != updated && updated != null ) {
|
||||
updated.addOnScrollListener(this);
|
||||
updated.addOnScrollListener(mOnScrollListener);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
private void setupDivider() {
|
||||
Resources res = mHeaderView.getResources();
|
||||
Resources res = getResources();
|
||||
int verticalGap = res.getDimensionPixelSize(R.dimen.all_apps_divider_margin_vertical);
|
||||
int sideGap = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
|
||||
mDivider.setPadding(sideGap, verticalGap,sideGap, mTopOnlyMode ? verticalGap : 0);
|
||||
@@ -93,11 +137,7 @@ public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
|
||||
setExpanded(true);
|
||||
}
|
||||
|
||||
public View getHeaderView() {
|
||||
return mHeaderView;
|
||||
}
|
||||
|
||||
public PredictionRowView getContentView() {
|
||||
public PredictionRowView getPredictionRow() {
|
||||
return mPredictionRow;
|
||||
}
|
||||
|
||||
@@ -109,24 +149,6 @@ public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
|
||||
return mDivider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(RecyclerView rv, int dx, int dy) {
|
||||
boolean isMainRV = rv == mMainRV;
|
||||
if (isMainRV != mMainRVActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAnimator.isStarted()) {
|
||||
mAnimator.cancel();
|
||||
}
|
||||
|
||||
int current = - (isMainRV
|
||||
? mMainRV.getCurrentScrollY()
|
||||
: mWorkRV.getCurrentScrollY());
|
||||
moved(current);
|
||||
apply();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mMainScrolledY = 0;
|
||||
mWorkScrolledY = 0;
|
||||
@@ -182,20 +204,6 @@ public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
if (SHOW_PREDICTIONS_ONLY_ON_TOP) {
|
||||
return;
|
||||
}
|
||||
if (!mTopOnlyMode && newState == RecyclerView.SCROLL_STATE_IDLE
|
||||
&& mTranslationY != -mMaxTranslation && mTranslationY != 0) {
|
||||
float scroll = Math.abs(getCurrentScroll());
|
||||
boolean expand = scroll > mMaxTranslation
|
||||
? Math.abs(mTranslationY) < mMaxTranslation / 2 : true;
|
||||
setExpanded(expand);
|
||||
}
|
||||
}
|
||||
|
||||
private void setExpanded(boolean expand) {
|
||||
int translateTo = expand ? 0 : -mMaxTranslation;
|
||||
mAnimator.setIntValues(mTranslationY, translateTo);
|
||||
@@ -221,3 +229,5 @@ public class FloatingHeaderHandler extends RecyclerView.OnScrollListener
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user