开发中需要外部添加指示器动画,指示器跟着banner时长显示增长进度动画,但是遇到banner无法监听到触摸事件,banner内部包裹viewpager 设置touchevent没有回调。
方案1
子视图itemview设置触摸事件,
holder.itemView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_OUTSIDE) {
indicator.setLottieState(0);
// start();
} else if (action == MotionEvent.ACTION_DOWN) {
indicator.setLottieState(1);
// stop();
}
return false;
}
});
这样可以监听到触摸,但是触摸滑动被释放,不能达到预期效果,再加上banner滑动事件监听,效果不佳
@Override
public void onPageScrollStateChanged(int state) {
// if (state == ViewPager2.SCROLL_STATE_DRAGGING) {
// indicator.setLottieState(1);//stop
// } else if (state == ViewPager2.SCROLL_STATE_IDLE){
// indicator.setLottieState(0);//start
// }
方案2
直接重写banner类和scrollManager类,增加dispatchTouchEvent回调从里面处理触摸和离开事件
//增加接口回调
private OnTouchListener onTouchListener;
public void setOnBannerTouchListener(OnTouchListener onTouchListener) {
this.onTouchListener = onTouchListener;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!getViewPager2().isUserInputEnabled()) {
return super.dispatchTouchEvent(ev);
}
if (onTouchListener!=null){//回调给外部
//返回啥都无所谓 不用
boolean none = onTouchListener.onTouch(this,ev);
}
int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_OUTSIDE) {
start();
} else if (action == MotionEvent.ACTION_DOWN) {
stop();
}
return super.dispatchTouchEvent(ev);
}
//设置监听
banner.setOnBannerTouchListener((v1, event) -> {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_OUTSIDE) {
indicator.setLottieState(0);
} else if (action == MotionEvent.ACTION_DOWN) {
indicator.setLottieState(1);
}
return false;
});
方案3
/**
* @author mahongyin
* 重写事件分发
*/
public class DisPatchTouchBanner<T,VB extends BannerAdapter> extends Banner<T,VB> {
public DisPatchTouchBanner(Context context) {
super(context);
}
public DisPatchTouchBanner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DisPatchTouchBanner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private OnTouchListener onTouchListener;
public void setOnBannerTouchListener(OnTouchListener onTouchListener) {
this.onTouchListener = onTouchListener;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!getViewPager2().isUserInputEnabled()) {//同样优先viewpager
return super.dispatchTouchEvent(ev);
}
if (onTouchListener!=null){//回调给外部
//返回啥都无所谓 不用
boolean none = onTouchListener.onTouch(this,ev);
}
return super.dispatchTouchEvent(ev);
}
}
//设置监听
//只能在事件分发时处理 因为在子itemview的触摸事件有些event事件vp的内部处理不了的
banner.setOnBannerTouchListener((v1, event) -> {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_OUTSIDE) {
indicator.setLottieState(0);
} else if (action == MotionEvent.ACTION_DOWN) {
indicator.setLottieState(1);
}
return false;
});
题外话
//给banner设置圆角
banner.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 12);
}
});
banner.setClipToOutline(true);