Scroller应用:ListView滑动删除
1、设计思路
在Scroller的应用--滑屏实现中使用Scroller实现滑屏效果,这里使用Scroller与ListView实现相似QQ滑动。然后点击删除功能。设计思路是Item使用Scroller实现滑动,ListView依据触摸推断是横向滑动还是竖直滑动。关于点击事件处理思路:对于View的onClick事件跟寻常一样,里面针对OnItemClick做了处理,推断触摸距离来推断。假设小于5的话,在Item的onTouchEvent方法中的MotionEvent.ACTION_UP里面返回false,这样ListView里面的dispatchTouchEvent的super.dispatchTouchEvent(event)就会返回false,依据x,y获取当前position以及点击的view。调用super.performItemClick(view, position, view.getId());来告诉ListView出发onItemClick事件。
2、Item的代码
package com.jwzhangjie.scrollview; 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.Scroller; public class ListItemDelete extends LinearLayout { private Scroller mScroller;// 滑动控制
private float mLastMotionX;// 记住上次触摸屏的位置
private int deltaX;
private int back_width;
private float downX; public ListItemDelete(Context context) {
this(context, null);
} public ListItemDelete(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
} private void init(Context context) {
mScroller = new Scroller(context);
} @Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {// 会更新Scroller中的当前x,y位置
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i < count; i++) {
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
if (i == 1) {
back_width = getChildAt(i).getMeasuredWidth();
}
} } @Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
float x = event.getX();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.e("test", "item ACTION_DOWN");
mLastMotionX = x;
downX = x;
break;
case MotionEvent.ACTION_MOVE:
Log.e("test", back_width + " item ACTION_MOVE " + getScrollX());
deltaX = (int) (mLastMotionX - x);
mLastMotionX = x;
int scrollx = getScrollX() + deltaX;
if (scrollx > 0 && scrollx < back_width) {
scrollBy(deltaX, 0);
} else if (scrollx > back_width) {
scrollTo(back_width, 0);
} else if (scrollx < 0) {
scrollTo(0, 0);
}
break;
case MotionEvent.ACTION_UP:
Log.e("test", "item ACTION_UP");
int scroll = getScrollX();
if (scroll > back_width / 2) {
scrollTo(back_width, 0);
} else {
scrollTo(0, 0);
}
if (Math.abs(x - downX) < 5) {// 这里依据点击距离来推断是否是itemClick
return false;
}
break;
case MotionEvent.ACTION_CANCEL:
scrollTo(0, 0);
break;
}
return true;
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int margeLeft = 0;
int size = getChildCount();
for (int i = 0; i < size; i++) {
View view = getChildAt(i);
if (view.getVisibility() != View.GONE) {
int childWidth = view.getMeasuredWidth();
// 将内部子孩子横排排列
view.layout(margeLeft, 0, margeLeft + childWidth,
view.getMeasuredHeight());
margeLeft += childWidth;
}
}
}
}
3、ListView的代码
package com.jwzhangjie.scrollview; 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 ScrollListviewDelete extends ListView { private float minDis = 10;
private float mLastMotionX;// 记住上次X触摸屏的位置
private float mLastMotionY;// 记住上次Y触摸屏的位置
private boolean isLock = false; public ScrollListviewDelete(Context context, AttributeSet attrs) {
super(context, attrs);
} /**
* 假设一个ViewGroup的onInterceptTouchEvent()方法返回true。说明Touch事件被截获,
* 子View不再接收到Touch事件。而是转向本ViewGroup的
* onTouchEvent()方法处理。 从Down開始,之后的Move,Up都会直接在onTouchEvent()方法中处理。
* 先前还在处理touch event的child view将会接收到一个 ACTION_CANCEL。 * 假设onInterceptTouchEvent()返回false。则事件会交给child view处理。 */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isIntercept(ev)) {
return false;
}
return super.onInterceptTouchEvent(ev);
} @Override
public boolean dispatchTouchEvent(MotionEvent event) {
boolean dte = super.dispatchTouchEvent(event);
if (MotionEvent.ACTION_UP == event.getAction() && !dte) {//onItemClick
int position = pointToPosition((int)event.getX(), (int)event.getY());
View view = getChildAt(position);
super.performItemClick(view, position, view.getId());
}
return dte;
} @Override
// 处理点击事件,假设是手势的事件则不作点击事件 普通View
public boolean performClick() {
return super.performClick();
} @Override
// 处理点击事件。假设是手势的事件则不作点击事件 ListView
public boolean performItemClick(View view, int position, long id) {
return super.performItemClick(view, position, id);
} /**
* 检測是ListView滑动还是item滑动 isLock 一旦判读是item滑动。则在up之前都是返回false
*/
private boolean isIntercept(MotionEvent ev) {
float x = ev.getX();
float y = ev.getY();
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.e("test", "isIntercept ACTION_DOWN "+isLock);
mLastMotionX = x;
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
Log.e("test", "isIntercept ACTION_MOVE "+isLock);
if (!isLock) {
float deltaX = Math.abs(mLastMotionX - x);
float deltay = Math.abs(mLastMotionY - y);
mLastMotionX = x;
mLastMotionY = y;
if (deltaX > deltay && deltaX > minDis) {
isLock = true;
return false;
}
} else {
return false;
}
break;
case MotionEvent.ACTION_UP:
Log.e("test", "isIntercept ACTION_UP "+isLock);
isLock = false;
break;
case MotionEvent.ACTION_CANCEL:
Log.e("test", "isIntercept ACTION_CANCEL "+isLock);
isLock = false;
break;
}
return true;
} }
4、Activity代码
package com.jwzhangjie.scrollview; import java.util.ArrayList;
import java.util.List; import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast; public class ScrollerDeleteActivity extends FragmentActivity implements
OnItemClickListener { private Toast mToast;
private ScrollListviewDelete listviewDelete;
private DeleteAdapter adapter;
private String[] datas = { "第一项", "第二项", "第三项", "第四项", "第五项", "第六项", "第七项",
"第八项", "第九项", "第十项" };
private List<String> listDatas = new ArrayList<String>(); @Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_scroller_delete);
int len = datas.length;
for (int i = 0; i < len; i++) {
listDatas.add(datas[i]);
}
listviewDelete = (ScrollListviewDelete) findViewById(android.R.id.list);
adapter = new DeleteAdapter();
listviewDelete.setAdapter(adapter);
listviewDelete.setOnItemClickListener(this);
} class DeleteAdapter extends BaseAdapter { @Override
public int getCount() {
return listDatas.size();
} @Override
public Object getItem(int position) {
return listDatas.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(final int position, View convertView,
ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(getApplicationContext())
.inflate(R.layout.item_delete, null);
holder.itemData = (TextView) convertView
.findViewById(R.id.itemData);
holder.btnDelete = (Button) convertView
.findViewById(R.id.btnDelete);
holder.btnNao = (Button) convertView.findViewById(R.id.btnNao);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.btnDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showInfo("点击删除了");
}
});
holder.itemData.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
showInfo("点击了数据: " + listDatas.get(position));
}
});
holder.btnNao.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showInfo("点击了闹铃");
}
});
holder.itemData.setText(listDatas.get(position));
return convertView;
} class ViewHolder {
TextView itemData;
Button btnDelete;
Button btnNao;
}
} @Override
public void onItemClick(AdapterView<? > parent, View view, int position,
long id) {
showInfo("onItemClick : " + position);
} public void showInfo(String text) {
if (mToast == null) {
mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
} else {
mToast.setText(text);
mToast.setDuration(Toast.LENGTH_SHORT);
}
mToast.show();
} }
5、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.jwzhangjie.scrollview.ScrollListviewDelete
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<com.jwzhangjie.scrollview.ListItemDelete xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <LinearLayout
android:id="@+id/front"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_item_list_8"
android:gravity="center"
android:orientation="horizontal" > <TextView
android:id="@+id/itemData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="測试数据" />
</LinearLayout> <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" > <Button
android:id="@+id/btnNao"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/bg_item_list_4"
android:text="闹铃" /> <Button
android:id="@+id/btnDelete"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/bg_item_list_5"
android:text="删除" />
</LinearLayout> </com.jwzhangjie.scrollview.ListItemDelete>
6、界面效果
不保证上面的代码是最新的。更新代码地址:https://github.com/jwzhangjie/-ScrollerDelete
V1.0版本号:解决提供改动数据多时。item滑动底部数据反复。解决方式:推断是否有滑动的item,假设有则复位
地址:https://github.com/jwzhangjie/-ScrollerDelete 里面有编译好的apk
Scroller应用:ListView滑动删除的更多相关文章
- ListView滑动删除效果实现
通过继承ListView然后结合PopupWindow实现 首先是布局文件: delete_btn.xml:这里只需要一个Button <?xml version="1.0" ...
- ListView滑动删除
本来准备在ListView的每个Item的布局上设置一个隐藏的Button,当滑动的时候显示.但是因为每次只要存在一个Button,发现每个Item上的Button相互间不好控制.所以决定继承List ...
- ListView滑动删除 ,仿腾讯QQ
转载请表明出处:http://blog.csdn.net/lmj623565791/article/details/22961279 在CSDN上开了很多大神们的文章,感觉受益良多,也非常欣赏大家的分 ...
- ListView + PopupWindow实现滑动删除
原文:ListView滑动删除 ,仿腾讯QQ(鸿洋_) 文章实现的功能是:在ListView的Item上从右向左滑时,出现删除按钮,点击删除按钮把Item删除. 看过文章后,感觉没有必要把dispat ...
- 【转】Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果
原文网址:http://blog.csdn.net/xiaanming/article/details/17539199 转帖请注明本文出自xiaanming的博客(http://blog.csdn. ...
- [转]Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果
转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17539199),请尊重他人的辛勤劳动成果,谢谢! 我在上一 ...
- Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果
转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17539199),请尊重他人的辛勤劳动成果,谢谢! 我在上一 ...
- Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果
本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877) 今天还是给大家带来自定义控件的编写,自定义一个Lis ...
- 【转】Android 实现ListView的滑动删除效果
http://www.cnblogs.com/weixiao870428/p/3524055.html http://download.csdn.net/download/love_javc_you/ ...
随机推荐
- office2007添加 方框并对勾选中 及约等于
看这里! http://wenku.baidu.com/view/8f2d8fbac77da26925c5b0f5.html
- Elasticsearch 5.5.1的安装和入门教程(转)
说明:转自老阮的文章,业界最简单的入门教程.一切的安装的运行建议不要用root权限,最好是当前用户下的权限. 作者: 阮一峰 日期: 2017年8月17日 全文搜索属于最常见的需求,开源的 Elast ...
- 最佳实践: 勿在 Servlet 中实现 SingleThreadModel
摘要 请不要实现 SingleThreadModel 接口.这种实践将导致 Web 容器创建多个 servlet 实例:即为每个用户创建一个实例.对于任何大小的应用程序,这种实践都将导致严重的性能问题 ...
- (转)C++ STL中的vector的内存分配与释放
C++ STL中的vector的内存分配与释放http://www.cnblogs.com/biyeymyhjob/archive/2012/09/12/2674004.html 1.vector的内 ...
- 从connect到express01-connect
介绍 Connect是一个node中间件框架.每个中间件在http处理过程中通过改写request, response的数据.状态,实现了特定的功能. 根据中间件在整个http处理流程的位置,将中间件 ...
- 调用wsdl的接口-用axis
// 创建一个服务(service)调用(call) org.apache.axis.client.Service service = new org.apache.axis.client.Servi ...
- 使用weinre调试手机页面
阅读目录 介绍Weinre 安装Weinre 通过Weinre调试页面 启动target 介绍Weinre Weinre(Web Inspector Remote),是一种远程调试工具.功能与Fire ...
- Android应用程序访问linux驱动第一步:实现并测试Linux驱动
一直都想亲自做一次使用android应用程序访问Linux内核驱动的尝试,但总是没能做到.最近抽出时间,下决心重新尝试一次.尝试的开始当然是先写一个Linux内核驱动了. 我希望写一个简单测驱动程序, ...
- deferred rendering with msaa
https://docs.nvidia.com/gameworks/content/gameworkslibrary/graphicssamples/d3d_samples/antialiasedde ...
- 将思维转向rss
本屌丝因为穷住在了离市区比较远的农民房,平时上下班单程地铁时间接近一小时.在这漫长的一小时里,总得干点什么来蹉跎这段时光,看手机是最容易实现的事情.最地铁信号不好,手机也没什么好看的. 经过高人指点说 ...