前言
博主是个android程序员,最近接了不少私活在做。想写博客也一直没时间,刚好有几个项目交工了才有时间写博客。同时这也是我写的第一篇博客,因为一直以来我都是写开发笔记的。
在做项目的时候我遇到一个需求,一个横向滚动的列表要添加拖动刷新和加载的功能。本着快速开发的原则,我就在网上找别人的控件使用。然而找到一个控件只能左拉加载,却不能同时两端拖动加载。于是就自己写了。
一、先上个效果图
二、创建可以滑动的容器
1、既然是个容器那就直接继承FrameLayout,如下
public class HorizontalRefreshView extends FrameLayout {
public HorizontalRefreshView(Context context) {
super(context);
init(context);
}
public HorizontalRefreshView(Context context, AttributeSet attrs) {
super(context, attrs);
this.attrs = attrs;
init(context);
}
}
2、添加左右两边的的拖动展示控件
leftView = new MoreView(context);
leftView.setId(leftViewId);
leftView.setIsStats(1);
leftView.setText(text1, text2);
leftView.setBgColor(bgColor);
rightView = new MoreView(context);
rightView.setId(rightViewId);
rightView.setIsStats(2);
rightView.setText(text1, text2);
rightView.setBgColor(bgColor);
LayoutParams params = new LayoutParams((int) maxW, -1);
addView(leftView, params);
params = new LayoutParams((int) maxW, -1);
addView(rightView, params);
3、控件是添加进入了,但是还是需要计算控件的位置和控件如何摆放
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
this.r = r;
b = b - t;
this.b = b;
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childAt = getChildAt(i);
if (childAt.getId() == leftViewId) {//左边
childAt.layout(0, 0, 0, b);//将控件宽度设置为0
} else if (childAt.getId() == rightViewId) {
childAt.layout(r, 0, 0, b);
} else {
mChildView = childAt;//获取其中要滚动的view,可以是listview
}
}
}
我将两个控件分别放在一左一右,childAt.layout(0,
0,
0, b);从这可以看出,我将控件的展示宽度设置成0px,后面拖动时就可以改变其宽度。4、拦截触摸事件
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ox = event.getX();//按下时的位置
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
x = ox - x;//计算移动手指的偏移
if (x > 0 && !canScrollLeft()) {//判断是否可以向左滑
scrollStats = 2;
return true;
} else if (x < 0 && !canScrollRight()) {//判断是否可以向右滑
scrollStats = 1;
return true;
}
}
return super.onInterceptTouchEvent(event);
}
5、监听事件并改变控件宽度
public boolean onTouchEvent(MotionEvent event) {//事件监听
if (scrollStats != 0)
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
float x = event.getX();
if (oldX == 0) oldX = x;//第一次监听到移动
else {//计算移动偏移
scrollW = oldX - x;
ViewHelper.setTranslationX(mChildView, -scrollW);//平移控件
Log.v("--scrollW--", "" + scrollW);
Log.v("--scrollStats--", "" + scrollStats);
float scrollW = Math.abs(this.scrollW);
//显示左右的提示控件
if (scrollStats == 1) {
leftView.layout(0, 0, (int) (scrollW > maxW ? maxW : scrollW), b);
leftView.setShowStats(scrollW > maxW ? 2 : 1);
} else if (scrollStats == 2) {
rightView.layout((int) (r - (scrollW > maxW ? maxW : scrollW)), 0, r, b);
rightView.setShowStats(scrollW > maxW ? 2 : 1);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//结束滑动
oldX = 0;
//开启动画
startAnim();
Log.v("--ACTION_UP--", "ACTION_UP");
//触发监听事件
float scrollW = Math.abs(this.scrollW);
if (onHorizontalRefresh != null && scrollW > maxW) {
if (scrollStats == 1) onHorizontalRefresh.OnLeftRefresh(this);
else onHorizontalRefresh.OnRightRefresh(this);
}
return true;
}
return super.onTouchEvent(event);
}
到此这个控件基本上就可以做完了,其中的MoreView 就是拖动出来展示的控件,这个控件可以自己随意更换展示,并不会有什么影响。其实也没什么好说的,注释里写的还是很明白的。篇幅有限,就讲到这了。附上源码地址:https://github.com/cookieci/HorizontalRefresh/