ListView 滑动删除效果

ListView的条目滑动删除效果。

 

原理:

         1、利用onTouchListener方法获取手指触摸的点的坐标。

         2、利用ListView的pointToPosition方法获取当前获得焦点的条目在ListView中的position

         3、利用Animation播放滑动的动画。

         4、利用AnimationListener可以监听到动画播放开始,重复和解说事件。我们要在结束时删除条目。

 

布局和动画都很简单,只有删除条目和获取播放动画的条目两处有些容易出错,贴出代码后会说到这两个地方的小问题。

 

下面是布局代码:

         界面布局activity_main.xml

        

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
   <ListView
        android:id="@+id/lv"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
   </ListView>
 
</LinearLayout>


  

   ListView的条目item.xml

        

    

     <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
 
   <TextView
        android:id="@+id/tv"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:textColor="#FF0000"
        android:textSize="40dp" />
 
</LinearLayout>

 

动画 delete.xml

 

<?xml version="1.0"encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 
   <translate
        android:duration="1000"
        android:fromXDelta="0%"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toXDelta="100%"/>
 
</set>


 

界面代码和适配器代码在同一个java文件中  MainActivity.java

        

package com.example.listviewdemo;
 
import java.util.ArrayList;
import java.util.List;
 
import com.example.listviewdemo.R;
 
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.app.Activity;
import android.content.Context;
 
public classMainActivity extends Activity implements OnTouchListener,
      AnimationListener{
 
   public List<String> list = newArrayList<String>();
   private ListView lv;
   private StringAdapter adapter;
   private int pointX, pointY, endX;
   private int position;
 
   @Override
   public void onCreate(BundlesavedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      lv = (ListView)findViewById(R.id.lv);
      adapter = new StringAdapter(this);
      lv.setAdapter(adapter);
      lv.setOnTouchListener(this);
   }
 
   @SuppressWarnings("static-access")
   @Override
   public boolean onTouch(View v,MotionEvent event) {
      switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
         // 手指按下,计算焦点位于ListView的那个条目
         pointX = (int) event.getX();
         pointY = (int) event.getY();
         // 备注1
         position = lv.pointToPosition(pointX, pointY);
         break;
      case MotionEvent.ACTION_MOVE:
 
         break;
      case MotionEvent.ACTION_UP:
         endX = (int) event.getX();
         if (endX - pointX > 300) {
            // 获取到ListView第一个可见条目的position
            int firstVisiblePosition = lv.getFirstVisiblePosition();
            // 删除条目的动画
            AnimationUtilsutils = newAnimationUtils();
            Animationanimation = utils.loadAnimation(MainActivity.this,
                   R.anim.delete);
            animation.setAnimationListener(this);
            // --------------备注2
            Viewview = lv.getChildAt(position -firstVisiblePosition);
            try {
                view.startAnimation(animation);
            }catch(NullPointerException e) {
                Log.i("MainActivity","报个空指针异常!");// --------------备注3
            }
 
         }
         break;
 
      default:
         break;
      }
      return false;
   }
 
   @Override
   public voidonAnimationEnd(Animation animation) {
      // 使用List集合的remove方法移除掉第position个元素,然后通知适配器重新适配数据。
      try {
         list.remove(position);
      }catch(ArrayIndexOutOfBoundsException e) {
         Log.i("MainActivity","报个数组越界异常!    position =" + position);// --------------备注4
      }
 
      adapter.notifyDataSetChanged();
   }
 
   @Override
   public voidonAnimationRepeat(Animation animation) {
   }
 
   @Override
   public voidonAnimationStart(Animation animation) {
   }
 
   public class StringAdapter extends BaseAdapter {
 
      private LayoutInflater inflater;
      private String content = "";
 
      public StringAdapter(Contextcontext) {
         inflater = LayoutInflater.from(context);
         for (int i = 0; i < 20; i++){
            content = "item "+ i;
            list.add(content);
         }
      }
 
      @Override
      public int getCount() {
 
         return list.size();
      }
 
      @Override
      public Object getItem(int position) {
 
         return list.get(position);
      }
 
      @Override
      public long getItemId(int position) {
 
         return position;
      }
 
      @Override
      public View getView(int position, ViewconvertView, ViewGroup parent) {
         if (convertView == null) {
            convertView= inflater.inflate(R.layout.item, null);
         }
         TextViewtv = (TextView) convertView.findViewById(R.id.tv);
         tv.setText(getItem(position)+ "");
         return convertView;
      }
 
   }
 
}
 


关键代码解释:

 

备注1:根据手指触摸点的坐标计算ListView的那个条目获得了焦点。这里得到的position是相对于整个ListView而说。这里很重要。

 

备注2:getChildAt(int position)方法中的形参position是以当前ListView的可视区域确定的。与 备注1中的position完全没有关系。所以这里使用的不能是position,而应该是position减去第一个可见条目的position。

 

备注3 和备注 4:我自己捕获的异常。如果删除动作很快很频繁而且ListView条目很多时,这里会抛出两个异常。

 

 

 点击这里下载免积分Demo

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值