Android 仿美團懸浮購物車顯示隱藏
阿新 • • 發佈:2018-12-19
效果圖:
這是美團的效果
通過效果圖可以看到 靜止的時候是購物車圖示是顯示的,滑動的時候是隱藏一半並半透明顯示的。
這裡用到一個觸控反饋的方法dispatchTouchEvent
- MotionEvent.ACTION_DOWN://手指按下
- MotionEvent.ACTION_MOVE://手指滑動
- MotionEvent.ACTION_UP://手指擡起
整體的思路就是在滑動過程中,購物車圖示向右位移,並加一個漸變效果。
向右移動的距離計算:螢幕的寬度減去圖示距左邊的寬度(紅線),然後加上圖示的半徑(藍線)
佈局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent"/> <ImageView android:id="@+id/iv_cart" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_marginBottom="60dp" android:layout_marginEnd="20dp" android:layout_marginRight="20dp" android:contentDescription="@null" android:src="@drawable/ic_cart"/> </RelativeLayout>
程式碼
初始化控制元件
mListView = findViewById(R.id.list_view);
mIvCart = findViewById(R.id.iv_cart);
初始化資料
for (int i = 0; i < 50; i++) { titles.add("第 - " + i + " - 條資料"); } mListView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, titles));
計算移動距離
//控制元件繪製完成之後再獲取其寬高 mIvCart.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //動畫移動的距離 螢幕的寬度減去圖片距左邊的寬度 就是圖片距右邊的寬度,再加上隱藏的一半 moveDistance = getScreenWidth() - mIvCart.getRight() + mIvCart.getWidth() / 2; //監聽結束之後移除監聽事件 mIvCart.getViewTreeObserver().removeOnGlobalLayoutListener(this); } });
private int getScreenWidth() {
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
隱藏動畫
private void hideFloatImage(int distance) {
isShowFloatImage = false;
//位移動畫
TranslateAnimation ta = new TranslateAnimation(0, distance, 0, 0);
ta.setDuration(300);
//漸變動畫
AlphaAnimation al = new AlphaAnimation(1f, 0.5f);
al.setDuration(300);
AnimationSet set = new AnimationSet(true);
//動畫完成後不回到原位
set.setFillAfter(true);
set.addAnimation(ta);
set.addAnimation(al);
mIvCart.startAnimation(set);
}
顯示動畫
private void showFloatImage(int distance) {
isShowFloatImage = true;
//位移動畫
TranslateAnimation ta = new TranslateAnimation(distance, 0, 0, 0);
ta.setDuration(300);
//漸變動畫
AlphaAnimation al = new AlphaAnimation(0.5f, 1f);
al.setDuration(300);
AnimationSet set = new AnimationSet(true);
//動畫完成後不回到原位
set.setFillAfter(true);
set.addAnimation(ta);
set.addAnimation(al);
mIvCart.startAnimation(set);
}
處理滑動邏輯
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN://手指按下
if (System.currentTimeMillis() - upTime < 1000) {
//本次按下距離上次的擡起小於1s時,取消Timer
timer.cancel();
}
startY = event.getY();
break;
case MotionEvent.ACTION_MOVE://手指滑動
if (Math.abs(startY - event.getY()) > 10) {
if (isShowFloatImage) {
hideFloatImage(moveDistance);
}
}
startY = event.getY();
break;
case MotionEvent.ACTION_UP://手指擡起
if (!isShowFloatImage) {
//擡起手指1s後再顯示懸浮按鈕
//開始1s倒計時
upTime = System.currentTimeMillis();
timer = new Timer();
timer.schedule(new FloatTask(), 1000);
}
break;
}
return super.dispatchTouchEvent(event);
}
- 這裡用一個
upTime
記錄手指擡起的時間,如果小於1s動畫就不執行,避免快速反覆滑動導致動畫多次執行。 - 然後用一個定時器
timer
延時執行動畫 - 在手指擡起的時候記錄當前時間戳,並執行動畫
moveDistance
就是計算的移動的距離isShowFloatImage
是一個布林型別的標識,判斷圖示狀態是否顯示- startY - event.getY()) > 10 這個大於10是因為手指按下的是一個面,不是一個點,把這個面的高度定為10
github : https://github.com/yechaoa/FloatCartDemo
ok,完成,借鑑https://blog.csdn.net/Lindroid20/article/details/78887347