高德效果
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.
複製代碼