本文将使用上篇文章介绍的Scroller类来完成一个比较常见的效果——滑动删除效果。
item.xml:
主界面代码:
代码如下:
simpleSwipeListView:
- package cn.edu.chd.simpleswipelistview;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.ViewConfiguration;
- import android.view.WindowManager;
- import android.widget.AbsListView;
- import android.widget.ListView;
- import android.widget.Scroller;
- /**
- * @author Rowandjj
- *
- *滑动删除示例
- */
- public class SimpleSwipeListView extends ListView
- {
- private static final String TAG = "SimpleSwipeListView";
- private static final boolean DEBUG = true;
- private Scroller mScroller = null;
- private int mTouchSlop;
- /**
- * 屏幕宽度
- */
- private int mScreenWidth;
- private View targetView;
- /**
- * 当前item的位置
- */
- private int position;
- /**
- * 手指按下的位置
- */
- private int downX,downY;
- /**
- * 是否能删除item
- */
- private boolean canRemove = true;
- private boolean isSwipe;
- /**
- * item被删除的回调事件
- */
- private OnItemRemovedListener mListener;
- public interface OnItemRemovedListener
- {
- public void removeItem(int position);
- }
- public void setOnItemRemovedListener(OnItemRemovedListener listener)
- {
- this.mListener = listener;
- }
- public SimpleSwipeListView(Context context)
- {
- this(context, null);
- }
- public SimpleSwipeListView(Context context, AttributeSet attrs)
- {
- this(context, attrs, 0);
- }
- public SimpleSwipeListView(Context context, AttributeSet attrs,
- int defStyleAttr)
- {
- super(context, attrs, defStyleAttr);
- init(context);
- }
- private void init(Context context)
- {
- mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- mScreenWidth = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
- mScroller = new Scroller(context);
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev)
- {
- switch (ev.getAction())
- {
- case MotionEvent.ACTION_DOWN:
- if(!mScroller.isFinished())
- return super.onTouchEvent(ev);
- downX = (int) ev.getX();
- downY = (int) ev.getY();
- //根据坐标得到position
- position = pointToPosition(downX, downY);
- if(position == AbsListView.INVALID_POSITION)
- return super.onTouchEvent(ev);
- //根据position得到代表item的view对象
- targetView = getChildAt(position-getFirstVisiblePosition());
- break;
- case MotionEvent.ACTION_MOVE:
- int x = (int) ev.getX();
- int y = (int) ev.getY();
- if(Math.abs(x-downX)>mTouchSlop&&Math.abs(y-downY)<mTouchSlop)
- {
- int deltaX = downX-x;
- downX = x;
- downY = y;
- targetView.scrollBy(deltaX,0);
- isSwipe = true;
- }
- if(isSwipe)//禁止listView滚动
- return true;
- break;
- case MotionEvent.ACTION_UP:
- scrollByOffset();
- isSwipe = false;
- break;
- }
- return super.onTouchEvent(ev);
- }
- /**
- * 根据偏移量判断是向左还是向右滚动
- */
- private void scrollByOffset()
- {
- int scrollX = targetView.getScrollX();//当前偏移
- if(scrollX > mScreenWidth/3)//应该向左滚
- {
- scrollToLeft(scrollX);
- }else if(scrollX < -mScreenWidth/3)//应该向右滚
- {
- scrollToRight(scrollX);
- }else//滚回原点
- {
- scrollToOrigin(scrollX);
- }
- }
- private void scrollToOrigin(int scrollX)
- {
- mScroller.startScroll(scrollX,0,-scrollX,0,Math.abs(scrollX));
- postInvalidate();
- canRemove = false;
- }
- /**
- * 向右滚动
- */
- private void scrollToRight(int scrollX)
- {
- int deltaX = mScreenWidth+scrollX;
- mScroller.startScroll(scrollX, 0, -deltaX, 0, Math.abs(deltaX));
- invalidate();
- canRemove = true;
- }
- /**
- * 向左滚动
- */
- private void scrollToLeft(int scrollX)
- {
- int deltaX = mScreenWidth - scrollX;
- mScroller.startScroll(scrollX, 0, deltaX, 0, Math.abs(deltaX));
- invalidate();
- canRemove = true;
- }
- @Override
- public void computeScroll()
- {
- if(mScroller != null)
- {
- if(mScroller.computeScrollOffset())
- {
- int currX = mScroller.getCurrX();
- int currY = mScroller.getCurrY();
- targetView.scrollTo(currX,currY);
- postInvalidate();
- if(mScroller.isFinished())
- {
- targetView.scrollTo(0, 0);
- if(canRemove)
- {
- if(mListener == null)
- throw new RuntimeException("you must call setOnRemoveItemListener to set a listener");
- if(DEBUG)
- Log.d(TAG,"position:"+position);
- //删除item
- mListener.removeItem(position);
- canRemove = false;
- }
- }
- }
- }
- }
- }
布局:
activity_main.xml
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#ededed"
- tools:context="cn.edu.chd.simpleswipelistview.MainActivity" >
- <cn.edu.chd.simpleswipelistview.SimpleSwipeListView
- android:id="@+id/lv"
- android:layout_width="match_parent"
- android:layout_marginTop="2dp"
- android:layout_marginBottom="2dp"
- android:layout_height="wrap_content"
- android:listSelector="@android:color/transparent"
- android:cacheColorHint="@android:color/transparent"
- android:divider="@null"
- android:dividerHeight="2dp"
- ></cn.edu.chd.simpleswipelistview.SimpleSwipeListView>
- </RelativeLayout>
- <?xml version="1.0" encoding="utf-8"?>
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingLeft="3dp"
- android:descendantFocusability="beforeDescendants"
- android:paddingRight="3dp" >
- <!--滚动的是下面的内容-->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="55dp"
- android:background="@drawable/card_background_selector"
- android:gravity="center_vertical|left"
- android:descendantFocusability="afterDescendants"
- android:orientation="vertical" >
- <TextView
- android:id="@+id/tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:textColor="@android:color/black"
- android:textSize="18sp" />
- </LinearLayout>
- </FrameLayout>
主界面代码:
- package cn.edu.chd.simpleswipelistview;
- import java.util.ArrayList;
- import java.util.List;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.ArrayAdapter;
- import cn.edu.chd.simpleswipelistview.SimpleSwipeListView.OnItemRemovedListener;
- public class MainActivity extends Activity
- {
- private SimpleSwipeListView mListView = null;
- private ArrayAdapter<String> mAdapter = null;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mListView = (SimpleSwipeListView) findViewById(R.id.lv);
- final List<String> data = new ArrayList<String>();
- for(int i = 0; i < 20; i++)
- {
- data.add("this is text num"+i);
- }
- mAdapter = new ArrayAdapter<>(this,R.layout.item, R.id.tv, data);
- mListView.setAdapter(mAdapter);
- mListView.setOnItemRemovedListener(new OnItemRemovedListener()
- {
- @Override
- public void removeItem(int position)
- {
- //此处并不用调用notifyDataSetChanged,因为remove方法内部调用了
- mAdapter.remove(data.get(position));
- }
- });
- }
- }
效果截屏不方便,大家自己看吧。
相信大家结合上篇文章介绍的Scroller理解代码应该很easy。
重点需要注意以下几点:
1.如何根据坐标找到view对象。(pointToPosition和getChildAt方法的使用)
2.Scroller的使用,特别是scrollTo、scrollBy以及computeScroll方法。
3.需要注意如果希望对某个view进行滚动,应该调用其父view的scrollTo、scrollBy方法。
4.处理滑动冲突,横向滑动删除时应避免listView滚动。
转自:http://blog.youkuaiyun.com/chdjj/article/details/41702961