在实际项目中删除列表中的某一项是很常见的功能。传统的做法能够使用长按监听器等,而如今流行的做法是左滑弹出删除button,微信,QQ等都是这么做的,以下做一个演示样例,代码例如以下:

主页面MainActivity:代码比較简单常规

package com.home.testslideview;

import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView; import com.home.textslideview.R; public class MainActivity extends Activity { private ListView listView; private List<NewInfoBean> list = new ArrayList<NewInfoBean>(); // 适配器
private SlideAdapter adapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initView();
initData();
setAdapter();
} /**
* 初始化页面控件
*/
private void initView() {
listView = (ListView) findViewById(R.id.main_lv);
} /**
* 初始化数据
*/
private void initData() {
list.add(new NewInfoBean("这是測试内容1"));
list.add(new NewInfoBean("这是測试内容2"));
list.add(new NewInfoBean("这是測试内容3"));
list.add(new NewInfoBean("这是測试内容4"));
list.add(new NewInfoBean("这是測试内容5"));
list.add(new NewInfoBean("这是測试内容6"));
list.add(new NewInfoBean("这是測试内容7"));
list.add(new NewInfoBean("这是測试内容8"));
list.add(new NewInfoBean("这是測试内容9"));
list.add(new NewInfoBean("这是測试内容10"));
} /**
* 设置适配器
*/
private void setAdapter() {
if (adapter == null) {
adapter = new SlideAdapter(this, list);
listView.setAdapter(adapter);
} else {
adapter.setList(list);
adapter.notifyDataSetChanged();
}
} }

实体类NewInfoBean:详细项目中由自定义:

package com.home.testslideview;

public class NewInfoBean {
public SlideView slideView; private String content; public SlideView getSlideView() {
return slideView;
} public void setSlideView(SlideView slideView) {
this.slideView = slideView;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public NewInfoBean() {
super();
} public NewInfoBean(String content) {
super();
this.content = content;
} }

适配器SlideAdapter:也比較简单

package com.home.testslideview;

import java.util.List;

import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView; import com.home.testslideview.SlideView.OnSlideListener;
import com.home.textslideview.R; public class SlideAdapter extends BaseAdapter implements OnSlideListener,
OnClickListener { private LayoutInflater inflater; private List<NewInfoBean> list; private Context context; public SlideAdapter(Context context, List<NewInfoBean> list) {
if (inflater == null) {
inflater = LayoutInflater.from(context);
}
this.list = list;
this.context = context;
} @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, View convertView, ViewGroup arg2) { SlideView slideView = (SlideView) convertView;
NewInfoBean bean = list.get(position);
if (slideView == null) {
slideView = new SlideView(context);
slideView.setOnSlideListener(this);
} // 设置内容
TextView contentText = getAdapterView(slideView,
R.id.slideview_tv_content, position);
contentText.setText(bean.getContent()); // 删除button
TextView delText = getAdapterView(slideView, R.id.slideview_tv_del,
position);
delText.setOnClickListener(this); bean.slideView = slideView;
bean.slideView.shrink(); return slideView;
} @SuppressWarnings("unchecked")
public <T extends View> T getAdapterView(View convertView, int id,
Object tag) {
SparseArray<View> viewHolder = null;
try {
if (convertView.getTag(R.id.view_holder) instanceof SparseArray<?>) {
viewHolder = (SparseArray<View>) convertView
.getTag(R.id.view_holder);
}
} catch (ClassCastException e) {
}
if (viewHolder == null) {
viewHolder = new SparseArray<View>();
convertView.setTag(R.id.view_holder, viewHolder);
convertView.setTag(R.id.order_id, tag);
}
View childView = viewHolder.get(id);
if (childView == null) {
childView = convertView.findViewById(id);
childView.setTag(tag);
viewHolder.put(id, childView);
}
return (T) childView;
} public List<NewInfoBean> getList() {
return list;
} public void setList(List<NewInfoBean> list) {
this.list = list;
} @Override
public void onSlide(View view, int status) {
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.slideview_tv_del:
int position = (Integer) v.getTag();
list.remove(position);
notifyDataSetChanged();
break; default:
break;
}
} }

比較关键的两个类:

自己定义的ListView:SlideListView

package com.home.testslideview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView; public class SlideListView extends ListView { private SlideView itemView; public SlideListView(Context context) {
super(context);
} public SlideListView(Context context, AttributeSet attrs) {
super(context, attrs);
} public void shrinkListItem(int position) {
View item = getChildAt(position);
if (item != null) {
try {
((SlideView) item).shrink();
} catch (ClassCastException e) {
e.printStackTrace();
}
}
} @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);
if (position != INVALID_POSITION) {
NewInfoBean data = (NewInfoBean) getItemAtPosition(position);
itemView = data.slideView;
}
}
default:
break;
} if (itemView != null) {
itemView.onRequireTouchEvent(event);
} return super.onTouchEvent(event);
} }

自己定义的ListView中的每一行控件:SlideView(借鉴网上的一个演示样例):

package com.home.testslideview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Scroller; import com.home.textslideview.R; public class SlideView extends LinearLayout { private static final String TAG = SlideView.class.getSimpleName(); private Context mContext;
private Scroller mScroller;
private OnSlideListener mOnSlideListener; private int mHolderWidth = 80; private int mLastX = 0;
private int mLastY = 0;
private static final int TAN = 2; private LayoutInflater inflater; 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 SlideView(Context context) {
super(context);
initView();
} public SlideView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
} private void initView() {
mContext = getContext();
if (inflater == null) {
inflater = LayoutInflater.from(mContext);
}
mScroller = new Scroller(mContext); setOrientation(LinearLayout.HORIZONTAL);
View.inflate(mContext, R.layout.slide_view_merge, this);
mHolderWidth = Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources()
.getDisplayMetrics()));
} 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: {
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) {
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.75 > 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) * 3);
invalidate();
} @Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
} }

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <com.home.testslideview.SlideListView
android:id="@+id/main_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#00000000"
android:fadingEdge="none"
android:listSelector="#00000000"
android:scrollbars="none" /> </LinearLayout>

slide_view_merge.xml:

<?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"
android:orientation="horizontal" > <LinearLayout
android:id="@+id/slideview_layout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:orientation="horizontal" > <TextView
android:id="@+id/slideview_tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="内容部分"/> </LinearLayout> <LinearLayout
android:id="@+id/view_layout_del"
android:layout_width="80dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_toRightOf="@id/slideview_layout_content"
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal" > <TextView
android:id="@+id/slideview_tv_del"
android:layout_width="80dp"
android:layout_height="match_parent"
android:layout_marginBottom="2dp"
android:gravity="center"
android:padding="15dp"
android:text="删除"/> </LinearLayout> </merge>

源代码下载:http://download.csdn.net/detail/u010142437/8855289

高仿微信实现左滑显示删除button功能的更多相关文章

  1. Android 高仿微信 获取最近刚刚拍照的缩略图 功能实现

    原理其实挺简单的,android 中文件 修改 增加 删除等等 都会在数据库里的某个表里记录下来,你需要的时候 只要迅速的去查找这个表里的值 即可得到你想要的所有信息. 实际上 如果真正理解这个表结构 ...

  2. Flutter高仿微信项目开源-具即时通讯IM功能

    项目地址:https://github.com/fluttercandies/wechat_flutter wechat_flutter  Flutter版本微信 效果图: 下载体验(Android) ...

  3. android高仿微信拍照、多选、预览、删除(去除相片)相冊功能

    先声明授人与鱼不如授人与渔,仅仅能提供一个思路,当然须要源代码的同学能够私下有偿问我要源代码:QQ:508181017 工作了将近三年时间了,一直没正儿八经的研究系统自带的相冊和拍照,这回来个高仿微信 ...

  4. 高仿QQ6.0側滑菜单之滑动优化(二)

    好了,昨天已经实现了高仿QQ6.0的側滑大致框架.如有兴趣.能够去看下仿QQ6.0側滑之ViewDragHelper的使用(一) 可是之前的实现.仅仅是简单的能够显示和隐藏左側的菜单,可是特别生硬,并 ...

  5. iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码

    iOS精选源码 iOS高仿微信完整项目源码 Khala: Swift 编写的iOS/macOS 路由框架 微信左滑删除效果的实现与TableViewCell的常用样式介绍 实现阴影圆角并存,渐变色背景 ...

  6. 安卓开发笔记——Fragment+ViewPager组件(高仿微信界面)

    什么是ViewPager? 关于ViewPager的介绍和使用,在之前我写过一篇相关的文章<安卓开发复习笔记——ViewPager组件(仿微信引导界面)>,不清楚的朋友可以看看,这里就不再 ...

  7. 转-Fragment+ViewPager组件(高仿微信界面)

    http://www.cnblogs.com/lichenwei/p/3982302.html 什么是ViewPager? 关于ViewPager的介绍和使用,在之前我写过一篇相关的文章<安卓开 ...

  8. Android 高仿微信实时聊天 基于百度云推送

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天终于有幸利用百 ...

  9. Android 高仿微信即时聊天 百度云为基础的推

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天最终有幸利用百 ...

随机推荐

  1. Django2.0+小程序技术打造微信小程序助手百度云

    加Q[965546358]获取资源 第1章 课程导学 第2章 小程序开发入门 从几个方面介绍小程序开发相关的内容,包括小程序开发者账号注册.小程序开发流程.小程序开发规范.小程序常用的API,例如网络 ...

  2. ZZULIoj 1912 小火山的爱情密码

    Description 小火山获得了一个字符串,然而大火山让小火山从里面截取一段字符串,并且让小火山截取的字符串满足一些字符达到一定数量. 小火山觉得很容易,但是他想要知道他至少得截取多长的字符串. ...

  3. SVM 支持向量机算法介绍

    转自:https://zhuanlan.zhihu.com/p/21932911?refer=baina 参考:http://www.cnblogs.com/LeftNotEasy/archive/2 ...

  4. .NET:权限管理

    题外话: 临近大四,编写各种简历的时候发现,很多电子简历上是可以链上自己在各大论坛上留下的足迹.关于这点,学习网络,拥抱开源,具有互联网思维的博主很后悔,后悔当年只会在网上查资料,不会留资料,空有才能 ...

  5. Mysql 学习目录

    Mysql 目录 Mysql之路[第一篇]:Mysql基础 Mysql之路[第二篇]:Mysql 常用命令 Mysql之路[第三篇]:Python对Mysql的操作 Mysql之路[第四篇]:ORM ...

  6. json的两种表示结构(对象和数组).。

    JSON有两种表示结构,对象和数组.对象结构以”{”大括号开始,以”}”大括号结束.中间部分由0或多个以”,”分隔的”key(关键字)/value(值)”对构成,关键字和值之间以”:”分隔,语法结构如 ...

  7. 九度oj 题目1528:最长回文子串

    题目描述: 回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. 回文子串,顾名思义,即字符串中满足回文性质的子串. 给出一个只由小写英文字符a,b,c...x, ...

  8. BZOJ-1507 文本编辑器(Editor)

    一道极其相似的题...http://hi.baidu.com/8361101/item/5b149103cbf4007cbee97e5f 就多了个区间查找,少了个翻转... 少了翻转的话貌似可以不用S ...

  9. websql使用实例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Nk 1430 Divisors(因子数与质因数)

    Time Limit: 5000 ms    Memory Limit: 10000 kB   Total Submit : 432 (78 users)   Accepted Submit : 10 ...