android自定义下拉刷新使用ViewDraghelper处理事件

主要是使用ViewDragHelper处理的滑动侦听

privateViewDragHelperdragHelper;

privateViewmContentView;

privateViewGroupmTopView;

privateListViewlistView;

privateRecyclerViewrecyclerView;

privateScrollViewscrollView;

privateImageViewiv_circel;

privateRelativeLayoutrl_content;

private intmWidth,mHeight;

private intmaxRange=0;//最大下拉的高度

private intrefreshHeight;//下拉出发刷新的高度

private inttext_bottom;//中间文字的底部

private intdownY;

private intchildViewTop;

private booleanisMoveChildView,isLayout;//是否包含可滑动的view true包含

private booleanisStop,isStartAnim;//是否停止刷新,是否开启动画

//下拉刷新的状态

private final intSTATE_DOWN=0;//下拉中

private final intSTATE_REFRESHING=1;//刷新中

private final intSTATE_REFRESH=2;//可刷新

private intcurrent_state=STATE_DOWN;

//属性值

private intrefresh_gravity=1;//1 top 2 center 3 bottom

privateOnRefreshListenerlistener;

private booleanisRefresh=true;//是否可以刷新

privateTextViewtv_text;

publicRefreshView(Context context) {

this(context, null);

}

publicRefreshView(Context context,AttributeSet attrs) {

this(context,attrs,0);

}

publicRefreshView(Context context,AttributeSet attrs, intdefStyleAttr) {

super(context,attrs,defStyleAttr);

init();

//获取自定义属性

TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.refreshView);

refresh_gravity= ta.getInt(R.styleable.refreshView_refresh_gravity,1);

ta.recycle();

}

public interfaceOnRefreshListener {

voidonRefresh();

}

public voidsetOnRefreshListener(OnRefreshListener listener) {

this.listener= listener;

}

public voidsetIsRefresh(booleanisRefresh) {

this.isRefresh= isRefresh;

}

private voidinit() {

dragHelper= ViewDragHelper.create(this, newMyCallBack());

}

@Override

protected voidonSizeChanged(intw, inth, intoldw, intoldh) {

super.onSizeChanged(w,h,oldw,oldh);

mWidth= w;

mHeight= h;

}

@Override

protected voidonFinishInflate() {

super.onFinishInflate();

//健壮性检查

if(getChildCount() >1) {

throw newRuntimeException("只能包含一个子view或viewgroup");

}

if(getChildCount() ==0) {

throw newRuntimeException("not childview,childview would not be null!");

}

isLayout=false;

//因为在onFinishInflate中添加一个viewgroup在0的位置

mContentView= getChildAt(0);//获取布局中的view

isMoveChildView= childType(mContentView);//查看是否有可滑动的view

//添加下拉刷新头布局

mTopView= (ViewGroup) View.inflate(getContext(),R.layout.layout_refresh, null);

addView(mTopView,0);

rl_content= (RelativeLayout)mTopView.findViewById(R.id.fl_header);

rl_content.measure(0,0);

refreshHeight=rl_content.getMeasuredHeight();

tv_text= (TextView)mTopView.findViewById(R.id.tv_text);

iv_circel= (ImageView)mTopView.findViewById(R.id.iv_circel);

iv_circel.setAlpha(0.0f);

//根据设置的属性设置头布局的位置

if(refresh_gravity==1) {

rl_content.setGravity(Gravity.TOP);

}else if(refresh_gravity==2) {

rl_content.setGravity(Gravity.CENTER);

}else{

rl_content.setGravity(Gravity.BOTTOM);

}

}

/**

*判断此view是否是可滑动的view,或此view中是否包含可滑动的view(listview,scrollview,recyclerview)

*

*@paramview

*@returntrue则表示包含可滑动的view

*/

private booleanchildType(View view) {

booleanconform =false;

conform = isTypeConform(view,conform);

if(!conform) {

if(viewinstanceofViewGroup) {

ViewGroup viewGroup = (ViewGroup) view;

intchildCount = viewGroup.getChildCount();

for(inti =0;i < childCount;i++) {

View childView = viewGroup.getChildAt(i);

if(childViewinstanceofViewGroup) {

booleantypeConform = isTypeConform(childView,conform);

if(typeConform) {

childViewTop= childView.getTop();//可滑动view的初始top值

returntypeConform;

}

childType(childView);

}

}

}

}

returnconform;

}

/**

*是否是可滑动的view

*/

private booleanisTypeConform(View view, booleantype) {

if(viewinstanceofListView) {

type =true;

listView= (ListView) view;

}else if(viewinstanceofRecyclerView) {

recyclerView= (RecyclerView) view;

type =true;

}else if(viewinstanceofScrollView) {

scrollView= (ScrollView) view;

type =true;

}

returntype;

}

@Override

protected voidonLayout(booleanchanged, intleft, inttop, intright, intbottom) {

if(!isLayout) {

if(iv_circel!=null&&isStartAnim) {

iv_circel.clearAnimation();

isStartAnim=false;

iv_circel.setAlpha(0.0f);

}

super.onLayout(changed,left,top,right,bottom);

}

maxRange=mHeight-refreshHeight;//最大下拉距离

text_bottom=refreshHeight-refreshHeight/2;

mTopView.layout(0,-(mHeight-refreshHeight),mWidth,refreshHeight);

isLayout=false;

//重新摆放刷新布局

if(refresh_gravity==1&&mContentView.getTop() >=refreshHeight) {

mTopView.setTranslationY(mContentView.getTop() -refreshHeight);

}

}

@Override

public booleanonInterceptTouchEvent(MotionEvent ev) {

if(ev.getAction() == MotionEvent.ACTION_DOWN) {

downY= (int) ev.getY();

}

returndragHelper.shouldInterceptTouchEvent(ev);

}

@Override

public booleanonTouchEvent(MotionEvent event) {

dragHelper.processTouchEvent(event);

return true;

}

private classMyCallBackextendsViewDragHelper.Callback {

/**

*返回可拖拽的范围

*/

@Override

public intgetViewVerticalDragRange(View child) {

//如果包含可滑动的view

if(isMoveChildView&&downY>childViewTop) {

if(listView!=null&&listView.getAdapter() !=null) {

View childView =listView.getChildAt(0);

if(listView.getAdapter().getCount() >0&& childView !=null&& childView.getTop() <0)

return super.getViewVerticalDragRange(child);

}else if(scrollView!=null&&scrollView.getScrollY() >0) {

return super.getViewVerticalDragRange(child);

}else if(recyclerView!=null&&recyclerView.getAdapter() !=null&&recyclerView.getChildAt(0).getTop() <0) {

return super.getViewVerticalDragRange(child);

}

}

returnmaxRange;

}

/**

*返回true表示可以拖拽

*/

@Override

public booleantryCaptureView(View child, intpointerId) {

//如果触摸的是刷新的头部view或者是设置为不可刷新则返回false

if(child ==mTopView|| !isRefresh) {

return false;

}

return true;

}

/**

*当被拖拽的view移动位置后,会调用此方法。可以用于处理View之间的联动

*/

@Override

public voidonViewPositionChanged(View changedView, intleft, inttop, intdx, intdy) {

super.onViewPositionChanged(changedView,left,top,dx,dy);

//处理上面view的移动

floatmoveTop = top;

if(moveTop >=text_bottom) {

floatalpha = (moveTop -text_bottom) /text_bottom;

if(alpha >1) {

alpha =1.0f;

}else if(alpha <0.0) {

alpha =0.0f;

}

iv_circel.setAlpha(alpha);

}else{

iv_circel.setAlpha(0.0f);

}

if(tv_text!=null) {

isLayout=true;

tv_text.setText("下拉刷新");

}

if(moveTop >=refreshHeight) {

if(iv_circel!=null&&isStartAnim) {

isStartAnim=false;

iv_circel.clearAnimation();

}

if(refresh_gravity==1) {

isLayout=true;

LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)rl_content.getLayoutParams();

params.height= (int) moveTop;

rl_content.setLayoutParams(params);

rl_content.requestLayout();

}else if(refresh_gravity==2||refresh_gravity==3) {

floattranslationY = moveTop -refreshHeight;

mTopView.setTranslationY(translationY);

}

}

}

/**

*拖拽松开时调用

*/

@Override

public voidonViewReleased(View releasedChild, floatxvel, floatyvel) {

super.onViewReleased(releasedChild,xvel,yvel);

intmContentViewTop =mContentView.getTop();

if(mContentViewTop >refreshHeight) {

current_state=STATE_REFRESH;

refreshOpen();

}else{

close();

}

}

/**

*返回top值

*/

@Override

public intclampViewPositionVertical(View child, inttop, intdy) {

floatnewTop = top/** 0.93f*/;

if(newTop >=maxRange) {

newTop =maxRange;

}else if(top <0) {

newTop =0;

}

return(int) newTop;

}

}

/**

*开始刷新 并且滚动至相应的位置

*/

private voidrefreshOpen() {

inttop =refreshHeight;

if(dragHelper.smoothSlideViewTo(mContentView,0,top)) {

ViewCompat.postInvalidateOnAnimation(this);

}

}

/**

*关闭面板 此时下拉的高度没有达到刷新的高度,滚动至0的位置

*/

private voidclose() {

inttop =0;

if(dragHelper.smoothSlideViewTo(mContentView,0,top)) {

ViewCompat.postInvalidateOnAnimation(this);

}

isLayout=false;

current_state=STATE_DOWN;

iv_circel.clearAnimation();

}

@Override

public voidcomputeScroll() {

//        super.computeScroll();

if(dragHelper.continueSettling(true)) {

ViewCompat.postInvalidateOnAnimation(this);

}else if(mContentView.getTop() >=refreshHeight&¤t_state==STATE_REFRESH) {

startAnim();

current_state=STATE_REFRESHING;//改变状态

if(listener!=null) {

listener.onRefresh();

}

if(tv_text!=null) {

tv_text.setText("刷新中");

isLayout=true;

}

}

}

private longduration=500L;

private voidstartAnim() {

isStop=false;

duration=500L;

isStartAnim=true;

RotateAnimation anim =newRotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5F,Animation.RELATIVE_TO_SELF,0.5F);

anim.setDuration(duration);

anim.setRepeatCount(Animation.INFINITE);

anim.setInterpolator(newLinearInterpolator());

iv_circel.startAnimation(anim);

anim.setAnimationListener(newAnimation.AnimationListener() {

@Override

public voidonAnimationStart(Animation animation) {

}

@Override

public voidonAnimationEnd(Animation animation) {

current_state=STATE_DOWN;//清楚动画的同时并改变是否刷新的状态

if(tv_text!=null) {

isLayout=true;

tv_text.setText("刷新完毕");

}

postDelayed(newRunnable() {

@Override

public voidrun() {

close();//回滚至顶部

}

},300);

}

@Override

public voidonAnimationRepeat(Animation animation) {

if(!isStop) {

duration-=100;

if(duration<=230) {

duration=230;

}

}else{

duration+=100;

if(duration>=500) {

duration=500;

anim.setRepeatCount(1);

}

}

anim.setDuration(duration);

}

});

}

/**

*刷新完毕

*/

public voidrefreshFinish() {

isStop=true;

}

}

自定义属性

< declare-styleable name="refreshView">

<enum name="refresh_top" value="1"/>

<enum name="refresh_center" value="2"/>

<enum name="refresh_bottom" value="3"/>

<declare-styleable/>

头部布局

<LinearLayout 

android:id="@+id/ll_header"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@android:color/holo_green_light"

android:gravity="bottom"

android:orientation="vertical">

android:id="@+id/fl_header"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal"

android:gravity="bottom"

android:paddingBottom="20dp"

android:paddingTop="20dp">

<FramLayout

android:layout_width="wrap_content"

android:layout_height="wrap_content">

android:id="@+id/tv_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:text="下拉刷新"

android:textColor="@android:color/black"

android:textSize="12sp"/>

android:id="@+id/iv_circel"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:scaleType="fitXY"

android:src="@mipmap/circle"/>

</Framlayout>

欢迎大神指点

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容