Scroller应用:ListView滑动删除

来源:互联网 发布:装修设计3d效果图 知乎 编辑:程序博客网 时间:2024/05/10 22:48

1、设计思路

在Scroller的应用--滑屏实现中使用Scroller实现滑屏效果,这里使用Scroller与ListView实现类似QQ滑动,然后点击删除功能,设计思路是Item使用Scroller实现滑动,ListView根据触摸判断是横向滑动还是竖直滑动,关于点击事件处理思路:对于View的onClick事件跟平常一样,里面针对OnItemClick做了处理,判断触摸距离来判断,如果小于5的话,在Item的onTouchEvent方法中的MotionEvent.ACTION_UP里面返回false,这样ListView里面的dispatchTouchEvent的super.dispatchTouchEvent(event)就会返回false,根据x,y获取当前position以及点击的view,调用super.performItemClick(view, position, view.getId());来告诉ListView出发onItemClick事件。

2、Item的代码

package com.jwzhangjie.scrollview;    import android.content.Context;  import android.util.AttributeSet;  import android.util.Log;  import android.view.MotionEvent;  import android.view.View;  import android.widget.LinearLayout;  import android.widget.Scroller;    public class ListItemDelete extends LinearLayout {        private Scroller mScroller;// 滑动控制      private float mLastMotionX;// 记住上次触摸屏的位置      private int deltaX;      private int back_width;      private float downX;        public ListItemDelete(Context context) {          this(context, null);      }        public ListItemDelete(Context context, AttributeSet attrs) {          super(context, attrs);          init(context);      }        private void init(Context context) {          mScroller = new Scroller(context);      }        @Override      public void computeScroll() {          if (mScroller.computeScrollOffset()) {// 会更新Scroller中的当前x,y位置              scrollTo(mScroller.getCurrX(), mScroller.getCurrY());              postInvalidate();          }      }        @Override      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {          super.onMeasure(widthMeasureSpec, heightMeasureSpec);          int count = getChildCount();          for (int i = 0; i < count; i++) {              measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);              if (i == 1) {                  back_width = getChildAt(i).getMeasuredWidth();              }          }        }        @Override      public boolean onTouchEvent(MotionEvent event) {          int action = event.getAction();          float x = event.getX();          switch (action) {          case MotionEvent.ACTION_DOWN:              Log.e("test", "item  ACTION_DOWN");              mLastMotionX = x;              downX = x;              break;          case MotionEvent.ACTION_MOVE:              Log.e("test", back_width + "  item  ACTION_MOVE  " + getScrollX());              deltaX = (int) (mLastMotionX - x);              mLastMotionX = x;              int scrollx = getScrollX() + deltaX;              if (scrollx > 0 && scrollx < back_width) {                  scrollBy(deltaX, 0);              } else if (scrollx > back_width) {                  scrollTo(back_width, 0);              } else if (scrollx < 0) {                  scrollTo(0, 0);              }              break;          case MotionEvent.ACTION_UP:              Log.e("test", "item  ACTION_UP");              int scroll = getScrollX();              if (scroll > back_width / 2) {                  scrollTo(back_width, 0);              } else {                  scrollTo(0, 0);              }              if (Math.abs(x - downX) < 5) {// 这里根据点击距离来判断是否是itemClick                  return false;              }              break;          case MotionEvent.ACTION_CANCEL:              scrollTo(0, 0);              break;          }          return true;      }        @Override      protected void onLayout(boolean changed, int l, int t, int r, int b) {          int margeLeft = 0;          int size = getChildCount();          for (int i = 0; i < size; i++) {              View view = getChildAt(i);              if (view.getVisibility() != View.GONE) {                  int childWidth = view.getMeasuredWidth();                  // 将内部子孩子横排排列                  view.layout(margeLeft, 0, margeLeft + childWidth,                          view.getMeasuredHeight());                  margeLeft += childWidth;              }          }      }  }  

3、ListView的代码

package com.jwzhangjie.scrollview;    import android.content.Context;  import android.util.AttributeSet;  import android.util.Log;  import android.view.MotionEvent;  import android.view.View;  import android.widget.ListView;    public class ScrollListviewDelete extends ListView {        private float minDis = 10;      private float mLastMotionX;// 记住上次X触摸屏的位置      private float mLastMotionY;// 记住上次Y触摸屏的位置      private boolean isLock = false;        public ScrollListviewDelete(Context context, AttributeSet attrs) {          super(context, attrs);      }        /**      * 如果一个ViewGroup的onInterceptTouchEvent()方法返回true,说明Touch事件被截获,      * 子View不再接收到Touch事件,而是转向本ViewGroup的      * onTouchEvent()方法处理。从Down开始,之后的Move,Up都会直接在onTouchEvent()方法中处理。      * 先前还在处理touch event的child view将会接收到一个 ACTION_CANCEL。      * 如果onInterceptTouchEvent()返回false,则事件会交给child view处理。      */      @Override      public boolean onInterceptTouchEvent(MotionEvent ev) {          if (!isIntercept(ev)) {              return false;          }          return super.onInterceptTouchEvent(ev);      }        @Override      public boolean dispatchTouchEvent(MotionEvent event) {          boolean dte = super.dispatchTouchEvent(event);          if (MotionEvent.ACTION_UP == event.getAction() && !dte) {//onItemClick              int position = pointToPosition((int)event.getX(), (int)event.getY());              View view = getChildAt(position);              super.performItemClick(view, position, view.getId());          }          return dte;      }        @Override      // 处理点击事件,如果是手势的事件则不作点击事件 普通View      public boolean performClick() {          return super.performClick();      }        @Override      // 处理点击事件,如果是手势的事件则不作点击事件 ListView      public boolean performItemClick(View view, int position, long id) {          return super.performItemClick(view, position, id);      }        /**      * 检测是ListView滑动还是item滑动 isLock 一旦判读是item滑动,则在up之前都是返回false      */      private boolean isIntercept(MotionEvent ev) {          float x = ev.getX();          float y = ev.getY();          int action = ev.getAction();          switch (action) {          case MotionEvent.ACTION_DOWN:              Log.e("test", "isIntercept  ACTION_DOWN  "+isLock);              mLastMotionX = x;              mLastMotionY = y;              break;          case MotionEvent.ACTION_MOVE:              Log.e("test", "isIntercept  ACTION_MOVE  "+isLock);              if (!isLock) {                  float deltaX = Math.abs(mLastMotionX - x);                  float deltay = Math.abs(mLastMotionY - y);                  mLastMotionX = x;                  mLastMotionY = y;                  if (deltaX > deltay && deltaX > minDis) {                      isLock = true;                      return false;                  }              } else {                  return false;              }              break;          case MotionEvent.ACTION_UP:              Log.e("test", "isIntercept  ACTION_UP  "+isLock);              isLock = false;              break;          case MotionEvent.ACTION_CANCEL:              Log.e("test", "isIntercept  ACTION_CANCEL  "+isLock);              isLock = false;              break;          }          return true;      }    }  


4、Activity代码

package com.jwzhangjie.scrollview;    import java.util.ArrayList;  import java.util.List;    import android.os.Bundle;  import android.support.v4.app.FragmentActivity;  import android.view.LayoutInflater;  import android.view.View;  import android.view.View.OnClickListener;  import android.view.ViewGroup;  import android.widget.AdapterView;  import android.widget.AdapterView.OnItemClickListener;  import android.widget.BaseAdapter;  import android.widget.Button;  import android.widget.TextView;  import android.widget.Toast;    public class ScrollerDeleteActivity extends FragmentActivity implements          OnItemClickListener {        private Toast mToast;      private ScrollListviewDelete listviewDelete;      private DeleteAdapter adapter;      private String[] datas = { "第一项", "第二项", "第三项", "第四项", "第五项", "第六项", "第七项",              "第八项", "第九项", "第十项" };      private List<String> listDatas = new ArrayList<String>();        @Override      protected void onCreate(Bundle bundle) {          super.onCreate(bundle);          setContentView(R.layout.activity_scroller_delete);          int len = datas.length;          for (int i = 0; i < len; i++) {              listDatas.add(datas[i]);          }          listviewDelete = (ScrollListviewDelete) findViewById(android.R.id.list);          adapter = new DeleteAdapter();          listviewDelete.setAdapter(adapter);          listviewDelete.setOnItemClickListener(this);      }        class DeleteAdapter extends BaseAdapter {            @Override          public int getCount() {              return listDatas.size();          }            @Override          public Object getItem(int position) {              return listDatas.get(position);          }            @Override          public long getItemId(int position) {              return position;          }            @Override          public View getView(final int position, View convertView,                  ViewGroup parent) {              ViewHolder holder;              if (convertView == null) {                  holder = new ViewHolder();                  convertView = LayoutInflater.from(getApplicationContext())                          .inflate(R.layout.item_delete, null);                  holder.itemData = (TextView) convertView                          .findViewById(R.id.itemData);                  holder.btnDelete = (Button) convertView                          .findViewById(R.id.btnDelete);                  holder.btnNao = (Button) convertView.findViewById(R.id.btnNao);                  convertView.setTag(holder);              } else {                  holder = (ViewHolder) convertView.getTag();              }              holder.btnDelete.setOnClickListener(new OnClickListener() {                  @Override                  public void onClick(View v) {                      showInfo("点击删除了");                  }              });              holder.itemData.setOnClickListener(new OnClickListener() {                    @Override                  public void onClick(View v) {                      showInfo("点击了数据: " + listDatas.get(position));                  }              });              holder.btnNao.setOnClickListener(new OnClickListener() {                  @Override                  public void onClick(View v) {                      showInfo("点击了闹铃");                  }              });              holder.itemData.setText(listDatas.get(position));              return convertView;          }            class ViewHolder {              TextView itemData;              Button btnDelete;              Button btnNao;          }      }        @Override      public void onItemClick(AdapterView<?> parent, View view, int position,              long id) {          showInfo("onItemClick : " + position);      }        public void showInfo(String text) {          if (mToast == null) {              mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);          } else {              mToast.setText(text);              mToast.setDuration(Toast.LENGTH_SHORT);          }          mToast.show();      }    }  

5、XML代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical" >        <com.jwzhangjie.scrollview.ScrollListviewDelete          android:id="@android:id/list"          android:layout_width="match_parent"          android:layout_height="match_parent" />    </LinearLayout>

<com.jwzhangjie.scrollview.ListItemDelete xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:orientation="horizontal" >        <LinearLayout          android:id="@+id/front"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:background="@drawable/bg_item_list_8"          android:gravity="center"          android:orientation="horizontal" >            <TextView              android:id="@+id/itemData"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:text="测试数据" />      </LinearLayout>        <LinearLayout          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:gravity="center"          android:orientation="horizontal" >            <Button              android:id="@+id/btnNao"              android:layout_width="wrap_content"              android:layout_height="match_parent"              android:background="@drawable/bg_item_list_4"              android:text="闹铃" />            <Button              android:id="@+id/btnDelete"              android:layout_width="wrap_content"              android:layout_height="match_parent"              android:background="@drawable/bg_item_list_5"              android:text="删除" />      </LinearLayout>    </com.jwzhangjie.scrollview.ListItemDelete>

6、界面效果


不保证上面的代码是最新的,更新代码地址:https://github.com/jwzhangjie/-ScrollerDelete


V1.0版本:解决提供修改数据多时,item滑动底部数据重复,解决方案:判断是否有滑动的item,如果有则复位

地址:https://github.com/jwzhangjie/-ScrollerDelete  里面有编译好的apk




0 0
原创粉丝点击