直接来看效果图:
第一次隐藏是点击空白区域自动隐藏,第二次是通过手指滑动控制dialog隐藏。
实现这个效果的代码量很少,直接来看代码:
@Override
protected void onStart() {
super.onStart();
Window window = getWindow();
window.setWindowAnimations(R.style.bottomShow);
WindowManager.LayoutParams windowparams = window.getAttributes();
window.setGravity(Gravity.BOTTOM);
windowparams.height = DensityUtil.dip2px(context, 300);
windowparams.width = ScreenUtils.getScreenWidth(context);
window.setBackgroundDrawableResource(android.R.color.transparent);
window.setAttributes(windowparams);
}
在dialog的onstart方法中,我们获取dialog的window对象,设置内容view显示在底部,设置view高度为300dp。宽度为屏幕宽度,。这里要使用window的setBackgroundDrawableResource,否则会出现旁边有间隔的现象。还有设置window的动画:
<style name="bottomShow" parent="@android:style/Animation">
<item name="android:windowEnterAnimation">@anim/pop_show</item>
<item name="android:windowExitAnimation">@anim/pop_hidden</item>
</style>
pop_show.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromYDelta="100%p"
android:duration="500"
android:toYDelta="0"
></translate>
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromYDelta="0"
android:duration="500"
android:toYDelta="100%p"
></translate>
</set>
在style中指定android:windowEnterAnimation和android:windowExitAnimation,进入退出动画。
这样就完成了弹出隐藏的动画。
然后是手指控制dialog滑动隐藏:
为了滑动不起冲突,使用onTouchEvent方法来监听滑动事件:
float startY;
float moveY = 0;
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
moveY = ev.getY() - startY;
view.scrollBy(0, -(int) moveY);
startY = ev.getY();
if (view.getScrollY() > 0) {
view.scrollTo(0, 0);
}
break;
case MotionEvent.ACTION_UP:
if (view.getScrollY() < -this.getWindow().getAttributes().height / 4 && moveY > 0) {
this.dismiss();
}
view.scrollTo(0, 0);
break;
}
return super.onTouchEvent(ev);
}
在down的时候记录y,滑动的时候计算出滑动距离通过view。scrollBy方法控制view的滑动,确保view不能玩上滑动溢出,控制view.getScrollY大于0的时候重置。手指抬起的时候判断滑动方向如果是向下并且超过四分之一,隐藏dialog,然后重置view的位置。
通过改变mScrollY来变化view的位置,实际上view本身并没有发生移动 移动的view的内容。view的内容和view本身的横向纵向距离就是mScroolX和mScrollY的值: