android自定義下拉刷新使用ViewDraghelper處理事件

主要是使用ViewDragHelper處理的滑動偵聽

privateViewDragHelperdragHelper;

privateViewmContentView;

privateViewGroupmTopView;

privateListViewlistView;

privateRecyclerViewrecyclerView;

privateScrollViewscrollView;

privateImageViewiv_circel;

privateRelativeLayoutrl_content;

private intmWidth,mHeight;

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

private intrefreshHeight;//下拉出發(fā)刷新的高度

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

private intdownY;

private intchildViewTop;

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

private booleanisStop,isStartAnim;//是否停止刷新,是否開啟動畫

//下拉刷新的狀態(tài)

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之間的聯(lián)動

*/

@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;//改變狀態(tài)

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;//清楚動畫的同時并改變是否刷新的狀態(tài)

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>

歡迎大神指點

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容