天天看點

Android SwipeRefreshLayout下拉重新整理與上拉加載+滑動删除



SwipeRefreshLayout–Google官方提出的下拉重新整理控件,廣泛應用在各種APP中。一直想弄一個既能支援下拉重新整理,又能夠上拉加載,同時還能實作類似于QQ的滑動删除效果。上網找了很多資料,最後達到了下面的效果:

Android SwipeRefreshLayout下拉重新整理與上拉加載+滑動删除

參考資料:

SwipeRefreshLayout的上拉加載與下拉重新整理:

http://blog.csdn.net/u012036813/article/details/38959507

Listview的滑動删除:

http://blog.csdn.net/lmj623565791/article/details/22961279

Android事件傳遞機制:

http://blog.csdn.net/yanzi1225627/article/details/22592831

接下來看看具體實作過程。

1.界面布局:

<<span class="hljs-keyword">com</span><span class="hljs-preprocessor">.example</span><span class="hljs-preprocessor">.swiperefreshlayoutdemo</span><span class="hljs-preprocessor">.RefreshLayout</span>
        xmlns:android=<span class="hljs-string">"http://schemas.android.com/apk/res/android"</span>
        android:id=<span class="hljs-string">"@+id/swipe_container"</span>
        android:layout_width=<span class="hljs-string">"match_parent"</span>
        android:layout_height=<span class="hljs-string">"match_parent"</span> >

        <<span class="hljs-keyword">com</span><span class="hljs-preprocessor">.example</span><span class="hljs-preprocessor">.swiperefreshlayoutdemo</span><span class="hljs-preprocessor">.QQListView</span>
            android:id=<span class="hljs-string">"@+id/list"</span>
            android:layout_width=<span class="hljs-string">"match_parent"</span>
            android:layout_height=<span class="hljs-string">"wrap_content"</span> >
        </<span class="hljs-keyword">com</span><span class="hljs-preprocessor">.example</span><span class="hljs-preprocessor">.swiperefreshlayoutdemo</span><span class="hljs-preprocessor">.QQListView</span>>
    </<span class="hljs-keyword">com</span><span class="hljs-preprocessor">.example</span><span class="hljs-preprocessor">.swiperefreshlayoutdemo</span><span class="hljs-preprocessor">.RefreshLayout</span>>      
因為要實作上拉加載以及滑動删除,是以用的都是自定義的RefreshLayout以及Listview。 
<strong>2.代碼實作:</strong>      

SwipeRefreshLayout的上拉加載實作有兩種方法,一種是實作滑動監聽,當滑動到底部時實作加載更多功能;一種是通過事件傳遞機制監聽上拉動作,然後實作加載更多功能。先看第一種加載原理:

自定義的SwipeRefreshLayout:

<span class="hljs-comment">//繼承自SwipeRefreshLayout,進而實作滑動到底部時上拉加載更多的功能.</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RefreshLayout</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SwipeRefreshLayout</span> <span class="hljs-keyword">implements</span>    <span class="hljs-title">OnScrollListener</span> {</span>

    <span class="hljs-comment">// listview執行個體</span>
    <span class="hljs-keyword">private</span> ListView mListView;
    <span class="hljs-comment">// 上拉接口監聽器, 到了最底部的上拉加載操作</span>
    <span class="hljs-keyword">private</span> OnLoadListener mOnLoadListener;
    <span class="hljs-comment">// ListView的加載中footer</span>
    <span class="hljs-keyword">private</span> View mListViewFooter;
    <span class="hljs-comment">// 是否在加載中 ( 上拉加載更多 )</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> isLoading = <span class="hljs-keyword">false</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-title">RefreshLayout</span>(Context context) {
        <span class="hljs-keyword">this</span>(context, <span class="hljs-keyword">null</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-title">RefreshLayout</span>(Context context, AttributeSet attrs) {
        <span class="hljs-keyword">super</span>(context, attrs);
        <span class="hljs-comment">//一個圓形進度條</span>
        mListViewFooter = LayoutInflater.from(context).inflate(
                R.layout.listview_footer, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">false</span>);
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onLayout</span>(<span class="hljs-keyword">boolean</span> changed, <span class="hljs-keyword">int</span> left, <span class="hljs-keyword">int</span> top, <span class="hljs-keyword">int</span> right,
            <span class="hljs-keyword">int</span> bottom) {
        <span class="hljs-keyword">super</span>.onLayout(changed, left, top, right, bottom);
        <span class="hljs-comment">// 初始化ListView對象</span>
        <span class="hljs-keyword">if</span> (mListView == <span class="hljs-keyword">null</span>) {
            getListView();
        }
    }

    <span class="hljs-comment">// 擷取ListView對象</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">getListView</span>() {
        <span class="hljs-keyword">int</span> childs = getChildCount();
        <span class="hljs-keyword">if</span> (childs > <span class="hljs-number">0</span>) {
            View childView = getChildAt(<span class="hljs-number">0</span>);
            <span class="hljs-keyword">if</span> (childView <span class="hljs-keyword">instanceof</span> ListView) {
                mListView = (ListView) childView;
                <span class="hljs-comment">// 設定滾動監聽器給ListView</span>
                mListView.setOnScrollListener(<span class="hljs-keyword">this</span>);
            }
        }
    }



    <span class="hljs-comment">// 設定加載狀态,添加或者移除加載更多圓形進度條</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setLoading</span>(<span class="hljs-keyword">boolean</span> loading) {
        isLoading = loading;
        <span class="hljs-keyword">if</span> (isLoading) {
            mListView.addFooterView(mListViewFooter);
        } <span class="hljs-keyword">else</span> {
            mListView.removeFooterView(mListViewFooter);

        }
    }

    <span class="hljs-comment">//設定監聽器</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOnLoadListener</span>(OnLoadListener loadListener) {
        mOnLoadListener = loadListener;
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onScrollStateChanged</span>(AbsListView view, <span class="hljs-keyword">int</span> scrollState) {

    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onScroll</span>(AbsListView view, <span class="hljs-keyword">int</span> firstVisibleItem,
            <span class="hljs-keyword">int</span> visibleItemCount, <span class="hljs-keyword">int</span> totalItemCount) {

        <span class="hljs-comment">// 判斷是否到了最底部,并且不是在加載資料的狀态</span>
        <span class="hljs-keyword">if</span> (mListView.getLastVisiblePosition() == mListView.getAdapter()
                .getCount() - <span class="hljs-number">1</span> && isLoading == <span class="hljs-keyword">false</span>) {
            <span class="hljs-comment">// 首先設定加載狀态</span>
            setLoading(<span class="hljs-keyword">true</span>);
            <span class="hljs-comment">// 調用加載資料的方法</span>
            mOnLoadListener.onLoad();

        }

    }

    <span class="hljs-comment">// 加載更多的接口</span>
    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">OnLoadListener</span> {</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onLoad</span>();
    }
}      
注釋寫的很清楚,實作滑動監聽,然後初始化listview,寫好加載任務接口與方法。在滑動監聽方法裡面,有幾個參數注意一下: 
<strong>firstVisibleItem</strong> 表示在目前螢幕顯示的第一個listItem在整個listView裡面的位置(下标從0開始) 
<strong>visibleItemCount</strong>表示在現時螢幕可以見到的ListItem(部分顯示的ListItem也算)總數 
<strong>totalItemCount</strong>表示ListView的ListItem總數 
<strong>listView.getLastVisiblePosition()</strong>表示在現時螢幕最後一個ListItem (最後ListItem要完全顯示出來才算)在整個ListView的位置(下标從0開始)
剛開始隻判斷是否滑動到了最底部,沒有對加載狀态進行判斷,導緻程式運作崩潰,在最底部加載資料時會一直加載。後來加上判斷,預設不加載資料,isLoading==false,滑動到最底部加載資料時,設定為true,當加載完成以後,設定為false,加載完畢。      

接下來是第二種加載原理:

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RefreshLayout</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SwipeRefreshLayout</span> {</span>

    <span class="hljs-comment">// listview執行個體</span>
    <span class="hljs-keyword">private</span> ListView mListView;
    <span class="hljs-comment">// 上拉接口監聽器, 到了最底部的上拉加載操作</span>
    <span class="hljs-keyword">private</span> OnLoadListener mOnLoadListener;
    <span class="hljs-comment">// ListView的加載中footer</span>
    <span class="hljs-keyword">private</span> View mListViewFooter;
    <span class="hljs-comment">// 是否在加載中 ( 上拉加載更多 )</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> isLoading = <span class="hljs-keyword">false</span>;

    <span class="hljs-comment">// 按下時的y坐标</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mYDown;
    <span class="hljs-comment">// 擡起時的y坐标</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mLastY;
    <span class="hljs-comment">// 滑動到最下面時的上拉操作</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mTouchSlop;

    <span class="hljs-keyword">public</span> <span class="hljs-title">RefreshLayout</span>(Context context) {
        <span class="hljs-keyword">this</span>(context, <span class="hljs-keyword">null</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-title">RefreshLayout</span>(Context context, AttributeSet attrs) {
        <span class="hljs-keyword">super</span>(context, attrs);

        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mListViewFooter = LayoutInflater.from(context).inflate(
                R.layout.listview_footer, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">false</span>);
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onLayout</span>(<span class="hljs-keyword">boolean</span> changed, <span class="hljs-keyword">int</span> left, <span class="hljs-keyword">int</span> top, <span class="hljs-keyword">int</span> right,
            <span class="hljs-keyword">int</span> bottom) {
        <span class="hljs-keyword">super</span>.onLayout(changed, left, top, right, bottom);
        <span class="hljs-comment">// 初始化ListView對象</span>
        <span class="hljs-keyword">if</span> (mListView == <span class="hljs-keyword">null</span>) {
            getListView();
        }
    }

    <span class="hljs-comment">// 擷取ListView對象</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">getListView</span>() {
        <span class="hljs-keyword">int</span> childs = getChildCount();
        <span class="hljs-keyword">if</span> (childs > <span class="hljs-number">0</span>) {
            View childView = getChildAt(<span class="hljs-number">0</span>);
            <span class="hljs-keyword">if</span> (childView <span class="hljs-keyword">instanceof</span> ListView) {
                mListView = (ListView) childView;
            }
        }
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">dispatchTouchEvent</span>(MotionEvent event) {
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> action = event.getAction();

        <span class="hljs-keyword">switch</span> (action) {
        <span class="hljs-keyword">case</span> MotionEvent.ACTION_DOWN:
            <span class="hljs-comment">// 按下</span>
            mYDown = (<span class="hljs-keyword">int</span>) event.getRawY();
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> MotionEvent.ACTION_MOVE:
            <span class="hljs-comment">// 移動</span>
            mLastY = (<span class="hljs-keyword">int</span>) event.getRawY();
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> MotionEvent.ACTION_UP:
            <span class="hljs-comment">// 擡起</span>
            <span class="hljs-keyword">if</span> ((mYDown - mLastY) >= mTouchSlop && isLoading == <span class="hljs-keyword">false</span>) {
                <span class="hljs-comment">// 設定狀态</span>
                setLoading(<span class="hljs-keyword">true</span>);
                <span class="hljs-comment">//</span>
                mOnLoadListener.onLoad();
            }
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">break</span>;
        }

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.dispatchTouchEvent(event);
    }

    <span class="hljs-comment">// 設定加載狀态</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setLoading</span>(<span class="hljs-keyword">boolean</span> loading) {
        isLoading = loading;
        <span class="hljs-keyword">if</span> (isLoading) {
            mListView.addFooterView(mListViewFooter);
        } <span class="hljs-keyword">else</span> {
            mListView.removeFooterView(mListViewFooter);

        }
    }

    <span class="hljs-comment">// 設定監聽器</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOnLoadListener</span>(OnLoadListener loadListener) {
        mOnLoadListener = loadListener;
    }

    <span class="hljs-comment">// 加載更多的接口</span>
    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">OnLoadListener</span> {</span>
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onLoad</span>();
    }
}      
初始化資料都一樣,不同的是記錄了兩個Y坐标,一個按下,一個擡起,用來判斷滑動到底部時的上拉動作。<strong>getScaledTouchSlop</strong>是一個距離,表示滑動的時候,手的移動要大于這個距離才開始移動控件。如果小于這個距離就不觸發移動控件,如viewpager就是用這個距離來判斷使用者是否翻頁。
然後就是通過事件傳遞機制,拿到view的三個動作: 
<strong>MotionEvent.ACTION_DOWN</strong> 按下View,是所有事件的開始 
<strong>MotionEvent.ACTION_MOVE</strong> 滑動事件 
<strong>MotionEvent.ACTION_UP</strong> 與down對應,表示擡起 
當滑動的距離大于或者等于要求距離并且加載狀态為false時,開始設定狀态,加載資料,原理和上面一樣。      

接下裡就是MainActivity的相關代碼:

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Activity</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">OnRefreshListener</span>,
        <span class="hljs-title">OnLoadListener</span> {</span>

    <span class="hljs-keyword">private</span> RefreshLayout swipeLayout;
    <span class="hljs-keyword">private</span> QQListView listView;
    <span class="hljs-keyword">private</span> MyAdapter adapter;
    <span class="hljs-keyword">private</span> List<Integer> list = <span class="hljs-keyword">new</span> ArrayList<Integer>();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> y = <span class="hljs-number">11</span>;

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) {

        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        setData();
        setListener();
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initView</span>() {
        swipeLayout = (RefreshLayout) findViewById(R.id.swipe_container);
        swipeLayout.setOnRefreshListener(<span class="hljs-keyword">this</span>);
        swipeLayout.setColorScheme(android.R.color.holo_blue_bright,
                android.R.color.holo_green_light,
                android.R.color.holo_orange_light,
                android.R.color.holo_red_light);

    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setData</span>() {
        list = <span class="hljs-keyword">new</span> ArrayList<>();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">3</span>; i < <span class="hljs-number">12</span>; i++) {
            list.add(i);
        }

        listView = (QQListView) findViewById(R.id.list);
        adapter = <span class="hljs-keyword">new</span> MyAdapter(<span class="hljs-keyword">this</span>, list);
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(<span class="hljs-keyword">new</span> OnItemClickListener() {

            <span class="hljs-annotation">@Override</span>
            <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onItemClick</span>(AdapterView<?> arg0, View arg1,
                    <span class="hljs-keyword">int</span> position, <span class="hljs-keyword">long</span> arg3) {

                Toast.makeText(getApplicationContext(),
                        <span class="hljs-string">"這是第"</span> + String.valueOf(position + <span class="hljs-number">1</span>) + <span class="hljs-string">"項"</span>,
                        Toast.LENGTH_SHORT).show();

            }
        });

        listView.setDelButtonClickListener(<span class="hljs-keyword">new</span> DelButtonClickListener() {

            <span class="hljs-annotation">@Override</span>
            <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">clickHappend</span>(<span class="hljs-keyword">int</span> position) {
                list.remove(position);
                refresh();
            }
        });

    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setListener</span>() {
        swipeLayout.setOnRefreshListener(<span class="hljs-keyword">this</span>);
        swipeLayout.setOnLoadListener(<span class="hljs-keyword">this</span>);
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRefresh</span>() {
        swipeLayout.postDelayed(<span class="hljs-keyword">new</span> Runnable() {

            <span class="hljs-annotation">@Override</span>
            <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>() {
                <span class="hljs-comment">// 更新資料</span>
                list.clear();
                y = <span class="hljs-number">12</span>;
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">13</span>; i++) {
                    list.add(i);
                }
                refresh();

                <span class="hljs-comment">// 更新完後調用該方法結束重新整理</span>
                swipeLayout.setRefreshing(<span class="hljs-keyword">false</span>);
            }
        }, <span class="hljs-number">1000</span>);

    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onLoad</span>() {
        swipeLayout.postDelayed(<span class="hljs-keyword">new</span> Runnable() {

            <span class="hljs-annotation">@Override</span>
            <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>() {
                <span class="hljs-comment">// 更新資料</span>
                y++;
                list.add(y);
                refresh();
                <span class="hljs-comment">// 更新完後調用該方法結束重新整理</span>
                swipeLayout.setLoading(<span class="hljs-keyword">false</span>);
            }
        }, <span class="hljs-number">1000</span>);

    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">refresh</span>() {
        adapter.setList(list);
        adapter.notifyDataSetChanged();
    }

}      

實作自帶的下拉重新整理接口方法以及我們自己定義的上拉加載方法,然後在各自的方法裡進行業務操作,我這裡模拟的是簡單數字重新整理。到這裡,SwipeRefreshLayout的下拉重新整理與上拉加載已經完成。最後就是SwipeRefreshLayout的滑動删除。

這裡的滑動删除參考的是鴻洋的這篇部落格,代碼注釋,講解都很詳細:

http://blog.csdn.net/lmj623565791/article/details/22961279

滑動删除item原理就是通過回調拿到item的position,然後執行删除操作,更新擴充卡即可。難點就是解決上拉加載與下拉重新整理操作與listview側滑删除操作沖突的問題

<span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">dispatchTouchEvent</span>(MotionEvent ev) {

        <span class="hljs-comment">//獲得動作類型</span>
        <span class="hljs-keyword">int</span> action = ev.getAction();
        <span class="hljs-keyword">int</span> x = (<span class="hljs-keyword">int</span>) ev.getX();
        <span class="hljs-keyword">int</span> y = (<span class="hljs-keyword">int</span>) ev.getY();
        <span class="hljs-keyword">switch</span> (action) {

        <span class="hljs-keyword">case</span> MotionEvent.ACTION_DOWN:
            xDown = x;
            yDown = y;
            <span class="hljs-javadoc">/**
             * 如果目前popupWindow顯示,則直接隐藏,然後屏蔽ListView的touch事件的下傳
             */</span>
            <span class="hljs-keyword">if</span> (mPopupWindow.isShowing()) {
                dismissPopWindow();
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            }
            <span class="hljs-comment">// 獲得目前手指按下時的item的位置</span>
            mCurrentViewPos = pointToPosition(xDown, yDown);
            View view = getChildAt(mCurrentViewPos - getFirstVisiblePosition());
            mCurrentView = view;
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MotionEvent.ACTION_MOVE:
            xMove = x;
            yMove = y;
            <span class="hljs-keyword">int</span> dx = xMove - xDown;
            <span class="hljs-keyword">int</span> dy = yMove - yDown;
            <span class="hljs-javadoc">/**
             * 判斷是否是從右到左的滑動
             */</span>
            <span class="hljs-keyword">if</span> (xMove < xDown && Math.abs(dx) > touchSlop
                    && Math.abs(dy) < touchSlop) {
                <span class="hljs-comment">// Log.e(TAG, "touchslop = " + touchSlop + " , dx = " + dx +</span>
                <span class="hljs-comment">// " , dy = " + dy);</span>
                isSliding = <span class="hljs-keyword">true</span>;
            }
            <span class="hljs-keyword">break</span>;
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.dispatchTouchEvent(ev);
    }

    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">onTouchEvent</span>(MotionEvent ev) {
        <span class="hljs-keyword">int</span> action = ev.getAction();
        <span class="hljs-javadoc">/**
         * 如果是從右到左的滑動才相應 
         */</span>
        <span class="hljs-keyword">if</span> (isSliding) {
            <span class="hljs-keyword">switch</span> (action) {
            <span class="hljs-keyword">case</span> MotionEvent.ACTION_MOVE:

                <span class="hljs-keyword">int</span>[] location = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">2</span>];
                <span class="hljs-comment">// 獲得目前item的位置x與y </span>
                mCurrentView.getLocationOnScreen(location);
                <span class="hljs-comment">// 設定popupWindow的動畫  </span>
                mPopupWindow
                        .setAnimationStyle(R.style.popwindow_delete_btn_anim_style);
                mPopupWindow.update();
                mPopupWindow.showAtLocation(mCurrentView, Gravity.LEFT
                        | Gravity.TOP, location[<span class="hljs-number">0</span>] + mCurrentView.getWidth(),
                        location[<span class="hljs-number">1</span>] + mCurrentView.getHeight() / <span class="hljs-number">2</span>
                                - mPopupWindowHeight / <span class="hljs-number">2</span>);
                <span class="hljs-comment">// 設定删除按鈕的回調  </span>
                mDelBtn.setOnClickListener(<span class="hljs-keyword">new</span> OnClickListener() {
                    <span class="hljs-annotation">@Override</span>
                    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span>(View v) {
                        <span class="hljs-keyword">if</span> (mListener != <span class="hljs-keyword">null</span>) {
                            mListener.clickHappend(mCurrentViewPos);
                            mPopupWindow.dismiss();
                        }
                    }
                });
                <span class="hljs-comment">// Log.e(TAG, "mPopupWindow.getHeight()=" + mPopupWindowHeight);</span>

                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> MotionEvent.ACTION_UP:
                isSliding = <span class="hljs-keyword">false</span>;

            }
            <span class="hljs-comment">//  相應滑動期間螢幕itemClick事件,避免發生沖突</span>
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        }

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.onTouchEvent(ev);
    }
      

通過dispatchTouchEvent事件傳遞機制,設定目前是否響應使用者滑動,然後在onTouchEvent中判斷是否響應,如果響應則popupWindow以動畫的形式展示出來。當然螢幕上如果存在PopupWindow,則螢幕ListView的滾動與Item的點選,以及從右到左滑動時螢幕Item的click事件都将被屏蔽。

其中關于dispatchTouchEvent,這裡原理說的比較詳細,就不班門弄斧了:

http://blog.csdn.net/yanzi1225627/article/details/22592831

最後截圖的時候比較卡,效果還是不錯的。

轉:http://blog.csdn.net/tyk0910/article/details/50427531