Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d87ed17 authored by Mario Bertschler's avatar Mario Bertschler
Browse files

FloatingHeaderHandler refactored into custom view FloatingHeaderView.

No logical change.

Change-Id: I9a6dadb151872abe9915e96833af530ca08ddb8e
parent adaeeee6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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 -->
+26 −23
Original line number Diff line number Diff line
@@ -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,16 +521,18 @@ 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;
            if (FeatureFlags.ALL_APPS_PREDICTION_ROW_VIEW) {
                setupHeader();
            }
        }
    }

    public AppInfo findApp(ComponentKeyMapper<AppInfo> mapper) {
        return mapper.getItem(mComponentToAppMap);
@@ -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
Original line number Diff line number Diff line
@@ -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,11 +85,20 @@ 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,
@@ -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
    }

}