类似QQ消息左滑删除的Demo

最近在网上学到一篇类似QQ消息左滑删除的demo,完善了下代码,感觉还不错,特此分享一波:

CustomSwipeListView.java 是个继承自ListView的类,里面调用了自定义View 类SwipeItemView.java的一个收缩的方法。其实QQ消息删除这个动画可以有很多种方法实现,这里我们介绍的方法是:常规ListView的每个Item展示方式不变,只是在Adapter类里面去绑定该显示的数据和删除等字样。具体详见如下:

自定义的ListView:

package com.ryg.slideview;

import android.annotation.SuppressLint;
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 CustomSwipeListView extends ListView {

private static final String TAG = "ListViewCompat";

public static SwipeItemView mFocusedItemView;

private int mPosition;

public CustomSwipeListView(Context context) {
super(context);
}

public CustomSwipeListView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public CustomSwipeListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

public void shrinkListItem(int position) {
View item = getChildAt(position);

if (item != null) {
try {
((SwipeItemView) item).shrink();
}
catch (ClassCastException e) {
e.printStackTrace();
}
}
}

@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
int x = (int) event.getX();
int y = (int) event.getY();
// 我们想知道当前点击了哪一行
int position = pointToPosition(x, y);
Log.e(TAG, "postion=" + position);
if (position != INVALID_POSITION) {
int firstPos = getFirstVisiblePosition();
mFocusedItemView = (SwipeItemView) getChildAt(position - firstPos);
}
}
default:
break;
}

if (mFocusedItemView != null) {
mFocusedItemView.onRequireTouchEvent(event);

}

return super.onTouchEvent(event);
}

}

自定义的布局:

package com.ryg.slideview;

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.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;

public class SwipeItemView extends LinearLayout {

private static final String TAG = "SlideView";

private Context mContext;

private LinearLayout mViewContent;

private RelativeLayout mHolder;

private Scroller mScroller;

private OnSlideListener mOnSlideListener;

private int mHolderWidth;

private int mLastX = 0;

private int mLastY = 0;

private static final int TAN = 2;

private boolean isHorizontalMove = true;// 判断是否横滑

public interface OnSlideListener {
public static final int SLIDE_STATUS_OFF = 0;

public static final int SLIDE_STATUS_START_SCROLL = 1;

public static final int SLIDE_STATUS_ON = 2;

/**
* @param view
* current SlideView
* @param status
* SLIDE_STATUS_ON or SLIDE_STATUS_OFF
*/
public void onSlide(View view, int status);
}

public SwipeItemView(Context context) {
super(context);
initView();
}

public SwipeItemView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}

private void initView() {
mContext = getContext();
// 初始化弹性滑动对象
mScroller = new Scroller(mContext);
// 设置其方向为横向
setOrientation(LinearLayout.HORIZONTAL);
// 将slide_view_merge加载进来
View.inflate(mContext, R.layout.slide_view_merge, this);
mViewContent = (LinearLayout) findViewById(R.id.view_content);

mHolder = (RelativeLayout) findViewById(R.id.holder);
mHolder.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
mHolderWidth = mHolder.getMeasuredWidth();
mHolder.setLayoutParams(new LinearLayout.LayoutParams(mHolderWidth, LayoutParams.MATCH_PARENT));
}

public void setButtonText(CharSequence text) {
((TextView) findViewById(R.id.delete)).setText(text);
}

public void setContentView(View view) {
mViewContent.addView(view);
}

public void setOnSlideListener(OnSlideListener onSlideListener) {
mOnSlideListener = onSlideListener;
}

public void shrink() {
if (getScrollX() != 0) {
this.smoothScrollTo(0, 0);
}
}

public void onRequireTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
int scrollX = getScrollX();
Log.d(TAG, "x=" + x + " y=" + y);

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
isHorizontalMove = true;// 按下默认为true,当移上下则为false
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
if (mOnSlideListener != null) {
mOnSlideListener.onSlide(this, OnSlideListener.SLIDE_STATUS_START_SCROLL);
}
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
// 上下移动
if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) {
isHorizontalMove = false;
break;
}

if (!isHorizontalMove)
break;
int newScrollX = scrollX - deltaX;

if (deltaX != 0) {
if (newScrollX < 0) {
newScrollX = 0;
}
else if (newScrollX > mHolderWidth) {
newScrollX = mHolderWidth;
}
this.scrollTo(newScrollX, 0);
}
break;
}
case MotionEvent.ACTION_UP: {
int newScrollX = 0;
if (scrollX - mHolderWidth * 0.15 > 0) {
newScrollX = mHolderWidth;
}
this.smoothScrollTo(newScrollX, 0);
if (mOnSlideListener != null) {
mOnSlideListener.onSlide(this, newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF : OnSlideListener.SLIDE_STATUS_ON);
}
break;
}
default:
break;
}

mLastX = x;
mLastY = y;
}

private void smoothScrollTo(int destX, int destY) {
int scrollX = getScrollX();
int delta = destX - scrollX;
mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 2);
invalidate();
}

@Override
public void computeScroll() {//由父视图调用,用于通知子视图在必要时更新 mScrollX 和 mScrollY 的值。 该操作主要用于子视图使用 Scroller 进行动画滚动时
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}

public boolean getisHorizontalMove() {
return isHorizontalMove;
}

}

Adapter:

package com.ryg.slideview;

import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.ryg.slideview.SwipeItemView.OnSlideListener;

public class HistoryListViewAdapter extends BaseAdapter {

private LayoutInflater mInflater;

private List<HistoryListItemObject> mMessageItems;

private Context context;

private SwipeItemView mLastSlideViewWithStatusOn;

public HistoryListViewAdapter(Context context, List<HistoryListItemObject> mMessageItems) {
mInflater = LayoutInflater.from(context);
this.mMessageItems = mMessageItems;
this.context = context;
}

@Override
public int getCount() {
return mMessageItems.size();
}

@Override
public Object getItem(int position) {
return mMessageItems.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@SuppressLint("InflateParams")
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
SwipeItemView slideView = (SwipeItemView) convertView;
if (slideView == null) {
View itemView = mInflater.inflate(R.layout.history_listview_items, null);
slideView = new SwipeItemView(context);
slideView.setContentView(itemView);
holder = new ViewHolder(slideView);
slideView.setOnSlideListener(new OnSlideListener() {
@Override
public void onSlide(View view, int status) {
// TODO Auto-generated method stub
if (mLastSlideViewWithStatusOn != null && mLastSlideViewWithStatusOn != view) {
mLastSlideViewWithStatusOn.shrink();
}
if (status == SLIDE_STATUS_ON) {
mLastSlideViewWithStatusOn = (SwipeItemView) view;
}
}
});
slideView.setTag(holder);
}
else {
holder = (ViewHolder) slideView.getTag();
}
HistoryListItemObject item = mMessageItems.get(position);
if (CustomSwipeListView.mFocusedItemView != null) {
CustomSwipeListView.mFocusedItemView.shrink();
}

holder.icon.setImageResource(item.getIconRes());
holder.title.setText(item.getTitle());
holder.msg.setText(item.getMsg());
holder.deleteHolder.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
mMessageItems.remove(position);
Toast.makeText(context, String.valueOf(position), Toast.LENGTH_SHORT).show();
notifyDataSetChanged();
}
});

return slideView;
}

private static class ViewHolder {
public ImageView icon;

public TextView title;

public TextView msg;

public ViewGroup deleteHolder;

ViewHolder(View view) {
icon = (ImageView) view.findViewById(R.id.icon);
title = (TextView) view.findViewById(R.id.title);
msg = (TextView) view.findViewById(R.id.msg);
deleteHolder = (ViewGroup) view.findViewById(R.id.holder);
}
}
}

布局:

没有删除布局的Item布局:

<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="wrap_content"
android:descendantFocusability="blocksDescendants"
android:gravity="center_vertical"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp" >

<ImageView
android:id="@+id/icon"
android:layout_width="160dp"
android:layout_height="50dp"
android:layout_marginRight="5dp"
android:scaleType="fitStart"
android:src="@drawable/wechat_icon" />

<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/icon"
android:gravity="right"
android:hint="title"
android:textColor="@color/black"
android:textSize="15sp" />

<TextView
android:id="@+id/msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/icon"
android:layout_alignLeft="@id/title"
android:gravity="right"
android:hint="message"
android:textColor="@color/grey" />

</RelativeLayout>

Merge成最终的Item的布局:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:id="@+id/view_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout>

<RelativeLayout
android:id="@+id/holder"
android:layout_width="120dp"
android:layout_height="match_parent"
android:background="#5FBBB9"
android:clickable="true" >

<TextView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="解绑"
android:textColor="@color/floralwhite" />

</RelativeLayout>

</merge>

最后在Activity里面去用CustomSwipeListView这个自定义View就好了,因为它继承自ListView,所以直接用Adapter绑定数据.

时间: 2024-10-25 17:03:55

类似QQ消息左滑删除的Demo的相关文章

android QQ消息左滑动删除实例(优化版SwipeListViewEX)

仿 QQ消息左滑动删除item消息实例 源代码参考:http://blog.csdn.net/gaolei1201/article/details/42677951 自己作了一些调整,全部代码下载地址: http://download.csdn.net/detail/jenson138/8490067 效果图: 以下只有适配器类: 1 package com.ryg.slideview; 2 3 import java.util.List; 4 5 import com.ryg.slidevie

qq联系人 左滑删除功能

// 局部刷新 NSArray *indexPaths = @[ [NSIndexPath indexPathForRow:0 inSection:0], [NSIndexPath indexPathForRow:1 inSection:0] ]; [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft]; #pragma mark - 按钮的点击 - (IBAc

类似qq的左滑菜单栏简单实现

主演实现代码: 1.滑动的viewController的初始化主要view -(instancetype)initWithSlideView:(YYBaseSlideView * )view{ self = [super init]; if (self) { self.slideView = view; } return self; } -(void)viewDidLoad{ [super viewDidLoad]; _state = SlideViewStateClosed; [self.vi

Android开发学习之路-PopupWindow和仿QQ左滑删除

这周作业,要做一个类似QQ的左滑删除效果的ListView,因为不想给每个item都放一个按钮,所以决定用PopupWindow,这里记录一下 先放一下效果图: 先说明一下这里面的问题: ①没有做到像QQ那样可以允许item跟随手指移动,虽然PopupWindow有update方法让我们动态移动,但是在屏幕外移动会没有动画效果,直接弹进来 ②仔细观察可以发现,item的滑动和删除按钮的滑动是分开的,无法保证它们会一起播放,QQ的动画可以 再说说大概的思路,因为我们没有让item都带上Button

模仿QQ左滑删除

需求: 1.左滑删除 2.向左滑动距离超过一半的时候让它自动滑开,向右滑动超过一半的时候自动隐藏 3.一次只允许滑开一个item 还有,根本不需要自定义view来实现,谨防入坑 布局: <?xml version="1.0" encoding="utf-8"?> <HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" and

ListView左滑删除&amp;代理模式

要实现类似QQ的ListView左滑删除其实可以给ListView中每个条目外面添加一个可以处理左滑事件的View即可.该控件需要重写onInterceptTouchEvent方法和onTouchEvent方法,具体处理过程参考 安卓事件分发机制,确定由自定义控件处理触摸事件后需要调用requestDisallowInterceptTouchEvent来防止ListView响应事件. 下面介绍如何通过代理来实现. public class SlideListView extends ListVi

Android自定义组合控件---教你如何自定义下拉刷新和左滑删除

绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和QQ的对比了一下,并没有太大区别,今天分享给大家,其实并不难,但是不知道为什么网上没有比较好的Demo,当你的项目真的很急的时候,又没有比较好的Demo,那么"那条友谊的小船儿真是说翻就翻啊",好了,下面先来具体看一下实现后的效果吧: 代码已经上传到Github上了,小伙伴们记

ANDROID仿IOS微信滑动删除_SWIPELISTVIEW左滑删除例子

http://dwtedx.sinaapp.com/itshare_290.html 本例子实现了滑动删除ListView的Itemdemo的效果.大家都知道.这种创意是来源于IOS的.左滑删除的功能.在Android上面实现比较麻烦.本例子中不仅实现了左滑删除功能.还实现了左滑赞.左滑分享.左滑收藏等功能.当然大家也可以根据自己项目的需求来修改功能.QQ和微信也实现了相同的功能.大家可以看看.先上程序运行的效果 怎么样.大家看了这个截图是不是很心动呀.而且在左滑的时候还配有简单的滑动动画呢.非

小程序实现左滑删除效果

小程序的左滑删除效果用的是组件 movable-area 和 movable-view 文档 : https://developers.weixin.qq.com/miniprogram/dev/component/movable-view.html 1.movable-area基本概念 (1)movable-area这个就是定义了一个移动的区域,跟普通的<view></view>的含义是一样的,不同在于,接着往下看: 注意:movable-area 必须设置width和heigh