高德效果
android
Android 仿高德地图可拉伸的BottomSheet
如下是我用motionlayout实现的效果,没有达到丝滑流畅,优化就看小伙伴你了
git
「译」 MotionLayout 介绍 (Part I - IV)
系列教会你如何使用MotionLayoutxxscene.xml
主要用于描述场景动画的关键帧和view状态变化等xxscene.xml
内容包括 主要为3个关键内容:Transition
过渡constraintSetStart
:启动约束场景github
constraintSetEnd
:结束约束场景express
app:dragDirection="dragUp"
拽动(拖拉)apache
KeyFrameSet
关键帧集合KeyAttribute
关键帧bash
app:framePosition
位置,进度app
app:target="@id/xxx
被描述的view id框架
ConstraintSet
约束集合<Transition
app:constraintSetEnd="@id/slideup_end"
app:constraintSetStart="@id/slideup_start"
app:duration="600"
app:interpolator="easeIn">
<OnSwipe
app:dragDirection="dragUp"
app:maxAcceleration="600"
app:touchAnchorSide="top"
app:touchAnchorId="@id/content"
/>
<KeyFrameSet>
<KeyAttribute
android:alpha="0"
app:framePosition="45"
app:target="@id/sugar_title" />
<KeyAttribute
android:alpha="1"
app:framePosition="90"
app:target="@id/sugar_title" />
...
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/slideup_start">
<Constraint
···
/>
...
</ConstraintSet>
复制代码
MotionLayout
就只有一个初始约束和结束约束,没有中间约束,如何实现这种三段式效果?MotionLayout
自带进度拆解完毕
less
/**
* 初始位置
*/
public final static float PROGRESS_START = 0f;
/**
* 顶部阀值
*/
public final static float PROGRESS_TOP = 0.9f;
/**
* 低部阀值
*/
public final static float PROGRESS_BOTTOM = 0.1f;
/**
* 中间位置
*/
public final static float PROGRESS_MIDDLE = 0.6f;
/**
* 结束位置
*/
public final static float PROGRESS_END = 1.0f;
复制代码
MotionLayout
的onTouchEvent
事件 ,使用hasMiddle
布尔值判断是否有中间状态@Override
public boolean onTouchEvent(MotionEvent event) {
float progress = getProgress();
View viewGroup = findViewById(R.id.content);
Rect mRect = new Rect();
if (!mTouchStared) {
viewGroup.getHitRect(mRect);
mTouchStared = mRect.contains((int) event.getX(), (int) event.getY());
}
float endY;
if (hasMiddle) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_CANCEL:
mTouchStared = false;
break;
case MotionEvent.ACTION_DOWN:
startY = event.getY();
break;
case MotionEvent.ACTION_UP:
endY = event.getY();
//手势向下
if ((endY - startY) > 0) {
if (progress >= PROGRESS_TOP) {
mTouchStared = false;
handleProgress(PROGRESS_END);
}
if (progress < PROGRESS_TOP && progress >= PROGRESS_MIDDLE) {
handleProgress(PROGRESS_MIDDLE);
}
if (progress < PROGRESS_MIDDLE) {
handleProgress(PROGRESS_START);
}
//手势向上
} else {
if (progress <= PROGRESS_BOTTOM) {
handleProgress(PROGRESS_START);
}
if (progress > PROGRESS_BOTTOM && progress <= PROGRESS_MIDDLE) {
handleProgress(PROGRESS_MIDDLE);
}
if (progress > PROGRESS_MIDDLE) {
mTouchStared = false;
handleProgress(PROGRESS_END);
}
}
return mTouchStared;
}
} else {
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL || event.getActionMasked() == MotionEvent.ACTION_UP) {
mTouchStared = false;
return super.onTouchEvent(event);
}
}
return mTouchStared && super.onTouchEvent(event);
}
复制代码
bottom_scene.xml
PROGRESS_TOP
以后标题出如今屏幕内,其他时候出如今屏幕外便可;scaleX
和scaleY
设为0.9结束设为了1,仅仅是为了过渡好看,你能够不用设置随意修改便可setProgress(pro);
倒是一步直达;private void handleProgress(float progress) {
//若是须要设置的进度和当前进度相同不作处理
if (progress == getProgress()){
return;
}
//动画播放时间底值
long time = 200;
//进度间隔 >0 说明上拉 < 0说明下滑
float interval = progress - getProgress();
long startTime, endTime;
if (interval > 0) {
startTime = (long) (getProgress() * time);
endTime = (long) (progress * time);
} else {
endTime = (long) (getProgress() * time);
startTime = (long) (progress * time);
}
if (timeDisposable != null){
timeDisposable.dispose();
}
//startTime 初始时间 endTime - startTime为次数 0为延迟时间 3为间隔 单位TimeUnit.MILLISECONDS 毫秒
timeDisposable = Observable.intervalRange(startTime, endTime - startTime, 0, 3, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.io())
.compose(((BaseActivity) getContext()).getProvider().bindToLifecycle())
.observeOn(AndroidSchedulers.mainThread())
.map(new Function<Long, Long>() {
@Override
public Long apply(Long aLong) throws Exception {
//下滑须要反向
if (interval < 0) {
long interStart = aLong - startTime;
return endTime - interStart;
}
return aLong;
}
})
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
float pro = (Float.valueOf(aLong) / time);
setProgress(pro);
}
});
}
复制代码
源码已放入sugar demo中,sugar是我会长期维护的一个库⬇️⬇️⬇️
ide
🍯 Sugar 简单便捷 快速开发Android项目,集合流行框架封装
Copyright 2019, wobiancao
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.
复制代码