2017-01-13 遇到的一点小问题
之前用到Behavior只是按网上看到的方式来做个简单点的滑动隐藏显示顶部View,
CoordinatorLayout与AppBarLayout配合使用的滑动效果 这个提过了。
前几天看到利用自定义Behavior,打造动画效果,打算了解看看,先从最简单的开始。
http://www.jianshu.com/p/82d18b0d18f4
BottomSheetBehavior的用法很简单,将View放在android.support.design.widget.CoordinatorLayout
布局里,再加上app:layout_behavior="@string/bottom_sheet_behavior"
这个属性就可以。这样是默认显示的,如果要默认隐藏就再加上app:behavior_peekHeight="0dp"
。没找到能在底部上滑让底部View出现的方法,只好将peekHeight设置为5dp,这样,在折叠时,也能上滑让底部View出现。
BottomSheetBehavior有好几个状态,默认收起来是STATE_COLLAPSED
折叠状态,如果你希望是STATE_HIDDEN
隐藏状态,就要加上bottomSheetBehavior.setHideable(true);
看源码可知道,mHideable 默认是false,如果不改成true,在bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
时就会抛出异常
/**
* Sets the state of the bottom sheet. The bottom sheet will transition to that state with
* animation.
*
* @param state One of {@link #STATE_COLLAPSED}, {@link #STATE_EXPANDED}, or
* {@link #STATE_HIDDEN}.
*/
public final void setState(final @State int state) {
if (state == mState) {
return;
}
if (mViewRef == null) {
// The view is not laid out yet; modify mState and let onLayoutChild handle it later
if (state == STATE_COLLAPSED || state == STATE_EXPANDED ||
(mHideable && state == STATE_HIDDEN)) {
mState = state;
}
return;
}
final V child = mViewRef.get();
if (child == null) {
return;
}
// Start the animation; wait until a pending layout if there is one.
ViewParent parent = child.getParent();
if (parent != null && parent.isLayoutRequested() && ViewCompat.isAttachedToWindow(child)) {
child.post(new Runnable() {
@Override
public void run() {
startSettlingAnimation(child, state);
}
});
} else {
startSettlingAnimation(child, state);
}
}
void startSettlingAnimation(View child, int state) {
int top;
if (state == STATE_COLLAPSED) {
top = mMaxOffset;
} else if (state == STATE_EXPANDED) {
top = mMinOffset;
} else if (mHideable && state == STATE_HIDDEN) {
top = mParentHeight;
} else {
throw new IllegalArgumentException("Illegal state argument: " + state);
}
setStateInternal(STATE_SETTLING);
if (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) {
ViewCompat.postOnAnimation(child, new SettleRunnable(child, state));
}
}
所为,如果我们没必要监听他的状态变化和滑动距离,只是点击别的按钮让他展开和折叠,使用方法就特别简单了。
final BottomSheetBehavior<View> bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom));
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(bottomSheetBehavior.getState() != BottomSheetBehavior.STATE_EXPANDED){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}else {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
});
BottomSheetDialog用法和普通的自定义Dialog没差。
BottomSheetDialog dialog = new BottomSheetDialog(context);
View view = LayoutInflater.from(context).inflate(R.layout.dialog_behavior,null);
dialog.setContentView(view);
dialog.show();
SwipeDismissBehavior滑动删除,效果和Snackbar滑动删除的一样。
可以参考http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1103/3650.html 的用法,也可以按 http://www.cnblogs.com/yuanchongjie/p/4997134.html 写的,参考android.support.design.widget.Snackbar
的源码来操作。
确保使用
SwipeDismissBehavior
的View在android.support.design.widget.CoordinatorLayout
布局里面。 http://blog.csdn.net/wuyuxing24/article/details/51160182 这边也有写了几个主要方法的中文注释,英语不好可以参考。这样就没问题了。滑动后,View并不是真的消失,他还是VISIBLE,只是Alpha变成0,不过自己改成1也不会再显示的,这个还不知道怎么让他再显示。使用SwipeDismissBehavior滑动,不限于单个View,而是整个在LayoutParams里的View都可以。如果要只限制某个View能滑动,需要参考Snackbar的源码,自己定义一个
MySwipeDismissBehavior
继承extends android.support.design.widget.SwipeDismissBehavior
,然后重写boolean canSwipeDismissView(@NonNull View view)
方法,根据条件来return true
或return false
,默认是所有都return true
。可以通过boolean canSwipeDismissView(@NonNull View view)
来查询某个View是否能滑动删除。继续看自定义Behavior。