在实际项目中删除列表中的某一项是很常见的功能。传统的做法能够使用长按监听器等,而如今流行的做法是左滑弹出删除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. CSS盒模型-box-sizing

    CSS中Box model是分为两种,第一种是W3C的标准模型,另一种是IE的传统模型 1.W3C的标准Box Model: /*外盒尺寸计算(元素空间尺寸)*/ Element空间高度 = cont ...

  2. cvs 文件无法上传debug

    当时文件始终上传不成功时(一般先update后commit): cvs update filename report:move away filename ,it is in the way cvs ...

  3. 四、10分钟ToPandas_0.24.2

    # Author:Zhang Yuan整理,版本Pandas0.24.2 # 0. 习惯上,我们会按下面格式引入所需要的包: import pandas as pd import numpy as n ...

  4. 二、Pandas库与数据处理

    # Author:Zhang Yuan import pandas as pd import numpy as np #Pandas提供了两大数据结构:一维结构的Series类型.二维结构的DataF ...

  5. JQuery中如何处理键盘事件

    背景:比如在页面中,敲击回车键以后,实现登录功能,在之前的Winform开发时,也遇到过处理键盘事件的功能,比如游戏软件中,上下左右的移动等. 代码如下: $(document).keydown(fu ...

  6. POJ——3159Candies(差分约束SPFA+前向星+各种优化)

    Candies Time Limit: 1500MS   Memory Limit: 131072K Total Submissions: 28071   Accepted: 7751 Descrip ...

  7. 如何构建一个flink sql平台

    在本系列前面的文章中,简单介绍了一下Ignite的机器学习网格,下面会趁热打铁,结合一些示例,深入介绍Ignite支持的一些机器学习算法. 如果要找合适的数据集,会发现可用的有很多,但是对于线性回归来 ...

  8. [luoguP2324] [SCOI2005]骑士精神(A*?)

    传送门 蒟蒻并不懂A*是什么,但是题解里有个Astar 可以看出,当前棋盘和最终的棋盘如果有k个不同的,那么至少需要k-1步来移动 所以如果 当前步数 + k - 1 > limit 就直接退出 ...

  9. [POJ2778]DNA Sequence(AC自动机 + DP + 矩阵优化)

    传送门 AC自动机加DP就不说了 注意到 m <= 10,所以模式串很少. 而 n 很大就需要 log 的算法,很容易想到矩阵. 但是该怎么构建? 还是矩阵 A(i,j) = ∑A(i,k) * ...

  10. [luoguP3668] [USACO17OPEN]Modern Art 2 现代艺术2(栈)

    传送门 还是一个字——栈 然后加一大堆特判 至少我是这么做的 我的代码 #include <cstdio> #include <iostream> #define N 1000 ...