关于这方面的文章百度下有很多,我就只写写我自己实现过程。

我觉得学习一门语言不是做了几个项目就可以认为自己会了,这只是暂时的,若没有笔记,时间长了,你是怎么解决某些问题,估计连你自己都忘了,又得费时费力的重新研究~ 这就是我为什么写这篇文章的原因。

现在公司做Android是用AndroidStudio来做的,AndroidStudio开发是需要搞gradle 的,有点麻烦,我就直接上Eclipse上做些测试例子~

进入正文:

下拉的刷新的实现主要是基于ListView这个控件扩展来的。ListView的数据需要由“适配器”来提供,这个跟之前的web开发有些差异。以前做集合控件开发时,将一些有规律的数据直接与控件绑定就可以显示了。但Android却不行,为什么呢?因为ListView是个多功能控件,它能将不同数据表现实现都在一个集合中展示。那不同的形式要在一个容器中展示就涉及到“适配”的问题。

(什么的适配?我的理解就是匹配,插口转换之类的)

原来ListView要呈现不同子视图,所以就需要一个适配器来做“兼容”~

下拉ListView时它上面会有“刷新”等图标及文字,这是怎么做到的? ListView类中有个addHeaderView(View v) 方法,我们将 【放好“刷新”等图标及文字】的一个子视图,通过这个方法将这个子视图放到ListView中,就可以从“逻辑上”了解了,上面那块“刷新”的东东是怎么来的。

新增的Head视图(Layout)
原ListView

有了这个组合,剩下的就是滑动相关了~

由于我们是要实现“下拉刷新”效果的,且这个效果是基于ListView控件的,所以我们需要自定义一个ListView控件,我们叫它mListView吧~

在继续下面文章之前,我提一个代码使用技巧,高手略过~

Begin---------------------------------------------------------------------------------------------------------------------------

如图:

我们把相关事件定义在辅类时,实现却在主类中来实现,怎么来实现呢?

在辅类中定义一个接口如IInterface1

辅类部分代码Code-begin -------------------------------------

IInterface1 iobj;

public void setIInterface1(IInterface1 l)

{

  iobj=l;

}

然后,在相应事件中直接使用iobj.doSomeThing() 把位置占住~

辅类部分代码Code-end -------------------------------------

主类Activity implementsIInterface1 (主类Activity实现 辅类中定义的接口及方法)

public override doSomeThing(){......}

KEY:主类中调用辅类的 setIInterface1 方法把自己放进去 如:setIInterface1(this);

小节下,辅类创建一个接口定义些抽象方法,在相关事件把位置占好,并提供外部set接口实例的方法,主类实现接口把自己做为接口的实现者传入辅类中,成功替换之前的占位抽象方法~

End---------------------------------------------------------------------------------------------------------------------------

以上逻辑将用于下拉触点时,调用相关刷新数据(加载数据)

自定义的mListView 需要 实现(implements)OnScrollListener 接口,

申明一个Scroller 实例,如下:

mScroller=new Scroller(context,new DecelerateInterpolator());

重写onTouchEvent 方法

根据不同事件保存与调用滑动方法

mScroller.startScroll(0, height, 0, finalHeight-height,SCROLL_DURATION);

然后就是调用方法 invalidate() 重绘界面

仅仅调用Scroller的startScroll方法是不能实现滚动的~ 还有个关键方法 computeScroll ,你可能需要重写这个方法

@Override    public void computeScroll() {                if(mScroller.computeScrollOffset())        {            mHeaderView.setVisiableHeight(mScroller.getCurrY());                        postInvalidate();            invokeOnScrolling();        }        super.computeScroll();    }

每次滑动时都会调用这个computerScroll()方法,

mScroller.computeScrollOffset()   /////  是否有偏移

postInvalidate()     /////  刷新界面与 Invalidate  有点细微差别~
  

以上就是我的小节~

直接贴代码吧~ 如下:

package com.example.androidtest1.widget;import android.content.Context;import android.text.format.Time;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewTreeObserver.OnGlobalLayoutListener;import android.view.animation.DecelerateInterpolator;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.Scroller;import com.example.androidtest1.R;public class XListView extends ListView implements OnScrollListener {        private float mLastY = -1; // save event y    private Scroller mScroller;    private OnScrollListener mScrollListener; ///// 滚动侦听        private IXListViewListener mListViewListener; ///// 触发刷新接口        private Context m_context;    private XListViewHeader mHeaderView;    private RelativeLayout mHeaderViewContent;    private int mHeaderViewHeight;    private boolean mEnablePullRefresh=true;  //// 是否允许下拉刷新    private boolean mPullRefreshing=false;    //// 下拉刷新中?        //////  list  中的数量    private int mTotalItemCount;        private int mScrollBack;    private final static int SCROLLBACK_HEADER=0;    private final static int SCROLLBACK_FOOTER=1;        private final static int SCROLL_DURATION=400;    private final static int PULL_LOAD_MORE_DELTA=50;        private final static float OFFSET_RADIO=1.8f;        public XListView(Context context) {        super(context);        initWidthContext(context);    }        public XListView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initWidthContext(context);    }    public XListView(Context context, AttributeSet attrs) {        super(context, attrs);        initWidthContext(context);    }    private void initWidthContext(Context context)    {        mScroller=new Scroller(context,new DecelerateInterpolator());        super.setOnScrollListener(this);                m_context=context;        mHeaderView=new XListViewHeader(context);        mHeaderViewContent=(RelativeLayout) mHeaderView.findViewById(R.id.xlistview_header_content);        addHeaderView(mHeaderView);                mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(                new OnGlobalLayoutListener(){                    @Override                    public void onGlobalLayout() {                        mHeaderViewHeight=mHeaderViewContent.getHeight();                        getViewTreeObserver().removeGlobalOnLayoutListener(this);                    }                });    }        /**     * 准备刷新中~     */    public void pullRefreshing(){        if(!mEnablePullRefresh){            return;        }        mHeaderView.setVisiableHeight(mHeaderViewHeight);        mPullRefreshing=true;        mHeaderView.setState(XListViewHeader.STATE_READY);    }        /*     * 设置能否下拉刷新     */    public void setPullRefreshEnable(boolean enable){        mEnablePullRefresh=enable;        if(!mEnablePullRefresh){            mHeaderViewContent.setVisibility(View.INVISIBLE);        }else{            mHeaderViewContent.setVisibility(View.VISIBLE);        }    }        /**     * 停止刷新     */    public void stopRefresh(){        Time time=new Time();        time.setToNow();        mHeaderView.setRefreshTime(time.format("%Y-%m-%d %T"));        if(mPullRefreshing==true){            mPullRefreshing=false;            resetHeaderHeight();        }    }        /**     * 未处于刷新状态,更新箭头     * @param delta     */    private void updateHeaderHeight(float delta)    {        mHeaderView.setVisiableHeight((int)delta+mHeaderView.getVisiableHeight());        if(mEnablePullRefresh && !mPullRefreshing){            if(mHeaderView.getVisiableHeight()>mHeaderViewHeight){                mHeaderView.setState(XListViewHeader.STATE_READY);            }else{                mHeaderView.setState(XListViewHeader.STATE_NORMAL);            }        }        setSelection(0);    }        /**     * 重置自定义头部高度     */    private void resetHeaderHeight()    {        int height=mHeaderView.getVisiableHeight();        if(height==0)            return;                /*         * 下拉刷新的高度不够~         * */        if(mPullRefreshing && height<=mHeaderViewHeight)        {            mListViewListener.reShowMoreView();        }        int finalHeight=0;        if(mPullRefreshing && height>mHeaderViewHeight){            finalHeight=mHeaderViewHeight;        }                mScrollBack=SCROLLBACK_HEADER;                //////  设置滚动        mScroller.startScroll(0, height, 0, finalHeight-height,SCROLL_DURATION);                //////  触发computeScroll        invalidate();    }        private void invokeOnScrolling(){        if(mScrollListener instanceof OnXScrollListener){            OnXScrollListener l=(OnXScrollListener)mScrollListener;            l.onXScrolling(this);        }    }        @Override    public boolean onTouchEvent(MotionEvent ev) {                if(mLastY==-1)            mLastY=ev.getRawY();                switch(ev.getAction()){        case MotionEvent.ACTION_DOWN:            mLastY=ev.getRawY();            break;        case MotionEvent.ACTION_MOVE:            final float deltaY=ev.getRawY()-mLastY;            mLastY=ev.getRawY();            if(getFirstVisiblePosition()==0                    && (mHeaderView.getVisiableHeight()>0 || deltaY>0))            {                updateHeaderHeight(deltaY/OFFSET_RADIO);                invokeOnScrolling();            }            break;        default:            mLastY=-1;            if(getFirstVisiblePosition()==0){                if(mHeaderView.getVisiableHeight()>0)                    mPullRefreshing=true;                                if(mEnablePullRefresh && mHeaderView.getVisiableHeight()>mHeaderViewHeight){                    mHeaderView.setState(XListViewHeader.STATE_REFRESHING);                    if(mListViewListener!=null){                        mListViewListener.onRefresh();                    }                }                resetHeaderHeight();            }            break;        }        return super.onTouchEvent(ev);    }        @Override    public void onScroll(AbsListView view, int firstVisibleItem,            int visibleItemCount, int totalItemCount) {        mTotalItemCount=totalItemCount;        if(mScrollListener!=null)        {            mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);        }    }    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        if(mScrollListener!=null)        {            mScrollListener.onScrollStateChanged(view, scrollState);        }    }        @Override    public void computeScroll() {                if(mScroller.computeScrollOffset())        {            mHeaderView.setVisiableHeight(mScroller.getCurrY());                        postInvalidate();            invokeOnScrolling();        }        super.computeScroll();    }        @Override    public void setOnScrollListener(OnScrollListener l) {        mScrollListener = l;    }    /**     *      * @param l     */    public void setXListViewListener(IXListViewListener l){        mListViewListener=l;    }        public interface OnXScrollListener extends OnScrollListener{        public void onXScrolling(View view);    }        public interface IXListViewListener{        public void onRefresh();        public void onLoadMore();        public void hiddenShowMoreView();        public void reShowMoreView();    }}

更多相关文章

  1. android AsyncTask使用总结
  2. 将Android通讯录导入iphone的方法
  3. Android中AsyncTask(异步执行任务)的使用
  4. IntelliJ IDEA Export to Eclipse Android工程不能正常被Eclipse
  5. Android(安卓)TextView 展开动画
  6. Android与服务器通信的方法之一(json)效率不高安全性不好
  7. .Net 转战 Android(安卓)4.4 日常笔记(9)--常用组件的使用方法[附
  8. 图解 Android(安卓)事件分发机制 和 handler 机制
  9. Android之Handler有感(一)

随机推荐

  1. EditText默认不弹出键盘
  2. Android实现选择本地音乐
  3. Android(安卓)stdio 3.0以上版本将图片文
  4. input 按键分发
  5. Android(安卓)Studio 将项目打成JAR包
  6. Android版本适配:9.0 Pie(API级别28)
  7. 日拱一卒(十七)
  8. Android(安卓)DeepLink
  9. Android基于HttpUrlConnection类的文件下
  10. android ::JNI WARNING illegal start by