ListView中每個item的左右滑動響應,附原始碼

yangxi_001發表於2014-01-12
要實現的效果:三星手機上左右滑動任一項聯絡人(ListView的Item),即可進行打電話或發簡訊的操作;備忘軟體Any.Do中,滑動ListView中任一項即可標記為已完成。

作為一個初學者,為了實現這一效果,花了很長時間終於才成功,希望大家支援下{:soso_e113:}。

思路:使用了OnItemClickListener, OnGestureListener,前者用於判斷當前選中的項,後者用於判斷是左右滑動還是直接點選選項。當在一項上滑動時, 會執行onFling,直到手指放開時才會執行onItemClick方法,所以先在onFling 中判斷是否為滑動動作,儲存到一個全域性變數中,然後在onItemClick 中根據這個變數的值就能判斷動作。這樣做也避免了滑動時先響應了onItemClick方法造成的干擾。


Layout中只有一個ListView

[mw_shl_code=xhtml,false]
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/listView1"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent" >
</ListView>
[/mw_shl_code]

Java程式碼如下:

[mw_shl_code=java,true]

public class MainActivity extends Activity implements OnItemClickListener, OnGestureListener {

        private GestureDetector gd;
        // 事件狀態
        private final char FLING_CLICK = 0;
        private final char FLING_LEFT = 1;
        private final char FLING_RIGHT = 2;
        private char flingState = FLING_CLICK;
        
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gd = new GestureDetector(this);

        ListView lv = (ListView) findViewById(R.id.listView1);
                lv.setAdapter(new ArrayAdapter<String>(this,
                                android.R.layout.simple_expandable_list_item_1,getData()));
                lv.setOnItemClickListener(this);
    }

        private List<String> getData(){
                List<String> data = new ArrayList<String>();
                data.add("測試資料0");
                data.add("測試資料1");
                data.add("測試資料2");
                data.add("測試資料3");
                data.add("測試資料4");
                data.add("測試資料5");
                data.add("測試資料6");
                data.add("測試資料7");
                data.add("測試資料8");
                data.add("測試資料9");
                data.add("測試資料10");
                data.add("測試資料11");
                data.add("測試資料12");
                return data;
        }
        
    /**
     * 事件處理
     * 其中flingState的值為事件
     * 引數pos為ListView的每一項
     */
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
                // TODO Auto-generated method stub
        Log.v("MY_TAG", "onItemClick: state="+flingState+", pos="+pos);

            switch(flingState) {
            // 處理左滑事件
            case FLING_LEFT:
                        Toast.makeText( this, "Fling Left:"+pos, Toast.LENGTH_SHORT).show();
                        flingState = FLING_CLICK;
                break;
        // 處理右滑事件
            case FLING_RIGHT:
                        Toast.makeText( this, "Fling Right:"+pos, Toast.LENGTH_SHORT).show();
                        flingState = FLING_CLICK;
                break;
        // 處理點選事件
            case FLING_CLICK:
                    switch(pos) {
                    case 0:break;
                    case 1:break;
                    }
                    Toast.makeText( this, "Click Item:"+pos, Toast.LENGTH_SHORT).show();
                    break;
            }
        }
        
        /**
         * 覆寫此方法,以解決ListView滑動被遮蔽問題
         */
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
            this.gd.onTouchEvent(event);
            return super.dispatchTouchEvent(event);
    }

    /**
     * 覆寫此方法,以使用手勢識別
     */
    @Override  
    public boolean onTouchEvent(MotionEvent event) {
        Log.v("MY_TAG", "onTouchEvent");
        return this.gd.onTouchEvent(event);
    }

    /**
     * 引數解釋:
         *                 e1:第1個ACTION_DOWN MotionEvent
         *                 e2:最後一個ACTION_MOVE MotionEvent
         *                 vX:X軸上的移動速度,畫素/秒
         *                 vY:Y軸上的移動速度,畫素/秒
         * 觸發條件 :
         *                 X座標位移大於minX,Y座標位移小於maxY,移動速度大於minV畫素/秒
         * 
     */
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float vX, float vY)
        {
                final int minX = 120 ,maxY = 20, minV = 150;
                int x1 = (int) e1.getX(), x2 = (int) e2.getX();
                int y1 = (int) e1.getY(), y2 = (int) e2.getY();
                
                if( Math.abs(x1-x2)>minX && Math.abs(y1-y2)<maxY && Math.abs(vX)>minV) {
                        if(x1>x2) {
                                Log.v("MY_TAG", "Fling Left");
                                flingState = FLING_LEFT;
                        }
                        else {
                                Log.v("MY_TAG", "Fling Right");
                                flingState = FLING_RIGHT;
                        }
                }
                return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {}

        @Override
        public void onShowPress(MotionEvent e) {}

    @Override
    public boolean onDown(MotionEvent e) {return false;}
        @Override
        public boolean onSingleTapUp(MotionEvent e) {return false;}
        
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float dX,float dY) {
                return false;
        }
}
[/mw_shl_code]


原始碼見附件,測試執行正常。


 GestureListView.zip (708.6 KB, 下載次數: 2276) 

相關文章