支持listview、GridView、普通布局、scrollview和viewpager的下拉刷新控件
来源:互联网 发布:极品飞车17截图软件 编辑:程序博客网 时间:2024/04/27 18:27
支持listview、GridView、scrollview和viewpager的下拉刷新(经测试未发现bug),但是不支持viewpager中嵌套listview、GridView等可上下滑动组件的情况,本来想作支持的,但是鉴于viewpager的嵌套的可能性太过复杂,最后还是放弃了。以下为scrollview刷新效果图
用法如下:
1.布局文件如下,只需将需要刷新效果的控件包裹在该控件中即可,注意只能有一个子控件,如果使用普通布局的情况,可使用布局进行包裹。
<com.zp.scrolltest.RefreshView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/refresh_view"> <!--<GridView--> <!--android:layout_width="match_parent"--> <!--android:layout_height="match_parent"--> <!--android:numColumns="1"--> <!--android:visibility="gone"--> <!--android:id="@+id/grid_view"/>--> <!--<ListView--> <!--android:layout_width="match_parent"--> <!--android:layout_height="match_parent"--> <!--android:background="#ff9900"--> <!--android:id="@+id/list_view"--> <!--android:visibility="gone"--> <!--android:text="content"/>--> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#00ff00"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="300dp" android:text="hhhhhhh"/> <TextView android:layout_width="wrap_content" android:layout_height="300dp" android:text="hhhhhhh"/> <TextView android:layout_width="wrap_content" android:layout_height="300dp" android:text="hhhhhhh"/> <TextView android:layout_width="wrap_content" android:layout_height="300dp" android:text="hhhhhhh"/> </LinearLayout> </ScrollView> <!--<LinearLayout--> <!--android:layout_width="match_parent"--> <!--android:layout_height="wrap_content"--> <!--android:orientation="vertical">--> <!--<TextView--> <!--android:layout_width="wrap_content"--> <!--android:layout_height="300dp"--> <!--android:text="hhhhhhh"/>--> <!--</LinearLayout>--> </com.zp.scrolltest.RefreshView>
Java代码中使用:
refresh_view = (RefreshView)findViewById(R.id.refresh_view); refresh_view.setOnRefshing(new RefreshView.OnRefshing() { @Override public void refresh() {// Toast.makeText(MainActivity.this, "hahah you are me", Toast.LENGTH_SHORT).show(); } }); refresh_view.setTime("2017-1-9 12:12:56");
可对刷新事件进行监听,可设置刷新时间(如果不设置则不显示该效果),可手动触发刷新(startRefresh())和停止刷新效果(stopRefresh())。
源码如下:
package com.zp.scrolltest;import android.content.Context;import android.os.Handler;import android.os.Message;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.util.Log;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.GridView;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.ScrollView;import android.widget.Scroller;import android.widget.TextView;import java.util.Calendar;/** * Created by ez on 2017/5/8. */public class RefreshView extends LinearLayout { TextView status_tv, refresh_time; ProgressBar progressBar; Context context; float lastY; int SCREEN_HEIGHT; Scroller scroller; int mHeight = 200; public static final int PREPARE = 0; public static final int WILLREFRESH = 1; public static final int REFRESHING = 2; public static final int END = 3; private int status; private int delayTime = 2000; boolean inControl;//临界点过度控制,由listview或者其他部分下拉到顶,触发滑动效果时用到 OnRefshing onRefshing; boolean isTopHidden; Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { return false; } }); public RefreshView(Context context) { super(context); init(context); } public RefreshView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public RefreshView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context){ this.context = context; SCREEN_HEIGHT = context.getResources().getDisplayMetrics().heightPixels; setOrientation(VERTICAL); LinearLayout ll = new LinearLayout(context); ll.setOrientation(HORIZONTAL); ll.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mHeight)); ll.setGravity(Gravity.CENTER); progressBar = new ProgressBar(context); progressBar.setVisibility(View.GONE); ll.addView(progressBar); LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(VERTICAL); linearLayout.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); status_tv = new TextView(context); LayoutParams param = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); param.setMargins(20, 0, 30, 0); status_tv.setLayoutParams(param); status_tv.setText("下拉刷新"); status_tv.setTextSize(16); status_tv.setGravity(Gravity.CENTER); linearLayout.addView(status_tv); refresh_time = new TextView(context); refresh_time.setLayoutParams(param); refresh_time.setText("刷新时间:"); refresh_time.setTextSize(12); refresh_time.setVisibility(View.GONE); linearLayout.addView(refresh_time); ll.addView(linearLayout); addView(ll); scrollTo(0, mHeight); scroller = new Scroller(context); status = PREPARE; } public void setDelayTime(int time){ this.delayTime = time; } public void setOnRefshing(OnRefshing onRefshing){ this.onRefshing = onRefshing; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); ViewGroup.LayoutParams params = getChildAt(1).getLayoutParams(); params.height = getMeasuredHeight(); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: lastY = ev.getY(); break; case MotionEvent.ACTION_MOVE: View view = getChildAt(1); float dy = ev.getY()-lastY; Log.e("zp", "坐标:"+ev.getY()); //作用于下面的组件滑动到最顶端,重新分发事件响应刷新动作 if(dy>0){ if(view instanceof ListView){ ListView lv = (ListView)view; View c = lv.getChildAt(lv.getFirstVisiblePosition()); if(c!=null && c.getTop()==0 && !inControl){ inControl = true; ev.setAction(MotionEvent.ACTION_CANCEL); MotionEvent ev2 = MotionEvent.obtain(ev); dispatchTouchEvent(ev); ev2.setAction(MotionEvent.ACTION_DOWN); return dispatchTouchEvent(ev2); } }else if(view instanceof ScrollView){ ScrollView sv = (ScrollView)view; if(sv.getScrollY()==0 && !inControl){ inControl = true; ev.setAction(MotionEvent.ACTION_CANCEL); MotionEvent ev2 = MotionEvent.obtain(ev); dispatchTouchEvent(ev); ev2.setAction(MotionEvent.ACTION_DOWN); return dispatchTouchEvent(ev2); } }else if(view instanceof GridView){ GridView gv = (GridView)view; View c = gv.getChildAt(gv.getFirstVisiblePosition()); if(c!=null && c.getTop()==0 && !inControl){ inControl = true; ev.setAction(MotionEvent.ACTION_CANCEL); MotionEvent ev2 = MotionEvent.obtain(ev); dispatchTouchEvent(ev); ev2.setAction(MotionEvent.ACTION_DOWN); return dispatchTouchEvent(ev2); } } } break; } return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: View view = getChildAt(1); float dy = ev.getY()-lastY; Log.e("zp", "坐标1:"+ev.getY()); //下拉且下面组件为顶端时,阻断事件向下层传递,直接触发本身的touch事件 if(dy>0){ if(view instanceof ListView){ ListView lv = (ListView)view; View c = lv.getChildAt(lv.getFirstVisiblePosition()); if(c!=null && c.getTop()==0 && inControl){ return true; } }else if(view instanceof ScrollView){ ScrollView sv = (ScrollView)view; if(sv.getScrollY()==0 && inControl){ return true; } }else if(view instanceof GridView){ GridView gv = (GridView)view; View c = gv.getChildAt(gv.getFirstVisiblePosition()); if(c!=null && c.getTop()==0 && inControl){ return true; } }else if(view instanceof ViewPager){ return true; } } break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: status = PREPARE; return true; case MotionEvent.ACTION_MOVE: //加入判断,防止多次刷新,同时也不影响界面的滑动 if(status!=REFRESHING){ float disY = event.getY()-lastY; lastY = event.getY(); Log.e("zp", "坐标2:"+event.getY()); int ty = getScrollY(); scrollBy(0, -(int)disY/2); if(getScrollY()<10){ status_tv.setText("松开手刷新"); status = WILLREFRESH; }else{ status_tv.setText("下拉刷新"); status = PREPARE; } //作用于刷新动作上滑取消,重新分发事件,响应下面组件的滑动效果 if(disY<0 && mHeight == getScrollY()){ event.setAction(MotionEvent.ACTION_DOWN); dispatchTouchEvent(event); inControl = false; } } break; case MotionEvent.ACTION_UP: if(status==PREPARE){ scroller.startScroll(0, getScrollY(), 0, mHeight-getScrollY(), 200); status_tv.setText("下拉刷新"); status = END; } else if(status == WILLREFRESH){ status = REFRESHING; scroller.startScroll(0, getScrollY(), 0, -getScrollY(), 200); progressBar.setVisibility(View.VISIBLE); status_tv.setText("正在刷新..."); if(onRefshing!=null){ onRefshing.refresh(); } handler.postDelayed(new Runnable() { @Override public void run() { stopRefresh(); } }, delayTime); } inControl = false; break; case MotionEvent.ACTION_CANCEL: if(scroller.isFinished()){ scroller.abortAnimation(); } break; } return super.onTouchEvent(event); } @Override public void computeScroll() { if (scroller.computeScrollOffset()) { scrollTo(0, scroller.getCurrY()); } invalidate(); } /** * scrollBy最终还是依靠scrollTo实现,这里的条件可以屏蔽上滑导致整个页面往上走,下面出现空白 * 便于处理事件的重新分发过程 * @param x * @param y */ @Override public void scrollTo(int x, int y) { if (y > mHeight) { y = mHeight; } if (y != getScrollY()) { super.scrollTo(x, y); } isTopHidden = getScrollY() == mHeight; } private String getTime(){ Calendar calendar=Calendar.getInstance(); return "上次刷新:"+calendar.get(Calendar.MONTH)+"-"+calendar.get(Calendar.DAY_OF_MONTH)+" "+calendar.get(Calendar.HOUR_OF_DAY)+":"+calendar.get(Calendar.MINUTE)+":"+calendar.get(Calendar.SECOND); } public void setTime(String time){ refresh_time.setVisibility(View.VISIBLE ); refresh_time.setText(time); } public void startRefresh(){ if(status!=REFRESHING){ status = REFRESHING; scroller.startScroll(0, getScrollY(), 0, -getScrollY(), 200); status_tv.setText("正在刷新..."); progressBar.setVisibility(View.VISIBLE); if(onRefshing!=null){ onRefshing.refresh(); } handler.postDelayed(new Runnable() { @Override public void run() { stopRefresh(); } }, delayTime); } } public void stopRefresh(){ if(status==REFRESHING){ progressBar.setVisibility(View.GONE); scroller.startScroll(0, getScrollY(), 0, mHeight-getScrollY(), 200); status_tv.setText("下拉刷新"); status = END; handler.removeCallbacksAndMessages(null); } } public interface OnRefshing{ void refresh(); }}
0 0
- 支持listview、GridView、普通布局、scrollview和viewpager的下拉刷新控件
- Android 下拉刷新,上拉加载更多控件–支持ListView,GridView和ScrollView
- Android 下拉刷新,上拉加载更多控件--支持ListView,GridView和ScrollView
- Android下拉刷新,上拉加载更多控件–支持ListView,GridView和ScrollView
- Android自定义控件(一):下拉刷新,支持ListView和GridView
- Android自定义控件(一) 下拉刷新,上拉分页加载更多(支持ListView, GridView, ScrollView)
- Android自定义控件(二) 下拉刷新,上拉分页加载更多(支持ListView, GridView, ScrollView)
- listview、gridView、ScrollView 下拉刷新
- 下拉刷新+分页加载通用版本支持gridview、listview、scrollview
- 上拉刷新,下拉加载的靠谱的第三方。支持listview,scrollview,gridview等等
- 仿苏宁易购下拉刷新控件(支持ListView、ScrollView)
- Android PullToRefresh 下拉刷新,上拉更多,支持ScrollView,ListView,可方便拓展GridView,WebView等
- GridView ListView ScrollView 下拉刷新 上拉加载更多
- 通用的自定义的下拉刷新,上拉更多,适用listView,gridView,ScrollView
- ListView,GridView的下拉刷新和上拉加载。
- PullToRefresh 支持刷新ListView丶GridView丶ScrollView和二级列表
- ListView,GridView下拉刷新
- Android 上拉下拉刷新,支持ListView,GridView,ScrollView
- android内存泄漏简单分析
- hbase和zookeeper的安装和部署
- 微信小程序遇到的坑
- 出名要趁早?赚到第一个100万更要趁早!
- SpringMVC校验
- 支持listview、GridView、普通布局、scrollview和viewpager的下拉刷新控件
- 常用正则表达式
- AndroidManifest文件中activity标签中的内容
- Wex5使用sqlite简单demo
- 图片文件上传预览
- 布局优化ViewStub
- iOS-一行代码搞定复杂的UIBarButtonItem创建(OC+Swift)
- Qt的信号和槽是如何工作的
- 每天一个算法: 全排列算法