1. 程式人生 > >Android 仿美團懸浮購物車顯示隱藏

Android 仿美團懸浮購物車顯示隱藏

效果圖:

在這裡插入圖片描述

這是美團的效果

在這裡插入圖片描述 在這裡插入圖片描述

通過效果圖可以看到 靜止的時候是購物車圖示是顯示的,滑動的時候是隱藏一半並半透明顯示的。
這裡用到一個觸控反饋的方法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