FloatingHeaderHandler refactored into custom view FloatingHeaderView.

No logical change.

Change-Id: I9a6dadb151872abe9915e96833af530ca08ddb8e
This commit is contained in:
Mario Bertschler
2017-12-06 11:45:49 -08:00
parent adaeeee690
commit 3d87ed17b3
3 changed files with 89 additions and 76 deletions
+2 -2
View File
@@ -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);
}
}
@@ -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
}
}