• 分享一个可下拉刷新的ScrollView


    原理:就是动态改变ScrollView header的margin实现

    主要的代码:

     http://blog.csdn.net/swust_chenpeng/article/details/39289721

     
    public class RefreshScrollView extends ScrollView {  
      
        private final static int SCROLL_DURATION = 400;  
        private final static float OFFSET_RADIO = 1.8f;  
        private int headerHeight = 0;  
        private boolean enableRefresh = true;  
        private boolean refreshing = false;  
        private int lastY;  
        private Scroller scroller = null;  
        private OnRefreshScrollViewListener listener = null;  
        private LinearLayout scrollContainer = null;  
        private ScrollViewHeader headerView = null;  
      
        public RefreshScrollView(Context context) {  
            super(context);  
            // TODO Auto-generated constructor stub  
            if (!isInEditMode()) {  
                initView(context);  
            }  
        }  
      
        public RefreshScrollView(Context context, AttributeSet attrs) {  
            super(context, attrs);  
            // TODO Auto-generated constructor stub  
            if (!isInEditMode()) {  
                initView(context);  
            }  
        }  
      
        public RefreshScrollView(Context context, AttributeSet attrs, int defStyle) {  
            super(context, attrs, defStyle);  
            // TODO Auto-generated constructor stub  
            if (!isInEditMode()) {  
                initView(context);  
            }  
        }  
      
        /** 
         * 初始化view 
         */  
        private void initView(Context context) {  
            scroller = new Scroller(context);  
            headerView = new ScrollViewHeader(context);  
            LinearLayout.LayoutParams headerViewParams = new LinearLayout.LayoutParams(  
                    LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);  
            //scrollview只允许嵌套一个子布局  
            scrollContainer = new LinearLayout(context);  
            scrollContainer.addView(headerView, headerViewParams);  
            scrollContainer.setOrientation(LinearLayout.VERTICAL);  
            addView(scrollContainer);  
            //提前获取headerView的高度  
            headerView.getViewTreeObserver().addOnGlobalLayoutListener(  
                    new OnGlobalLayoutListener() {  
      
                        @SuppressWarnings("deprecation")  
                        @Override  
                        public void onGlobalLayout() {  
                            // TODO Auto-generated method stub  
                            headerHeight = headerView.getHeight();  
                            headerView.updateMargin(-headerHeight);  
                            headerView.getViewTreeObserver()  
                                    .removeGlobalOnLayoutListener(this);  
                        }  
                    });  
        }  
      
        /** 
         * 设置内容区域 
         *  
         * @param context 
         * @param resId 
         */  
        public void setupContainer(Context context, View containerView) {  
            scrollContainer.addView(containerView);  
        }  
      
        /** 
         * 设置scroll是否可以刷新 
         *  
         * @param enableRefresh 
         */  
        public void setEnableRefresh(boolean enableRefresh) {  
            this.enableRefresh = enableRefresh;  
        }  
      
        @Override  
        public boolean onTouchEvent(MotionEvent ev) {  
            // TODO Auto-generated method stub  
            switch (ev.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                lastY = (int) ev.getY();  
                break;  
            case MotionEvent.ACTION_MOVE:  
                int deltY = (int) (ev.getY() - lastY);  
                lastY = (int) ev.getY();  
                Logger.d("getScrollY:" + getScrollY());  
                if (getScrollY() == 0  
                        && (deltY > 0 || headerView.getTopMargin() > -headerHeight)) {  
                    updateHeader(deltY/OFFSET_RADIO);  
                    return true;  
                }   
                break;  
            default:  
                //这里没有使用action_up的原因是,可能会受到viewpager的影响接收到action_cacel事件  
                Logger.d("ev.getAction: " +ev.getAction());  
                if (getScrollY() == 0) {  
                    Logger.d("topMargin():" + headerView.getTopMargin());  
                    if (headerView.getTopMargin() > 0 && enableRefresh && !refreshing) {  
                        refreshing = true;  
                        headerView.setState(ScrollViewHeader.STATE_REFRESHING);  
                        new Handler().postDelayed(new Runnable() {  
      
                            @Override  
                            public void run() {  
                                // TODO Auto-generated method stub  
                                if(listener != null) {  
                                    listener.onRefresh();  
                                    refreshing = false;  
                                    ShowUtils.shortShow("更新成功");  
                                    resetHeaderView();  
                                }  
                            }  
                        }, 3000);  
                    }  
                    Logger.d("resetHeaderView...");  
                    resetHeaderView();  
                }  
                break;  
            }  
            return super.onTouchEvent(ev);  
        }  
      
        /** 
         * 更新headerview的高度,同时更改状态 
         *  
         * @param deltY 
         */  
        public void updateHeader(float deltY) {  
            int currentMargin = (int) (headerView.getTopMargin() + deltY);  
            headerView.updateMargin(currentMargin);  
            if(enableRefresh && !refreshing) {  
                if (currentMargin > 0) {  
                    headerView.setState(ScrollViewHeader.STATE_READY);  
                } else {  
                    headerView.setState(ScrollViewHeader.STATE_NORMAL);  
                }  
            }  
        }  
      
        /** 
         * 重置headerview的高度 
         */  
        public void resetHeaderView() {  
            int margin = headerView.getTopMargin();  
            if(margin == -headerHeight) {  
                return ;  
            }  
            if(margin < 0 && refreshing) {  
                //当前已经在刷新,又重新进行拖动,但未拖满,不进行操作  
                return ;  
            }  
            int finalMargin = 0;  
            if(margin <= 0 && !refreshing) {  
                finalMargin = headerHeight;  
            }  
            Logger.d("margin: " + margin);  
            Logger.d("finalMargin: " + finalMargin);  
            //松开刷新,或者下拉刷新,又松手,没有触发刷新  
            scroller.startScroll(0, -margin, 0, finalMargin + margin, SCROLL_DURATION);  
              
            invalidate();  
        }  
          
        /** 
         * 开始刷新 
         */  
        public void startRefresh() {  
            refreshing = true;  
            headerView.setState(ScrollViewHeader.STATE_REFRESHING);  
            if(listener != null) {  
                Logger.d("xxx: " + headerHeight);  
                scroller.startScroll(0, 0, 0, headerHeight, SCROLL_DURATION);  
                invalidate();  
                listener.onRefresh();  
            }  
        }  
          
        /** 
         * 停止刷新 
         */  
        public void stopRefresh() {  
            if(refreshing) {  
                refreshing = false;  
                resetHeaderView();  
            }  
        }  
          
        @Override  
        public void computeScroll() {  
            // TODO Auto-generated method stub  
            if(scroller.computeScrollOffset()) {  
                Logger.d("getCurrY: " + scroller.getCurrY());   
                headerView.updateMargin(-scroller.getCurrY());  
                //继续重绘  
                postInvalidate();  
            }  
            super.computeScroll();  
        }  
          
        public void setOnRefreshScrollViewListener(OnRefreshScrollViewListener listener) {  
            this.listener = listener;  
        }  
          
        public interface OnRefreshScrollViewListener {  
            public void onRefresh();  
        }  
    }  

    代码其实还是比较容易,但是但是,自己还是花了很多时间,脑袋瓜不够灵活呀...

    下面是ScrollViewHeader的代码:

     
    public class ScrollViewHeader extends RelativeLayout {  
          
        public final static int STATE_NORMAL = 0;  
        public final static int STATE_READY = 1;  
        public final static int STATE_REFRESHING = 2;  
        private final int ROTATE_ANIM_DURATION = 180;  
        private int topMargin = 0;  
        private int state = STATE_NORMAL;  
        private TextView refreshTv = null;  
        private TextView refreshTimeTv = null;  
        private ProgressBar refreshProgress = null;  
        private ImageView refreshArrow = null;  
        private Animation animationUp = null;  
        private Animation animationDown = null;  
          
        public ScrollViewHeader(Context context) {  
            super(context);  
            // TODO Auto-generated constructor stub  
            if(!isInEditMode())   
                initView(context);  
        }  
      
        public ScrollViewHeader(Context context, AttributeSet attrs) {  
            super(context, attrs);  
            // TODO Auto-generated constructor stub  
            if(!isInEditMode())  
                initView(context);  
        }  
      
        public ScrollViewHeader(Context context, AttributeSet attrs, int defStyle) {  
            super(context, attrs, defStyle);  
            // TODO Auto-generated constructor stub  
            if(!isInEditMode())  
                initView(context);  
        }  
      
        /** 
         * 初始化相关的view 
         */  
        public void initView(Context context) {  
            animationDown = new RotateAnimation(-180f, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);  
            animationDown.setDuration(ROTATE_ANIM_DURATION);  
            animationDown.setFillAfter(true);  
            animationUp = new RotateAnimation(0, -180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);  
            animationUp.setDuration(ROTATE_ANIM_DURATION);  
            animationUp.setFillAfter(true);  
            setPadding(10, 25, 10, 25);  
            View view = LayoutInflater.from(context).inflate(R.layout.scrollview_header, this, true);  
            refreshTv = (TextView) view.findViewById(R.id.refresh_text);  
            refreshTimeTv = (TextView) view.findViewById(R.id.refresh_time);  
            refreshProgress = (ProgressBar) view.findViewById(R.id.refresh_progress);  
            refreshArrow = (ImageView) view.findViewById(R.id.refresh_arrow);  
        }  
          
        /** 
         * 设置scrollviewHeader的状态 
         * @param state 
         */  
        public void setState(int state) {  
            if(this.state == state) {  
                return ;  
            }  
            switch (state) {  
            case STATE_NORMAL:  
                refreshTv.setText("下拉刷新");  
                refreshArrow.setVisibility(View.VISIBLE);  
                refreshProgress.setVisibility(View.INVISIBLE);  
                if(this.state == STATE_READY) {  
                    refreshArrow.startAnimation(animationDown);  
                } else if(this.state == STATE_REFRESHING) {  
                    refreshArrow.clearAnimation();  
                }  
                break;  
            case STATE_READY:  
                refreshTv.setText("松开刷新");  
                refreshArrow.setVisibility(View.VISIBLE);  
                refreshProgress.setVisibility(View.INVISIBLE);  
                refreshArrow.startAnimation(animationUp);  
                break;  
            case STATE_REFRESHING:  
                refreshTv.setText("正在加载...");  
                refreshProgress.setVisibility(View.VISIBLE);  
                refreshArrow.clearAnimation();  
                refreshArrow.setVisibility(View.INVISIBLE);  
                break;  
            default:  
                break;  
            }  
            this.state = state;  
        }  
          
        /** 
         * 更新header的margin 
         * @param margin 
         */  
        public void updateMargin(int margin) {  
            //这里用Linearlayout的原因是Headerview的父控件是scrollcontainer是一个linearlayout   
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) this.getLayoutParams();  
            params.topMargin = margin;  
            topMargin = margin;  
            setLayoutParams(params);  
        }  
          
        /** 
         * 获取header的margin 
         * @return 
         */  
        public int getTopMargin() {  
            return topMargin;  
        }  
    }  

    header的布局文件,scrollview_header

    <?xml version="1.0" encoding="utf-8"?>  
    <merge xmlns:android="http://schemas.android.com/apk/res/android" >  
      
        <LinearLayout  
            android:id="@+id/refresh_des"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_centerInParent="true"  
            android:gravity="center"  
            android:orientation="vertical" >  
      
            <TextView  
                android:id="@+id/refresh_text"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:text="下拉刷新" />  
      
            <TextView  
                android:id="@+id/refresh_time"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:text="5分钟前更新" />  
        </LinearLayout>  
      
        <ProgressBar  
            android:id="@+id/refresh_progress"  
            android:layout_width="30dip"  
            android:layout_height="30dip"  
            android:layout_centerVertical="true"  
            android:layout_marginRight="10dip"  
            android:layout_toLeftOf="@id/refresh_des"  
            android:visibility="invisible" />  
      
        <ImageView  
            android:id="@+id/refresh_arrow"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_centerVertical="true"  
            android:layout_marginRight="10dip"  
            android:layout_toLeftOf="@id/refresh_des"  
            android:src="@drawable/arrow" />  
      
    </merge>  

    好了,相关的源码就只有3个文件...

  • 相关阅读:
    linux常用命令
    ANAFI EXTENOED无人机(1)环境配置和基础开发
    无人机自主降落
    ROS开发(1)安装环境
    bebop无人机(1)环境配置和基础开发
    YOLO标注软件
    Python2与Python3之间切换
    python实现IOU计算
    读取多个(海康大华)网络摄像头的视频流 (使用opencv-python),解决实时读取延迟问题
    如何到外面的世界看看
  • 原文地址:https://www.cnblogs.com/lbangel/p/4108898.html
Copyright © 2020-2023  润新知