fab: move in direct ratio to scroll
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									fbf32a6c29
								
							
						
					
					
						commit
						d0d56f3a1b
					
				@ -27,8 +27,6 @@ import android.view.Menu;
 | 
			
		||||
import android.view.MenuItem;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
import android.view.animation.AccelerateInterpolator;
 | 
			
		||||
import android.view.animation.DecelerateInterpolator;
 | 
			
		||||
 | 
			
		||||
import com.wireguard.android.Application;
 | 
			
		||||
import com.wireguard.android.R;
 | 
			
		||||
@ -38,7 +36,7 @@ import com.wireguard.android.databinding.TunnelListFragmentBinding;
 | 
			
		||||
import com.wireguard.android.databinding.TunnelListItemBinding;
 | 
			
		||||
import com.wireguard.android.model.Tunnel;
 | 
			
		||||
import com.wireguard.android.util.ExceptionLoggers;
 | 
			
		||||
import com.wireguard.android.widget.CustomRecyclerViewScrollListener;
 | 
			
		||||
import com.wireguard.android.widget.fab.FloatingActionsMenuRecyclerViewScrollListener;
 | 
			
		||||
import com.wireguard.config.Config;
 | 
			
		||||
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
@ -62,8 +60,6 @@ import java9.util.stream.StreamSupport;
 | 
			
		||||
public class TunnelListFragment extends BaseFragment {
 | 
			
		||||
    private static final int REQUEST_IMPORT = 1;
 | 
			
		||||
    private static final String TAG = "WireGuard/" + TunnelListFragment.class.getSimpleName();
 | 
			
		||||
    private static final TimeInterpolator FAB_SHOW_ANIMATION = new DecelerateInterpolator(2);
 | 
			
		||||
    private static final TimeInterpolator FAB_HIDE_ANIMATION = new AccelerateInterpolator(2);
 | 
			
		||||
 | 
			
		||||
    private final ActionModeListener actionModeListener = new ActionModeListener();
 | 
			
		||||
    @Nullable private ActionMode actionMode;
 | 
			
		||||
@ -196,23 +192,7 @@ public class TunnelListFragment extends BaseFragment {
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        });
 | 
			
		||||
        binding.tunnelList.setOnScrollListener(new CustomRecyclerViewScrollListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void show() {
 | 
			
		||||
                binding.createMenu.animate()
 | 
			
		||||
                        .translationY(0)
 | 
			
		||||
                        .setInterpolator(FAB_SHOW_ANIMATION)
 | 
			
		||||
                        .start();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public void hide() {
 | 
			
		||||
                binding.createMenu.animate()
 | 
			
		||||
                        .translationY(binding.createMenu.getHeight() + getResources().getDimension(R.dimen.fab_margin))
 | 
			
		||||
                        .setInterpolator(FAB_HIDE_ANIMATION)
 | 
			
		||||
                        .start();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        binding.tunnelList.setOnScrollListener(new FloatingActionsMenuRecyclerViewScrollListener(binding.createMenu));
 | 
			
		||||
        binding.executePendingBindings();
 | 
			
		||||
        return binding.getRoot();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,43 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright © 2018 Harsh Shandilya <msfjarvis@gmail.com>
 | 
			
		||||
 * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.wireguard.android.widget;
 | 
			
		||||
 | 
			
		||||
import android.support.v7.widget.RecyclerView;
 | 
			
		||||
 | 
			
		||||
import com.wireguard.android.R;
 | 
			
		||||
 | 
			
		||||
public abstract class CustomRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
 | 
			
		||||
 | 
			
		||||
    private int scrollDist;
 | 
			
		||||
    private boolean isVisible = true;
 | 
			
		||||
    private static int flingThreshold;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onScrolled(final RecyclerView recyclerView, final int dx, final int dy) {
 | 
			
		||||
        super.onScrolled(recyclerView, dx, dy);
 | 
			
		||||
 | 
			
		||||
        if (flingThreshold == 0)
 | 
			
		||||
            flingThreshold = recyclerView.getResources().getDimensionPixelSize(R.dimen.design_fab_size_normal) / 2;
 | 
			
		||||
 | 
			
		||||
        if (isVisible && scrollDist >= flingThreshold) {
 | 
			
		||||
            hide();
 | 
			
		||||
            scrollDist = 0;
 | 
			
		||||
            isVisible = false;
 | 
			
		||||
        } else if (!isVisible && scrollDist <= -flingThreshold) {
 | 
			
		||||
            show();
 | 
			
		||||
            scrollDist = 0;
 | 
			
		||||
            isVisible = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isVisible ? dy > 0 : dy < 0) {
 | 
			
		||||
            scrollDist += dy;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public abstract void show();
 | 
			
		||||
    public abstract void hide();
 | 
			
		||||
}
 | 
			
		||||
@ -25,8 +25,7 @@ public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior<Flo
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onDependentViewChanged(final CoordinatorLayout parent, final FloatingActionsMenu child,
 | 
			
		||||
                                          final View dependency) {
 | 
			
		||||
        final float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
 | 
			
		||||
        child.setTranslationY(translationY);
 | 
			
		||||
        child.setBehaviorYTranslation(Math.min(0, dependency.getTranslationY() - dependency.getMeasuredHeight()));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -67,6 +67,8 @@ public class FloatingActionsMenu extends ViewGroup {
 | 
			
		||||
    @Nullable private TouchDelegateGroup mTouchDelegateGroup;
 | 
			
		||||
    @Nullable private OnFloatingActionsMenuUpdateListener mListener;
 | 
			
		||||
    private final Rect touchArea = new Rect(0, 0, 0, 0);
 | 
			
		||||
    private float scrollYTranslation;
 | 
			
		||||
    private float behaviorYTranslation;
 | 
			
		||||
 | 
			
		||||
    public FloatingActionsMenu(final Context context) {
 | 
			
		||||
        this(context, null);
 | 
			
		||||
@ -103,6 +105,24 @@ public class FloatingActionsMenu extends ViewGroup {
 | 
			
		||||
        createAddButton(context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public float getScrollYTranslation() {
 | 
			
		||||
        return scrollYTranslation;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setScrollYTranslation(final float scrollYTranslation) {
 | 
			
		||||
        this.scrollYTranslation = scrollYTranslation;
 | 
			
		||||
        setTranslationY(behaviorYTranslation + scrollYTranslation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public float getBehaviorYTranslation() {
 | 
			
		||||
        return behaviorYTranslation;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setBehaviorYTranslation(final float behaviorYTranslation) {
 | 
			
		||||
        this.behaviorYTranslation = behaviorYTranslation;
 | 
			
		||||
        setTranslationY(behaviorYTranslation + scrollYTranslation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setOnFloatingActionsMenuUpdateListener(final OnFloatingActionsMenuUpdateListener listener) {
 | 
			
		||||
        mListener = listener;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,29 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.wireguard.android.widget.fab;
 | 
			
		||||
 | 
			
		||||
import android.support.v7.widget.RecyclerView;
 | 
			
		||||
 | 
			
		||||
import com.wireguard.android.R;
 | 
			
		||||
 | 
			
		||||
public class FloatingActionsMenuRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
 | 
			
		||||
    private static final float SCALE_FACTOR = 1.5f;
 | 
			
		||||
    private final FloatingActionsMenu menu;
 | 
			
		||||
 | 
			
		||||
    public FloatingActionsMenuRecyclerViewScrollListener(final FloatingActionsMenu menu) {
 | 
			
		||||
        this.menu = menu;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static float bound(float min, float proposal, float max) {
 | 
			
		||||
        return Math.min(max, Math.max(min, proposal));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onScrolled(final RecyclerView recyclerView, final int dx, final int dy) {
 | 
			
		||||
        super.onScrolled(recyclerView, dx, dy);
 | 
			
		||||
        menu.setScrollYTranslation(bound(0, menu.getScrollYTranslation() + dy * SCALE_FACTOR, menu.getMeasuredHeight() - menu.getTranslationY()));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -30,7 +30,7 @@
 | 
			
		||||
            android:id="@+id/tunnel_list"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="match_parent"
 | 
			
		||||
            android:paddingBottom="@dimen/design_fab_size_normal"
 | 
			
		||||
            android:paddingBottom="@{@dimen/design_fab_size_normal * 1.1f}"
 | 
			
		||||
            android:clipToPadding="false"
 | 
			
		||||
            android:choiceMode="multipleChoiceModal"
 | 
			
		||||
            app:items="@{tunnels}"
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user