前言
博主是個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/