«

ListView滑动删除 ,仿腾讯QQ

时间:2024-3-2 21:25     作者:韩俊     分类: Android


在CSDN上开了很多大神们的文章,感觉受益良多,也非常欣赏大家的分享态度,所以决定开始写Blog,给大家分享自己的心得。

本来准备在ListView的每个Item的布局上设置一个隐藏的Button,当滑动的时候显示。但是因为每次只要存在一个Button,发现每个Item上的Button相互间不好控制。所以决定继承ListView然后结合PopupWindow。

首先是布局文件:

delete_btn.xml:这里只需要一个Button



[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:id="@+id/id_item_btn"
android:layout_width="60dp"
android:singleLine="true"
android:layout_height="wrap_content"
android:text="删除"
android:background="@drawable/d_delete_btn"
android:textColor="#ffffff"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
/>
</LinearLayout>
主布局文件:activity_main.xml,ListView的每个Item的样式直接使用了系统的android.R.layout.simple_list_item_1


[html] view
plaincopy
<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" >
<com.example.listviewitemslidedeletebtnshow.QQListView
android:id="@+id/id_listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</com.example.listviewitemslidedeletebtnshow.QQListView>
</RelativeLayout>
接下来看看QQListView的实现:


[java] view
plaincopy
package com.example.listviewitemslidedeletebtnshow;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
public class QQListView extends ListView
{
private static final String TAG = "QQlistView";
// private static final int VELOCITY_SANP = 200;
// private VelocityTracker mVelocityTracker;
/**

  • 用户滑动的最小距离
    */
    private int touchSlop;
    /**
  • 是否响应滑动
    */
    private boolean isSliding;
    /**
  • 手指按下时的x坐标
    */
    private int xDown;
    /**
  • 手指按下时的y坐标
    */
    private int yDown;
    /**
  • 手指移动时的x坐标
    */
    private int xMove;
    /**
  • 手指移动时的y坐标
    */
    private int yMove;
    private LayoutInflater mInflater;
    private PopupWindow mPopupWindow;
    private int mPopupWindowHeight;
    private int mPopupWindowWidth;
    private Button mDelBtn;
    /**
  • 为删除按钮提供一个回调接口
    */
    private DelButtonClickListener mListener;
    /**
  • 当前手指触摸的View
    */
    private View mCurrentView;
    /**
  • 当前手指触摸的位置
    */
    private int mCurrentViewPos;
    /**
  • 必要的一些初始化
  • @param context
  • @param attrs
    */
    public QQListView(Context context, AttributeSet attrs)
    {
    super(context, attrs);
    mInflater = LayoutInflater.from(context);
    touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    View view = mInflater.inflate(R.layout.delete_btn, null);
    mDelBtn = (Button) view.findViewById(R.id.id_item_btn);
    mPopupWindow = new PopupWindow(view, LinearLayout.LayoutParams.WRAP_CONTENT,
    LinearLayout.LayoutParams.WRAP_CONTENT);
    /**
    • 先调用下measure,否则拿不到宽和高
      */
      mPopupWindow.getContentView().measure(0, 0);
      mPopupWindowHeight = mPopupWindow.getContentView().getMeasuredHeight();
      mPopupWindowWidth = mPopupWindow.getContentView().getMeasuredWidth();
      }
      @Override
      public boolean dispatchTouchEvent(MotionEvent ev)
      {
      int action = ev.getAction();
      int x = (int) ev.getX();
      int y = (int) ev.getY();
      switch (action)
      {
      case MotionEvent.ACTION_DOWN:
      xDown = x;
      yDown = y;
      /**
      • 如果当前popupWindow显示,则直接隐藏,然后屏蔽ListView的touch事件的下传
        */
        if (mPopupWindow.isShowing())
        {
        dismissPopWindow();
        return false;
        }
        // 获得当前手指按下时的item的位置
        mCurrentViewPos = pointToPosition(xDown, yDown);
        // 获得当前手指按下时的item
        View view = getChildAt(mCurrentViewPos - getFirstVisiblePosition());
        mCurrentView = view;
        break;
        case MotionEvent.ACTION_MOVE:
        xMove = x;
        yMove = y;
        int dx = xMove - xDown;
        int dy = yMove - yDown;
        /**
      • 判断是否是从右到左的滑动
        */
        if (xMove < xDown && Math.abs(dx) > touchSlop && Math.abs(dy) < touchSlop)
        {
        // Log.e(TAG, "touchslop = " + touchSlop + " , dx = " + dx +
        // " , dy = " + dy);
        isSliding = true;
        }
        break;
        }
        return super.dispatchTouchEvent(ev);
        }
        @Override
        public boolean onTouchEvent(MotionEvent ev)
        {
        int action = ev.getAction();
        /**
    • 如果是从右到左的滑动才相应
      */
      if (isSliding)
      {
      switch (action)
      {
      case MotionEvent.ACTION_MOVE:
      int[] location = new int[2];
      // 获得当前item的位置x与y
      mCurrentView.getLocationOnScreen(location);
      // 设置popupWindow的动画
      mPopupWindow.setAnimationStyle(R.style.popwindow_delete_btn_anim_style);
      mPopupWindow.update();
      mPopupWindow.showAtLocation(mCurrentView, Gravity.LEFT | Gravity.TOP,
      location[0] + mCurrentView.getWidth(), location[1] + mCurrentView.getHeight() / 2
      • mPopupWindowHeight / 2);
        // 设置删除按钮的回调
        mDelBtn.setOnClickListener(new OnClickListener()
        {
        @Override
        public void onClick(View v)
        {
        if (mListener != null)
        {
        mListener.clickHappend(mCurrentViewPos);
        mPopupWindow.dismiss();
        }
        }
        });
        // Log.e(TAG, "mPopupWindow.getHeight()=" + mPopupWindowHeight);
        break;
        case MotionEvent.ACTION_UP:
        isSliding = false;
        }
        // 相应滑动期间屏幕itemClick事件,避免发生冲突
        return true;
        }
        return super.onTouchEvent(ev);
        }
        /**
  • 隐藏popupWindow
    */
    private void dismissPopWindow()
    {
    if (mPopupWindow != null && mPopupWindow.isShowing())
    {
    mPopupWindow.dismiss();
    }
    }
    public void setDelButtonClickListener(DelButtonClickListener listener)
    {
    mListener = listener;
    }
    interface DelButtonClickListener
    {
    public void clickHappend(int position);
    }
    }
    代码注释写得很详细,简单说一下,在dispatchTouchEvent中设置当前是否响应用户滑动,然后在onTouchEvent中判断是否响应,如果响应则popupWindow以动画的形式展示出来。当然屏幕上如果存在PopupWindow则屏幕ListView的滚动与Item的点击,以及从右到左滑动时屏幕Item的click事件。

    接下来是MainActivity.java,这里代码很简单不做介绍了。


    [java] view
    plaincopy
    package com.example.listviewitemslidedeletebtnshow;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.ArrayAdapter;
    import android.widget.Toast;
    import com.example.listviewitemslidedeletebtnshow.QQListView.DelButtonClickListener;
    public class MainActivity extends Activity
    {
    private QQListView mListView;
    private ArrayAdapter<String> mAdapter;
    private List<String> mDatas;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mListView = (QQListView) findViewById(R.id.id_listview);
    // 不要直接Arrays.asList
    mDatas = new ArrayList<String>(Arrays.asList("HelloWorld", "Welcome", "Java", "Android", "Servlet", "Struts",
    "Hibernate", "Spring", "HTML5", "Javascript", "Lucene"));
    mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDatas);
    mListView.setAdapter(mAdapter);
    mListView.setDelButtonClickListener(new DelButtonClickListener()
    {
    @Override
    public void clickHappend(final int position)
    {
    Toast.makeText(MainActivity.this, position + " : " + mAdapter.getItem(position), 1).show();
    mAdapter.remove(mAdapter.getItem(position));
    }
    });
    mListView.setOnItemClickListener(new OnItemClickListener()
    {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    {
    Toast.makeText(MainActivity.this, position + " : " + mAdapter.getItem(position), 1).show();
    }
    });
    }
    }
    效果图如下:楼主使用asm.jar以及gifcamera截的gif,由于button的动画很短感觉截图效果很卡不流畅,大家有什么好的截图,还望推荐。有兴趣的还是下载源码看看效果i。


标签: android

热门推荐