这篇文章主要是仿Keep,通过监听ScrollView滚动事件和滚动状态(开始、停止)来实现向上滑动时PopupWindow向右退出消失,向下移动时PopupWindow向左推出出现的功能,感觉很有趣,于是想着自己动手也实现这样一个功能,和往常一样,主要是想总结一下我在学习过程中的一些笔记以及需要注意的地方。
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();
}
}
好了,本篇文章已经全部写完了,有什么疑问的,请在下面留言,存在不对的地方还望指导,感谢