Create SearchBarMover
This commit is contained in:
1 parent
f40b5cfbfc
commit
5732191058
4 files changed
+260
-239
No files matched your search
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* 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.hippo.widget;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
import com.hippo.yorozuya.SimpleAnimatorListener;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
public class SearchBarMover extends RecyclerView.OnScrollListener {
|
||||
|
||||
private static final long ANIMATE_TIME = 300L;
|
||||
|
||||
private boolean mShow;
|
||||
private ValueAnimator mSearchBarMoveAnimator;
|
||||
private final Helper mHelper;
|
||||
private final View mSearchBar;
|
||||
|
||||
public SearchBarMover(Helper helper, View searchBar, RecyclerView... recyclerViews) {
|
||||
mHelper = helper;
|
||||
mSearchBar = searchBar;
|
||||
for (RecyclerView recyclerView: recyclerViews) {
|
||||
recyclerView.addOnScrollListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelAnimation() {
|
||||
if (mSearchBarMoveAnimator != null) {
|
||||
mSearchBarMoveAnimator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState){
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE && mHelper.isValidView(recyclerView)) {
|
||||
returnSearchBarPosition();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
if (mHelper.isValidView(recyclerView)) {
|
||||
int oldBottom = (int) ViewUtils.getY2(mSearchBar);
|
||||
int offsetYStep = MathUtils.clamp(-dy, -oldBottom, -(int) mSearchBar.getTranslationY());
|
||||
if (offsetYStep != 0) {
|
||||
ViewUtils.translationYBy(mSearchBar, offsetYStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void returnSearchBarPosition() {
|
||||
returnSearchBarPosition(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SimplifiableIfStatement")
|
||||
public void returnSearchBarPosition(boolean animation) {
|
||||
if (mSearchBar.getHeight() == 0) {
|
||||
// Layout not called
|
||||
return;
|
||||
}
|
||||
|
||||
boolean show;
|
||||
if (mHelper.forceShowSearchBar()) {
|
||||
show = true;
|
||||
} else {
|
||||
RecyclerView recyclerView = mHelper.getValidRecyclerView();
|
||||
if (!recyclerView.isShown()) {
|
||||
show = true;
|
||||
} else if (recyclerView.computeVerticalScrollOffset() < mSearchBar.getBottom()){
|
||||
show = true;
|
||||
} else {
|
||||
show = (int) ViewUtils.getY2(mSearchBar) > (mSearchBar.getHeight()) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
int offset;
|
||||
if (show) {
|
||||
offset = -(int) mSearchBar.getTranslationY();
|
||||
} else {
|
||||
offset = -(int) ViewUtils.getY2(mSearchBar);
|
||||
}
|
||||
|
||||
if (offset == 0) {
|
||||
// No need to scroll
|
||||
return;
|
||||
}
|
||||
|
||||
if (animation) {
|
||||
if (mSearchBarMoveAnimator != null) {
|
||||
if (mShow == show) {
|
||||
// The same target, no need to do animation
|
||||
return;
|
||||
} else {
|
||||
// Cancel it
|
||||
mSearchBarMoveAnimator.cancel();
|
||||
mSearchBarMoveAnimator = null;
|
||||
}
|
||||
}
|
||||
|
||||
mShow = show;
|
||||
final ValueAnimator va = ValueAnimator.ofInt(0, offset);
|
||||
va.setDuration(ANIMATE_TIME);
|
||||
va.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mSearchBarMoveAnimator = null;
|
||||
}
|
||||
});
|
||||
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
int lastValue;
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
int value = (Integer) animation.getAnimatedValue();
|
||||
int offsetStep = value - lastValue;
|
||||
lastValue = value;
|
||||
ViewUtils.translationYBy(mSearchBar, offsetStep);
|
||||
}
|
||||
});
|
||||
mSearchBarMoveAnimator = va;
|
||||
va.start();
|
||||
} else {
|
||||
if (mSearchBarMoveAnimator != null) {
|
||||
mSearchBarMoveAnimator.cancel();
|
||||
}
|
||||
ViewUtils.translationYBy(mSearchBar, offset);
|
||||
}
|
||||
}
|
||||
|
||||
public void showSearchBar() {
|
||||
showSearchBar(true);
|
||||
}
|
||||
|
||||
public void showSearchBar(boolean animation) {
|
||||
if (mSearchBar.getHeight() == 0) {
|
||||
// Layout not called
|
||||
return;
|
||||
}
|
||||
|
||||
final int offset = -(int) mSearchBar.getTranslationY();
|
||||
|
||||
if (offset == 0) {
|
||||
// No need to scroll
|
||||
return;
|
||||
}
|
||||
|
||||
if (animation) {
|
||||
if (mSearchBarMoveAnimator != null) {
|
||||
if (mShow) {
|
||||
// The same target, no need to do animation
|
||||
return;
|
||||
} else {
|
||||
// Cancel it
|
||||
mSearchBarMoveAnimator.cancel();
|
||||
mSearchBarMoveAnimator = null;
|
||||
}
|
||||
}
|
||||
|
||||
mShow = true;
|
||||
final ValueAnimator va = ValueAnimator.ofInt(0, offset);
|
||||
va.setDuration(ANIMATE_TIME);
|
||||
va.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mSearchBarMoveAnimator = null;
|
||||
}
|
||||
});
|
||||
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
int lastValue;
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
int value = (Integer) animation.getAnimatedValue();
|
||||
int offsetStep = value - lastValue;
|
||||
lastValue = value;
|
||||
ViewUtils.translationYBy(mSearchBar, offsetStep);
|
||||
}
|
||||
});
|
||||
mSearchBarMoveAnimator = va;
|
||||
va.start();
|
||||
} else {
|
||||
if (mSearchBarMoveAnimator != null) {
|
||||
mSearchBarMoveAnimator.cancel();
|
||||
}
|
||||
ViewUtils.translationYBy(mSearchBar, offset);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Helper {
|
||||
|
||||
boolean isValidView(RecyclerView recyclerView);
|
||||
|
||||
RecyclerView getValidRecyclerView();
|
||||
|
||||
boolean forceShowSearchBar();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user