Android 仿Keep,探索向上滑动时PopupWindow向右退出消失,向下移动时PopupWindow向左推出出现

这篇文章主要是仿Keep,通过监听ScrollView滚动事件和滚动状态(开始、停止)来实现向上滑动时PopupWindow向右退出消失,向下移动时PopupWindow向左推出出现的功能,感觉很有趣,于是想着自己动手也实现这样一个功能,和往常一样,主要是想总结一下我在学习过程中的一些笔记以及需要注意的地方。

现在我们来看下项目结构图
Android 仿Keep,探索向上滑动时PopupWindow向右退出消失,向下移动时PopupWindow向左推出出现_第1张图片
现在我把完整的代码贴出来:

CustomPopupWindow

package per.juan.popupwindowdome;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;

import androidx.core.widget.NestedScrollView;

public class CustomPopupWindow extends PopupWindow {

    LinearLayout itemView;
    ImageView iv_activity_img;
    View      customView;
    View.OnClickListener mOnClickListener;
    Handler handler = new Handler();

    //是否需要显示
    private boolean needShow=false;

    public CustomPopupWindow(Context context, CustomScrollView scrollView) {
        super(context);
        customView = LayoutInflater.from(context).inflate(R.layout.popupwin_custom, null);
        setContentView(customView);
        setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
        setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);

        itemView=customView.findViewById(R.id.itemView);
        iv_activity_img=customView.findViewById(R.id.iv_activity_img);
        setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));// 透明背景


        oa = ObjectAnimator.ofFloat(customView, "translationX", 0, getWidth() / 3 * 2);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnClickListener != null) {
                    mOnClickListener.onClick(customView);
                }
            }
        });

        scrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
            @Override
            public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                if (scrollY > oldScrollY || scrollY == (v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) {
                    needShow=false;
                }
                if (scrollY < oldScrollY || scrollY == 0) {
                    needShow=true;
                }
            }
        });

        scrollView.setOnScrollListener(new CustomScrollView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(CustomScrollView view, int scrollState) {
                switch (scrollState) {
                    case SCROLL_STATE_FLING:
                        if (needShow){
                            showAnim();
                        }else{
                            hideAnim();
                        }
                        break;
                }
            }

            @Override
            public void onScroll(CustomScrollView view, boolean isTouchScroll, int l, int t, int oldl, int oldt) {
            }
        });
    }

    public void setOnClickListener(View.OnClickListener onClickListener) {
        this.mOnClickListener = onClickListener;
    }

    ObjectAnimator oa;

    public void show() {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                showAtLocation(customView, Gravity.BOTTOM | Gravity.RIGHT, 0, 200);
            }
        },500);
    }

    void hideAnim() {
        ofFloat(customView.getTranslationX(), customView.getWidth());
    }

    void showAnim() {
        ofFloat(customView.getTranslationX(), 0f);
    }

    private void ofFloat(float... values) {
        oa.cancel();
        oa.setFloatValues(values);
        oa.setDuration(200);
        oa.start();
    }
}

CustomScrollView

package per.juan.popupwindowdome;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.core.widget.NestedScrollView;

/**
 * ScrollView滚动事件和滚动状态(开始、停止)的监听实现
 */
public class CustomScrollView extends NestedScrollView {
    private static final int CHECK_SCROLL_STOP_DELAY_MILLIS = 80;
    private static final int MSG_SCROLL = 1;

    private boolean mIsTouched = false;
    private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;

    private OnScrollListener mOnScrollListener;

    private final Handler mHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {

        private int mLastY = Integer.MIN_VALUE;

        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == MSG_SCROLL) {
                final int scrollY = getScrollY();
                if (!mIsTouched && mLastY == scrollY) {
                    mLastY = Integer.MIN_VALUE;
                    setScrollState(OnScrollListener.SCROLL_STATE_IDLE);
                } else {
                    mLastY = scrollY;
                    restartCheckStopTiming();
                }
                return true;
            }
            return false;
        }
    });

    private void restartCheckStopTiming() {
        mHandler.removeMessages(MSG_SCROLL);
        mHandler.sendEmptyMessageDelayed(MSG_SCROLL, CHECK_SCROLL_STOP_DELAY_MILLIS);
    }

    public CustomScrollView(Context context) {
        super(context);
    }

    public CustomScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setOnScrollListener(OnScrollListener onScrollListener) {
        mOnScrollListener = onScrollListener;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        handleDownEvent(ev);
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        handleUpEvent(ev);
        return super.onTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mIsTouched) {
            setScrollState(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
        } else {
            setScrollState(OnScrollListener.SCROLL_STATE_FLING);
            restartCheckStopTiming();
        }
        if (mOnScrollListener != null) {
            mOnScrollListener.onScroll(this, mIsTouched, l, t, oldl, oldt);
        }
    }

    private void handleDownEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mIsTouched = true;
                break;
        }
    }

    private void handleUpEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mIsTouched = false;
                restartCheckStopTiming();
                break;
        }
    }

    private void setScrollState(int state) {
        if (mScrollState != state) {
            mScrollState = state;
            if (mOnScrollListener != null) {
                mOnScrollListener.onScrollStateChanged(this, state);
            }
        }
    }

    public interface OnScrollListener {
        // 空闲状态
        int SCROLL_STATE_IDLE = 0;
        // 触摸滚动,手指仍在屏幕上
        int SCROLL_STATE_TOUCH_SCROLL = 1;
        // 滚动结束
        int SCROLL_STATE_FLING = 2;

        void onScrollStateChanged(CustomScrollView view, int scrollState);

        void onScroll(CustomScrollView view, boolean isTouchScroll, int l, int t, int oldl, int oldt);
    }
}

布局文件




    

        

            
            
        
    

使用起来还是蛮简单的

package per.juan.popupwindowdome;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private CustomScrollView mScrollView;
    private CustomPopupWindow mCustomPopupWindow;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mScrollView =findViewById(R.id.nested_scroll_view);

        mCustomPopupWindow = new CustomPopupWindow(this, mScrollView);
        mCustomPopupWindow.show();
    }
}

好了,本篇文章已经全部写完了,有什么疑问的,请在下面留言,存在不对的地方还望指导,感谢

你可能感兴趣的:(【Android进阶】)