Android App中ListView仿QQ实现滑动删除效果的要点解析_Android

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

<?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

<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的实现:

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,这里代码很简单不做介绍了。

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
, qq
, listview
滑动删除
listview横向滑动、横向滑动的listview、listview滑动删除item、listview滑动监听、listview滑动删除,以便于您获取更多的相关知识。

时间: 2024-09-23 01:12:57

Android App中ListView仿QQ实现滑动删除效果的要点解析_Android的相关文章

Android App中ListView仿QQ实现滑动删除效果的要点解析

本来准备在ListView的每个Item的布局上设置一个隐藏的Button,当滑动的时候显示.但是因为每次只要存在一个Button,发现每个Item上的Button相互间不好控制.所以决定继承ListView然后结合PopupWindow. 首先是布局文件: delete_btn.xml:这里只需要一个Button <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=

Android App中制作仿MIUI的Tab切换效果的实例分享_Android

1.概述哈,今天给大家带来一个ViewPagerIndicator的制作,相信大家在做tabIndicator的时候,大多数人都用过TabPageIndicator,并且很多知名APP都使用过这个开源的指示器.大家有没有想过如何自己去实现这样的一个指示器,并且代码会有多复杂呢~~~今天,我就带领大家来从无到有的实现这样一个指示器,当然了,不准备一模一样,搞得没有创新似的,再看标题,跟MIUI相关,所以我们准备做一个特性与TabPageIndicator一致的,但是样子和MIUI的Tab一样的~~

Android使用SwipeListView实现类似QQ的滑动删除效果_Android

QQ的滑动删除效果很不错,要实现这种效果,可以使用SwipeListView. 1. 下载com.fortysevendeg.swipelistview这个项目(以前GitHub上有,现在GitHub上没有了,百度了很多次才下载到的),导入Eclipse,右键单击,选择Properties->Android,选中Library下面的IsLibrary. 2. 新建一个项目MySwipeListView,加入SwipeListView这个库. 3. 在主窗体里面放入一个SwipeListView控

Android App中使用ViewPager+Fragment实现滑动切换效果

在android应用中,多屏滑动是一种很常见的风格,没有采用viewpager的代码实现会很长,如果采用ViewPager,代码就会短很多,但是使用ViewPager也有弊端:需要导入android-support-v4.jar.细节无法控制.不过现在情况已经不一样了,android-support-v4中提供了很多实用的功能,以至于现在新建一个android工程默认都会导入这个jar包.那我们就也采用viewpager来做滑动吧.另外一个概念就是Fragment和FragmentActivit

Android App中制作仿MIUI的Tab切换效果的实例分享

1.概述 哈,今天给大家带来一个ViewPagerIndicator的制作,相信大家在做tabIndicator的时候,大多数人都用过TabPageIndicator,并且很多知名APP都使用过这个开源的指示器.大家有没有想过如何自己去实现这样的一个指示器,并且代码会有多复杂呢~~~今天,我就带领大家来从无到有的实现这样一个指示器,当然了,不准备一模一样,搞得没有创新似的,再看标题,跟MIUI相关,所以我们准备做一个特性与TabPageIndicator一致的,但是样子和MIUI的Tab一样的~

图片-仿QQ列表滑动删除和下拉刷新遇到的问题

问题描述 仿QQ列表滑动删除和下拉刷新遇到的问题 向左滑动还会触发listview的onitemclick()事件.手指向先向左再向下滑动,视图即会触发某一项向左滑动,也会触发listview下拉刷新.其中下拉刷新用的是XListview,左滑用的是SlidView,两个结合到一起. 希望能做到: 下拉刷新时只下拉刷新,不触发滑动删除,和onitemclick 滑动删除时只滑动删除,不触发下拉刷新,和onitemclick onitemclick只是在滑动菜单未弹出时触发. 希望能提供个思路,如

Android仿QQ列表滑动删除操作_Android

这篇山寨一个新版QQ的列表滑动删除,上篇有说到QQ的滑动删除,推测原理就是ListView本身每个item存在一个Button,只不过普通的状态下隐藏掉了,检测到向左的滑动事件的时候弹出隐藏的Button,不过再切换Button状态的时候会给Button一个出现和隐藏的动画.下面实现这个ListView.  首先有个难点就是通过ListView获取它某个item的View,对于ViewGroup,可以直接调用getChildAt()方法获取对应的子view,但是在ListView直接使用getC

Android仿QQ列表滑动删除操作

这篇山寨一个新版QQ的列表滑动删除,上篇有说到QQ的滑动删除,推测原理就是ListView本身每个item存在一个Button,只不过普通的状态下隐藏掉了,检测到向左的滑动事件的时候弹出隐藏的Button,不过再切换Button状态的时候会给Button一个出现和隐藏的动画.下面实现这个ListView. 首先有个难点就是通过ListView获取它某个item的View,对于ViewGroup,可以直接调用getChildAt()方法获取对应的子view,但是在ListView直接使用getCh

Android仿腾讯QQ实现滑动删除 附源码下载_Android

看了很多大神们的文章,感觉受益良多,也非常欣赏大家的分享态度,所以决定开始写Blog,给大家分享自己的心得. 先看看效果图: 本来准备在ListView的每个Item的布局上设置一个隐藏的Button,当滑动的时候显示.但是因为每次只要存在一个Button,发现每个Item上的Button相互间不好控制.所以决定继承ListView然后结合PopupWindow. 首先是布局文件: delete_btn.xml:这里只需要一个Button <?xml version="1.0"