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

主要是使用ViewDragHelper處理的滑動(dòng)偵聽

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;//是否包含可滑動(dòng)的view true包含

private booleanisStop,isStartAnim;//是否停止刷新,是否開啟動(dòng)畫

//下拉刷新的狀態(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("只能包含一個(gè)子view或viewgroup");

}

if(getChildCount() ==0) {

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

}

isLayout=false;

//因?yàn)樵趏nFinishInflate中添加一個(gè)viewgroup在0的位置

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

isMoveChildView= childType(mContentView);//查看是否有可滑動(dòng)的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);

//根據(jù)設(shè)置的屬性設(shè)置頭布局的位置

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是否是可滑動(dòng)的view,或此view中是否包含可滑動(dòng)的view(listview,scrollview,recyclerview)

*

*@paramview

*@returntrue則表示包含可滑動(dòng)的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();//可滑動(dòng)view的初始top值

returntypeConform;

}

childType(childView);

}

}

}

}

returnconform;

}

/**

*是否是可滑動(dòng)的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) {

//如果包含可滑動(dòng)的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或者是設(shè)置為不可刷新則返回false

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

return false;

}

return true;

}

/**

*當(dāng)被拖拽的view移動(dòng)位置后,會(huì)調(diào)用此方法。可以用于處理View之間的聯(lián)動(dòng)

*/

@Override

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

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

//處理上面view的移動(dòng)

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);

}

}

}

/**

*拖拽松開時(shí)調(diào)用

*/

@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;

}

}

/**

*開始刷新 并且滾動(dòng)至相應(yīng)的位置

*/

private voidrefreshOpen() {

inttop =refreshHeight;

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

ViewCompat.postInvalidateOnAnimation(this);

}

}

/**

*關(guān)閉面板 此時(shí)下拉的高度沒有達(dá)到刷新的高度,滾動(dòng)至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;//清楚動(dòng)畫的同時(shí)并改變是否刷新的狀態(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>

歡迎大神指點(diǎn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 說到下拉刷新控件,網(wǎng)上版本有很多,很多軟件也都有下拉刷新功能。有一個(gè)叫XListView的,我看別人用過,沒看過是...
    AiPuff閱讀 3,510評(píng)論 3 43
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,667評(píng)論 25 709
  • afinalAfinal是一個(gè)android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,834評(píng)論 2 45
  • 今天是母親節(jié),我無論如何應(yīng)該為母親寫點(diǎn)什么。 當(dāng)面說聲“媽媽我愛你”還真不好意思,但是,對(duì)母親的愛卻是深深地刻在我...
    青石山人閱讀 489評(píng)論 1 0
  • 1:感恩天地滋養(yǎng)萬物,感恩列祖列宗護(hù)佑,感恩父母給予生命。感恩一草一木,一花一樹。 2:在樓梯口看到一個(gè)孩子搬單車...
    吉秀wang閱讀 224評(píng)論 0 1

友情鏈接更多精彩內(nèi)容