高仿微信实现左滑显示删除button功能
在实际项目中删除列表中的某一项是很常见的功能。传统的做法能够使用长按监听器等,而如今流行的做法是左滑弹出删除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>
高仿微信实现左滑显示删除button功能的更多相关文章
- Android 高仿微信 获取最近刚刚拍照的缩略图 功能实现
原理其实挺简单的,android 中文件 修改 增加 删除等等 都会在数据库里的某个表里记录下来,你需要的时候 只要迅速的去查找这个表里的值 即可得到你想要的所有信息. 实际上 如果真正理解这个表结构 ...
- Flutter高仿微信项目开源-具即时通讯IM功能
项目地址:https://github.com/fluttercandies/wechat_flutter wechat_flutter Flutter版本微信 效果图: 下载体验(Android) ...
- android高仿微信拍照、多选、预览、删除(去除相片)相冊功能
先声明授人与鱼不如授人与渔,仅仅能提供一个思路,当然须要源代码的同学能够私下有偿问我要源代码:QQ:508181017 工作了将近三年时间了,一直没正儿八经的研究系统自带的相冊和拍照,这回来个高仿微信 ...
- 高仿QQ6.0側滑菜单之滑动优化(二)
好了,昨天已经实现了高仿QQ6.0的側滑大致框架.如有兴趣.能够去看下仿QQ6.0側滑之ViewDragHelper的使用(一) 可是之前的实现.仅仅是简单的能够显示和隐藏左側的菜单,可是特别生硬,并 ...
- iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码
iOS精选源码 iOS高仿微信完整项目源码 Khala: Swift 编写的iOS/macOS 路由框架 微信左滑删除效果的实现与TableViewCell的常用样式介绍 实现阴影圆角并存,渐变色背景 ...
- 安卓开发笔记——Fragment+ViewPager组件(高仿微信界面)
什么是ViewPager? 关于ViewPager的介绍和使用,在之前我写过一篇相关的文章<安卓开发复习笔记——ViewPager组件(仿微信引导界面)>,不清楚的朋友可以看看,这里就不再 ...
- 转-Fragment+ViewPager组件(高仿微信界面)
http://www.cnblogs.com/lichenwei/p/3982302.html 什么是ViewPager? 关于ViewPager的介绍和使用,在之前我写过一篇相关的文章<安卓开 ...
- Android 高仿微信实时聊天 基于百度云推送
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天终于有幸利用百 ...
- Android 高仿微信即时聊天 百度云为基础的推
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天最终有幸利用百 ...
随机推荐
- python爬虫(爬取图片)
python爬虫爬图片 爬虫爬校花网校花的图片 第一步 载入爬虫模块 #载入爬虫模块 import re #载入爬虫模块 import requests #载入爬虫模块 第二步 获得校花网的地址,获得 ...
- python列表的增删改查用法
列表,元组 查 索引(下标) ,都是从0开始 切片 .count 查某个元素的出现次数 .index 根据内容找其对应的位置 "haidilao ge" in a 增加 a.app ...
- boot_mem分配器
#define alloc_bootmem_low_pages(x) \ __alloc_bootmem_low(x, PAGE_SIZE, ) void * __init __alloc_bootm ...
- 【笔记】PIL 中的 Image 模块
Image 模块提供了一个同名类(Image),也提供了一些工厂函数,包括从文件中载入图片和创建新图片.例如,以下的脚本先载入一幅图片,将它旋转 45 度角,并显示出来: 1 >>> ...
- debian 9 安装AMD驱动
目录 debian 9 安装AMD驱动 安装驱动之前: 安装驱动: 安装驱动之后: debian 9 安装AMD驱动 需求说明: 安装完成debian系统后独显驱动未安装 操作系统版本: kyeup@ ...
- Leetcode 322.零钱兑换
零钱兑换 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: 输入: co ...
- 九度oj 题目1472:求两个多项式的和
题目描述: 输入两个多项式,计算它们的和. 每个多项式有若干对整数表示,每组整数中,第一个整数表示系数(非0),第二个整数表示该项的次数. 如由3 3 5 -2 1 4 0表示3x^5 - 2 * x ...
- 【bzoj4519】[Cqoi2016]不同的最小割 分治+最小割
题目描述 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将所有顶点处在不同 ...
- 刷题总结——切蛋糕(ssoj)
题目: 切蛋糕 (cake.cpp/c/pas) [问题描述] BG 有一块细长的蛋糕,长度为�. 有一些人要来BG 家里吃蛋糕, BG把蛋糕切成了若干块(整数长度),然后分给这些人.为了公平,每个人 ...
- farm
farm 时间限制:C/C++ 4秒,其他语言8秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 White Rabbit has ...