Android(安卓)类ListView下拉刷新控件实现 .
Android下拉刷新,在目前好多应用被使用到。
比如微博,下拉刷新更多数据。
一般我们在运用的ListView,本身就实现了下拉获取更多数据。只是这个下拉刷新的操作时在listView拉到底端的监听。
对于ListView刷新,我们可以分为两种情况:
1.获取更多的数据,按服务器数据库时间顺序存储入情况,此刻我们是获取是显示在我们应用中的数据更早前的数据,这也是最常见的情况。
比如(微博获取更多信息,就是获取更多更早前的信息,然后动态的添加到已有的数据的下方);
2.获取更多的最新的数据,其实还是一种获取更多的操作方式。但是这里主要考虑到用户的操作习惯了。一般,用户的操作习惯分这么两种
第一种,获取下一页,第二种,类似于网页的F5刷新,停留在当前页面的刷新。
ListView刷新其实类似于网页。如果没用下拉刷新,那么用户得将ListView拖拉到最后(当然也可以是在界面顶端添加一个刷新按钮控件,但是,对于手机这样界面不是很大,这样的设计其实是不应太多的。),如果数据太多,那么用户要下拉到很下面才能执行刷新。而对于大多数用户习惯,获取更多的最新资讯后,希望他添加的时候是在界面最上面的显眼处的。也就是,用户还是喜欢的是懒操作,在同一个可显示界面完成所有操作。那么,下拉刷新是一个不错的设计。
效果图:正常状态
下拉刷新:
基本效果就是这样。
自定义控件代码
[java] view plain copy print ?- /**
- *刷新控制view
- *
- *@authorNono
- *
- */
- publicclassRefreshableViewextendsLinearLayout{
- privatestaticfinalStringTAG="LILITH";
- privateScrollerscroller;
- privateViewrefreshView;
- privateImageViewrefreshIndicatorView;
- privateintrefreshTargetTop=-60;
- privateProgressBarbar;
- privateTextViewdownTextView;
- privateTextViewtimeTextView;
- privateRefreshListenerrefreshListener;
- privateStringdownTextString;
- privateStringreleaseTextString;
- privateLongrefreshTime=null;
- privateintlastX;
- privateintlastY;
- //拉动标记
- privatebooleanisDragging=false;
- //是否可刷新标记
- privatebooleanisRefreshEnabled=true;
- //在刷新中标记
- privatebooleanisRefreshing=false;
- privateContextmContext;
- publicRefreshableView(Contextcontext){
- super(context);
- mContext=context;
- }
- publicRefreshableView(Contextcontext,AttributeSetattrs){
- super(context,attrs);
- mContext=context;
- init();
- }
- privatevoidinit(){
- //TODOAuto-generatedmethodstub
- //滑动对象,
- scroller=newScroller(mContext);
- //刷新视图顶端的的view
- refreshView=LayoutInflater.from(mContext).inflate(R.layout.refresh_top_item,null);
- //指示器view
- refreshIndicatorView=(ImageView)refreshView.findViewById(R.id.indicator);
- //刷新bar
- bar=(ProgressBar)refreshView.findViewById(R.id.progress);
- //下拉显示text
- downTextView=(TextView)refreshView.findViewById(R.id.refresh_hint);
- //下来显示时间
- timeTextView=(TextView)refreshView.findViewById(R.id.refresh_time);
- LayoutParamslp=newLinearLayout.LayoutParams(LayoutParams.FILL_PARENT,-refreshTargetTop);
- lp.topMargin=refreshTargetTop;
- lp.gravity=Gravity.CENTER;
- addView(refreshView,lp);
- downTextString=mContext.getResources().getString(R.string.refresh_down_text);
- releaseTextString=mContext.getResources().getString(R.string.refresh_release_text);
- }
- /**
- *刷新
- *@paramtime
- */
- privatevoidsetRefreshText(Stringtime){
- //TODOAuto-generatedmethodstub
- //timeTextView.setText(time);
- }
- @Override
- publicbooleanonTouchEvent(MotionEventevent){
- inty=(int)event.getRawY();
- switch(event.getAction()){
- caseMotionEvent.ACTION_DOWN:
- //记录下y坐标
- lastY=y;
- break;
- caseMotionEvent.ACTION_MOVE:
- Log.i(TAG,"ACTION_MOVE");
- //y移动坐标
- intm=y-lastY;
- if(((m<6)&&(m>-1))||(!isDragging)){
- doMovement(m);
- }
- //记录下此刻y坐标
- this.lastY=y;
- break;
- caseMotionEvent.ACTION_UP:
- Log.i(TAG,"ACTION_UP");
- fling();
- break;
- }
- returntrue;
- }
- /**
- *up事件处理
- */
- privatevoidfling(){
- //TODOAuto-generatedmethodstub
- LinearLayout.LayoutParamslp=(LayoutParams)refreshView.getLayoutParams();
- Log.i(TAG,"fling()"+lp.topMargin);
- if(lp.topMargin>0){//拉到了触发可刷新事件
- refresh();
- }else{
- returnInitState();
- }
- }
- privatevoidreturnInitState(){
- //TODOAuto-generatedmethodstub
- LinearLayout.LayoutParamslp=(LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
- inti=lp.topMargin;
- scroller.startScroll(0,i,0,refreshTargetTop);
- invalidate();
- }
- privatevoidrefresh(){
- //TODOAuto-generatedmethodstub
- LinearLayout.LayoutParamslp=(LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
- inti=lp.topMargin;
- refreshIndicatorView.setVisibility(View.GONE);
- bar.setVisibility(View.VISIBLE);
- timeTextView.setVisibility(View.GONE);
- downTextView.setVisibility(View.GONE);
- scroller.startScroll(0,i,0,0-i);
- invalidate();
- if(refreshListener!=null){
- refreshListener.onRefresh(this);
- isRefreshing=true;
- }
- }
- /**
- *
- */
- @Override
- publicvoidcomputeScroll(){
- //TODOAuto-generatedmethodstub
- if(scroller.computeScrollOffset()){
- inti=this.scroller.getCurrY();
- LinearLayout.LayoutParamslp=(LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
- intk=Math.max(i,refreshTargetTop);
- lp.topMargin=k;
- this.refreshView.setLayoutParams(lp);
- this.refreshView.invalidate();
- invalidate();
- }
- }
- /**
- *下拉move事件处理
- *@parammoveY
- */
- privatevoiddoMovement(intmoveY){
- //TODOAuto-generatedmethodstub
- LinearLayout.LayoutParamslp=(LayoutParams)refreshView.getLayoutParams();
- if(moveY>0){
- //获取view的上边距
- floatf1=lp.topMargin;
- floatf2=moveY*0.3F;
- inti=(int)(f1+f2);
- //修改上边距
- lp.topMargin=i;
- //修改后刷新
- refreshView.setLayoutParams(lp);
- refreshView.invalidate();
- invalidate();
- }
- timeTextView.setVisibility(View.VISIBLE);
- if(refreshTime!=null){
- setRefreshTime(refreshTime);
- }
- downTextView.setVisibility(View.VISIBLE);
- refreshIndicatorView.setVisibility(View.VISIBLE);
- bar.setVisibility(View.GONE);
- if(lp.topMargin>0){
- downTextView.setText(R.string.refresh_release_text);
- refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_up);
- }else{
- downTextView.setText(R.string.refresh_down_text);
- refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_down);
- }
- }
- publicvoidsetRefreshEnabled(booleanb){
- this.isRefreshEnabled=b;
- }
- publicvoidsetRefreshListener(RefreshListenerlistener){
- this.refreshListener=listener;
- }
- /**
- *刷新时间
- *@paramrefreshTime2
- */
- privatevoidsetRefreshTime(Longtime){
- //TODOAuto-generatedmethodstub
- }
- /**
- *结束刷新事件
- */
- publicvoidfinishRefresh(){
- Log.i(TAG,"执行了=====finishRefresh");
- LinearLayout.LayoutParamslp=(LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
- inti=lp.topMargin;
- refreshIndicatorView.setVisibility(View.VISIBLE);
- timeTextView.setVisibility(View.VISIBLE);
- scroller.startScroll(0,i,0,refreshTargetTop);
- invalidate();
- isRefreshing=false;
- }
- /*该方法一般和ontouchEvent一起用
- *(non-Javadoc)
- *@seeandroid.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
- */
- @Override
- publicbooleanonInterceptTouchEvent(MotionEvente){
- //TODOAuto-generatedmethodstub
- intaction=e.getAction();
- inty=(int)e.getRawY();
- switch(action){
- caseMotionEvent.ACTION_DOWN:
- lastY=y;
- break;
- caseMotionEvent.ACTION_MOVE:
- //y移动坐标
- intm=y-lastY;
- //记录下此刻y坐标
- this.lastY=y;
- if(m>6&&canScroll()){
- returntrue;
- }
- break;
- caseMotionEvent.ACTION_UP:
- break;
- caseMotionEvent.ACTION_CANCEL:
- break;
- }
- returnfalse;
- }
- privatebooleancanScroll(){
- //TODOAuto-generatedmethodstub
- ViewchildView;
- if(getChildCount()>1){
- childView=this.getChildAt(1);
- if(childViewinstanceofListView){
- inttop=((ListView)childView).getChildAt(0).getTop();
- intpad=((ListView)childView).getListPaddingTop();
- if((Math.abs(top-pad))<3&&
- ((ListView)childView).getFirstVisiblePosition()==0){
- returntrue;
- }else{
- returnfalse;
- }
- }elseif(childViewinstanceofScrollView){
- if(((ScrollView)childView).getScrollY()==0){
- returntrue;
- }else{
- returnfalse;
- }
- }
- }
- returnfalse;
- }
- /**
- *刷新监听接口
- *@authorNono
- *
- */
- publicinterfaceRefreshListener{
- publicvoidonRefresh(RefreshableViewview);
- }
- }
/** * 刷新控制view * * @author Nono * */public class RefreshableView extends LinearLayout {private static final String TAG = "LILITH";private Scroller scroller;private View refreshView;private ImageView refreshIndicatorView;private int refreshTargetTop = -60;private ProgressBar bar;private TextView downTextView;private TextView timeTextView;private RefreshListener refreshListener;private String downTextString;private String releaseTextString;private Long refreshTime = null;private int lastX;private int lastY;// 拉动标记private boolean isDragging = false;// 是否可刷新标记private boolean isRefreshEnabled = true;// 在刷新中标记private boolean isRefreshing = false;private Context mContext;public RefreshableView(Context context) {super(context);mContext = context;}public RefreshableView(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;init();}private void init() {// TODO Auto-generated method stub//滑动对象,scroller = new Scroller(mContext);//刷新视图顶端的的view refreshView = LayoutInflater.from(mContext).inflate(R.layout.refresh_top_item, null);//指示器view refreshIndicatorView = (ImageView) refreshView.findViewById(R.id.indicator);//刷新barbar = (ProgressBar) refreshView.findViewById(R.id.progress);//下拉显示text downTextView = (TextView) refreshView.findViewById(R.id.refresh_hint);//下来显示时间 timeTextView = (TextView) refreshView.findViewById(R.id.refresh_time);LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, -refreshTargetTop);lp.topMargin = refreshTargetTop;lp.gravity = Gravity.CENTER;addView(refreshView, lp);downTextString = mContext.getResources().getString(R.string.refresh_down_text);releaseTextString = mContext.getResources().getString(R.string.refresh_release_text);}/** * 刷新 * @param time */private void setRefreshText(String time) {// TODO Auto-generated method stub//timeTextView.setText(time);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int y= (int) event.getRawY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN://记录下y坐标lastY = y;break;case MotionEvent.ACTION_MOVE:Log.i(TAG, "ACTION_MOVE");//y移动坐标int m = y - lastY;if(((m < 6) && (m > -1)) || (!isDragging )){ doMovement(m);}//记录下此刻y坐标this.lastY = y;break;case MotionEvent.ACTION_UP:Log.i(TAG, "ACTION_UP");fling();break;}return true;}/** * up事件处理 */private void fling() {// TODO Auto-generated method stubLinearLayout.LayoutParams lp = (LayoutParams) refreshView.getLayoutParams();Log.i(TAG, "fling()" + lp.topMargin);if(lp.topMargin > 0){//拉到了触发可刷新事件refresh();}else{returnInitState();}}private void returnInitState() {// TODO Auto-generated method stub LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams(); int i = lp.topMargin; scroller.startScroll(0, i, 0, refreshTargetTop); invalidate();}private void refresh() {// TODO Auto-generated method stub LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams(); int i = lp.topMargin; refreshIndicatorView.setVisibility(View.GONE); bar.setVisibility(View.VISIBLE); timeTextView.setVisibility(View.GONE); downTextView.setVisibility(View.GONE); scroller.startScroll(0, i, 0, 0-i); invalidate(); if(refreshListener !=null){ refreshListener.onRefresh(this); isRefreshing = true; }}/** * */@Overridepublic void computeScroll() {// TODO Auto-generated method stubif(scroller.computeScrollOffset()){int i = this.scroller.getCurrY(); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams(); int k = Math.max(i, refreshTargetTop); lp.topMargin = k; this.refreshView.setLayoutParams(lp); this.refreshView.invalidate(); invalidate();}}/** * 下拉move事件处理 * @param moveY */private void doMovement(int moveY) {// TODO Auto-generated method stubLinearLayout.LayoutParams lp = (LayoutParams) refreshView.getLayoutParams();if(moveY > 0){//获取view的上边距float f1 =lp.topMargin;float f2 = moveY * 0.3F;int i = (int)(f1+f2);//修改上边距lp.topMargin = i;//修改后刷新refreshView.setLayoutParams(lp);refreshView.invalidate();invalidate();}timeTextView.setVisibility(View.VISIBLE);if(refreshTime!= null){setRefreshTime(refreshTime);}downTextView.setVisibility(View.VISIBLE);refreshIndicatorView.setVisibility(View.VISIBLE);bar.setVisibility(View.GONE);if(lp.topMargin > 0){downTextView.setText(R.string.refresh_release_text);refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_up);}else{downTextView.setText(R.string.refresh_down_text);refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_down);}}public void setRefreshEnabled(boolean b) {this.isRefreshEnabled = b;}public void setRefreshListener(RefreshListener listener) {this.refreshListener = listener;}/** * 刷新时间 * @param refreshTime2 */private void setRefreshTime(Long time) {// TODO Auto-generated method stub}/** * 结束刷新事件 */public void finishRefresh(){Log.i(TAG, "执行了=====finishRefresh"); LinearLayout.LayoutParams lp= (LinearLayout.LayoutParams)this.refreshView.getLayoutParams(); int i = lp.topMargin; refreshIndicatorView.setVisibility(View.VISIBLE); timeTextView.setVisibility(View.VISIBLE); scroller.startScroll(0, i, 0, refreshTargetTop); invalidate(); isRefreshing = false; }/*该方法一般和ontouchEvent 一起用 * (non-Javadoc) * @see android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent) */@Overridepublic boolean onInterceptTouchEvent(MotionEvent e) {// TODO Auto-generated method stubint action = e.getAction();int y= (int) e.getRawY();switch (action) {case MotionEvent.ACTION_DOWN:lastY = y;break;case MotionEvent.ACTION_MOVE://y移动坐标int m = y - lastY;//记录下此刻y坐标this.lastY = y; if(m > 6 && canScroll()){ return true; }break;case MotionEvent.ACTION_UP:break;case MotionEvent.ACTION_CANCEL:break;}return false;}private boolean canScroll() {// TODO Auto-generated method stubView childView;if(getChildCount()>1){childView = this.getChildAt(1);if(childView instanceof ListView){int top =((ListView)childView).getChildAt(0).getTop(); int pad =((ListView)childView).getListPaddingTop(); if((Math.abs(top-pad)) < 3&&((ListView) childView).getFirstVisiblePosition() == 0){return true;}else{return false;}}else if(childView instanceof ScrollView){if(((ScrollView)childView).getScrollY() == 0){return true;}else{return false;}}}return false;}/** * 刷新监听接口 * @author Nono * */public interface RefreshListener{public void onRefresh(RefreshableView view);}}
此控件自定义实现一个线性布局,内部包含一个第一个子控件,刷新显示的View。
因为对于ListView下拉刷新的例子网上挺多的,上次我朋友也做,说特么弄了一个礼拜发现一个问题,listview里面条目太少时,刷新的view就会显示出来。
我没具体看过那个代码,也不知道到底什么情况。
自个定义的稍微用了点小技巧。即,我将刷新view的topMargin设置为了该view的高度的负数,那么,他就刚好隐藏起来了。
对于上面那个对于条目太少而造成刷新的view显示的bug有所解决。
[java] view plain copy print ?- @Override
- publicbooleanonTouchEvent(MotionEventevent){
- inty=(int)event.getRawY();
- switch(event.getAction()){
- caseMotionEvent.ACTION_DOWN:
- //记录下y坐标
- lastY=y;
- break;
- caseMotionEvent.ACTION_MOVE:
- Log.i(TAG,"ACTION_MOVE");
- //y移动坐标
- intm=y-lastY;
- if(((m<6)&&(m>-1))||(!isDragging)){
- doMovement(m);
- }
- //记录下此刻y坐标
- this.lastY=y;
- break;
- caseMotionEvent.ACTION_UP:
- Log.i(TAG,"ACTION_UP");
- fling();
- break;
- }
- returntrue;
- }
- /*该方法一般和ontouchEvent一起用
- *(non-Javadoc)
- *@seeandroid.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
- */
- @Override
- publicbooleanonInterceptTouchEvent(MotionEvente){
- //TODOAuto-generatedmethodstub
- intaction=e.getAction();
- inty=(int)e.getRawY();
- switch(action){
- caseMotionEvent.ACTION_DOWN:
- lastY=y;
- break;
- caseMotionEvent.ACTION_MOVE:
- //y移动坐标
- intm=y-lastY;
- //记录下此刻y坐标
- this.lastY=y;
- if(m>6&&canScroll()){
- returntrue;
- }
- break;
- caseMotionEvent.ACTION_UP:
- break;
- caseMotionEvent.ACTION_CANCEL:
- break;
- }
- returnfalse;
- }
@Overridepublic boolean onTouchEvent(MotionEvent event) {int y= (int) event.getRawY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN://记录下y坐标lastY = y;break;case MotionEvent.ACTION_MOVE:Log.i(TAG, "ACTION_MOVE");//y移动坐标int m = y - lastY;if(((m < 6) && (m > -1)) || (!isDragging )){ doMovement(m);}//记录下此刻y坐标this.lastY = y;break;case MotionEvent.ACTION_UP:Log.i(TAG, "ACTION_UP");fling();break;}return true;}/*该方法一般和ontouchEvent 一起用 * (non-Javadoc) * @see android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent) */@Overridepublic boolean onInterceptTouchEvent(MotionEvent e) {// TODO Auto-generated method stubint action = e.getAction();int y= (int) e.getRawY();switch (action) {case MotionEvent.ACTION_DOWN:lastY = y;break;case MotionEvent.ACTION_MOVE://y移动坐标int m = y - lastY;//记录下此刻y坐标this.lastY = y; if(m > 6 && canScroll()){ return true; }break;case MotionEvent.ACTION_UP:break;case MotionEvent.ACTION_CANCEL:break;}return false;}
控件使用:
[html] view plain copy print ?
- <PREclass=htmlname="code"><com.xxx.xxxx.view.RefreshableViewandroid:orientation="vertical"android:id="@+id/refresh_root"
- android:layout_width="fill_parent"android:layout_height="wrap_content"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <ListViewandroid:id="@+id/def_list"android:layout_width="fill_parent"
- android:scrollbars="none"android:fadingEdge="none"
- android:layout_height="wrap_content"android:scrollingCache="false">
- </ListView>
- </com.xxxx.xxxxx.view.RefreshableView></PRE><PREstyle="BACKGROUND-COLOR:rgb(255,255,255)"class=htmlname="code"><PREstyle="BACKGROUND-COLOR:rgb(255,255,255)"class=htmlname="code"></PRE>
- <P></P>
- <P></P>
- <P>即,我的listview是以该控件的第二个子view加入进去。此刻又会遇到一个问题:我在界面执行下拉时,应用如何分辨我是执行的RefreshableView下拉刷新操作,还是listview下拉操作。这个问题一开始挺悲剧的,就是当我的listview中数据挺多,那我手势一网上滑,此刻操作不会出现冲突,因为刷新View监听的下滑事件监听;然后此刻listview滑到了底部,我要回到listview顶部去,就得执行向下滑操作,那么这时的操作就和刷新view中下滑,下拉刷新监听冲突。后来发现了view中两个函数:子控件截取事件函数。具体来说是就是用的点击屏幕,touch事件会先被onInterceptTouchEvent捕捉,子view先做处理,然后根据true和false,才判断是否截取事件交给父View处理。那么我们就可以在onInterceptTouchEvent做了预处理,更具判断listview是佛在最底部,可下滑,来判断是佛让子view来截取处理该touch事件。具体判断看canScroll();同样的考虑到ScrollView类似有listview的情况,也做了处理,因此该控件支持包含listview和scrollview。实现代码基本如上,内部可能还有挺多的bug,但是目前我应用上实现暂没发现。最后感谢网上的可刷新代码demo,以及sina微博可刷新控件代码以及网易应用可刷新控件代码。</P>
- <P></P>
- <P></P>
- <P></P>
- <P></P>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
- </PRE>
[html] view plain copy print ?
- <com.xxx.xxxx.view.RefreshableViewandroid:orientation="vertical"android:id="@+id/refresh_root"
- android:layout_width="fill_parent"android:layout_height="wrap_content"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <ListViewandroid:id="@+id/def_list"android:layout_width="fill_parent"
- android:scrollbars="none"android:fadingEdge="none"
- android:layout_height="wrap_content"android:scrollingCache="false">
- </ListView>
- </com.xxxx.xxxxx.view.RefreshableView>
<com.xxx.xxxx.view.RefreshableView android:orientation="vertical" android:id="@+id/refresh_root" android:layout_width="fill_parent" android:layout_height="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android" ><ListView android:id="@+id/def_list" android:layout_width="fill_parent"android:scrollbars="none" android:fadingEdge="none"android:layout_height="wrap_content" android:scrollingCache="false"></ListView></com.xxxx.xxxxx.view.RefreshableView>[html] view plain copy print ?
- <PREstyle="BACKGROUND-COLOR:rgb(255,255,255)"class=htmlname="code"></PRE>
- <P></P>
- <P></P>
- <P>即,我的listview是以该控件的第二个子view加入进去。此刻又会遇到一个问题:我在界面执行下拉时,应用如何分辨我是执行的RefreshableView下拉刷新操作,还是listview下拉操作。这个问题一开始挺悲剧的,就是当我的listview中数据挺多,那我手势一网上滑,此刻操作不会出现冲突,因为刷新View监听的下滑事件监听;然后此刻listview滑到了底部,我要回到listview顶部去,就得执行向下滑操作,那么这时的操作就和刷新view中下滑,下拉刷新监听冲突。后来发现了view中两个函数:子控件截取事件函数。具体来说是就是用的点击屏幕,touch事件会先被onInterceptTouchEvent捕捉,子view先做处理,然后根据true和false,才判断是否截取事件交给父View处理。那么我们就可以在onInterceptTouchEvent做了预处理,更具判断listview是佛在最底部,可下滑,来判断是佛让子view来截取处理该touch事件。具体判断看canScroll();同样的考虑到ScrollView类似有listview的情况,也做了处理,因此该控件支持包含listview和scrollview。实现代码基本如上,内部可能还有挺多的bug,但是目前我应用上实现暂没发现。最后感谢网上的可刷新代码demo,以及sina微博可刷新控件代码以及网易应用可刷新控件代码。</P>
- <P></P>
- <P></P>
- <P></P>
- <P></P>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
[html] view plain copy print ?
即,我的listview是以该控件的第二个子view加入进去。此刻又会遇到一个问题:我在界面执行下拉时,应用如何分辨我是执行的RefreshableView下拉刷新操作,还是listview下拉操作。这个问题一开始挺悲剧的,就是当我的listview中数据挺多,那我手势一网上滑,此刻操作不会出现冲突,因为刷新View监听的下滑事件监听;然后此刻listview滑到了底部,我要回到listview顶部去,就得执行向下滑操作,那么这时的操作就和刷新view中下滑,下拉刷新监听冲突。后来发现了view中两个函数:子控件截取事件函数。具体来说是就是用的点击屏幕,touch事件会先被onInterceptTouchEvent捕捉,子view先做处理,然后根据true和false,才判断是否截取事件交给父View处理。那么我们就可以在onInterceptTouchEvent做了预处理,更具判断listview是佛在最底部,可下滑,来判断是佛让子view来截取处理该touch事件。具体判断看canScroll();同样的考虑到ScrollView类似有listview的情况,也做了处理,因此该控件支持包含listview和scrollview。实现代码基本如上,内部可能还有挺多的bug,但是目前我应用上实现暂没发现。最后感谢网上的可刷新代码demo,以及sina微博可刷新控件代码以及网易应用可刷新控件代码。
分享到:
- 10
- 踩
- 0
查看评论
- 13楼 DaweiKoo 2013-04-28 10:18发表 [回复] [引用] [举报]
-
- 新手学习。感谢分享。
- 12楼 Rockey723 2013-03-14 13:40发表 [回复] [引用] [举报]
-
- 大神厉害,顶
- Re: Rockey723 2013-03-14 13:49发表 [回复] [引用] [举报]
-
- 回复Rockey723:非常的齐全
- 11楼 _Zero 2013-01-24 14:05发表 [回复] [引用] [举报]
-
- 学习下!!!!!
- 10楼 枫叶雅少 2013-01-24 08:54发表 [回复] [引用] [举报]
- Re: Rockey723 2013-03-14 13:49发表 [回复] [引用] [举报]
- 回复Rockey723:非常的齐全
更多相关文章
- Android(安卓)View分区域点击实现方案——1.根据坐标范围
- Android(安卓)RecyclerView删除多个选中的item 及 局部刷新
- Android(安卓)补间动画之平移动画TranslateAnimation
- Android(安卓)基于坐标的图形开发
- Android变形(Transform)之Matrix用法
- android 屏幕坐标总结
- Android画布canvas rotate,translate的理解
- Android实现仿QQ登录可编辑下拉菜单
- Android实现滑动的七种方法实践