今天研究了一下android里面的手势,结合昨天学习的自定义View,做了一个自定义的listview,继承自listView,添加了条目的滑动手势操作,滑动后出现一个删除按钮,点击删除按钮,触发一个删除的事件,在事件中进行删除当选行的元素,刷新listview。
一共分为以下几步进行:
1、新建一个按钮的布局文件,用来作为动态添加的按钮:layout_button.xml
<?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android" android:text="删除" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn1"/>
2、定义按钮显示,隐藏的动画效果,简单的缩放动画:
btn_hide.xml:
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:fromXScale="1.0" android:toXScale="0" android:fromYScale="1.0" android:toYScale="1.0" android:pivotX="100%" android:pivotY="0" android:duration="200" />
btn_show.xml:
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:fromXScale="0" android:toXScale="1.0" android:fromYScale="1.0" android:toYScale="1.0" android:pivotX="100%" android:pivotY="0" android:duration="200" />
3、自定义ListView,继承自listView,并实现OnTouchListener,OnGestureListener接口,代码就不一步一步写了,里面我尽可能的注释详细一些:MyListView.java
package com.example.viewtest; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.ListView; import android.widget.RelativeLayout; /** * 项目名称:viewTest * 实现功能: 自定义ListView,增加滑动删除功能 * 类名称:MyListView * 类描述:(该类的主要功能) * 创建人:徐纪伟 * E-mail: xujiwei558@126.com * 创建时间:2014年11月2日 下午3:37:40 * 修改人: * 修改时间: * 修改备注: * @version */ public class MyListView extends ListView implements OnTouchListener,OnGestureListener { /** * 手势识别类 */ private GestureDetector gestureDetector; /** * 滑动时出现的按钮 */ private View btnDelete; /** * listview的每一个item的布局 */ private ViewGroup viewGroup; /** * 选中的项 */ private int selectedItem; /** * 是否已经显示删除按钮 */ private boolean isDeleteShow; /** * 点击删除按钮时删除每一行的事件监听器 */ private OnItemDeleteListener onItemDeleteListener; /** * 构造函数,初始化手势监听器等 * @param context * @param attrs */ public MyListView(Context context, AttributeSet attrs) { super(context, attrs); gestureDetector = new GestureDetector(getContext(),this); setOnTouchListener(this); } public void setOnItemDeleteListener(OnItemDeleteListener onItemDeleteListener) { this.onItemDeleteListener = onItemDeleteListener; } @Override public boolean onTouch(View v, MotionEvent event) { //得到当前触摸的条目 selectedItem = pointToPosition((int)event.getX(), (int)event.getY()); //如果删除按钮已经显示,那么隐藏按钮,异常按钮在当前位置的绘制 if (isDeleteShow) { btnHide(btnDelete); viewGroup.removeView(btnDelete); btnDelete = null; isDeleteShow = false; return false; }else{ //如果按钮没显示,则触发手势事件 //由此去触发GestureDetector的事件,可以查看其源码得知,onTouchEvent中进行了手势判断,调用onFling return gestureDetector.onTouchEvent(event); } } @Override public boolean onDown(MotionEvent e) { //得到当前触摸的条目 if (!isDeleteShow) { selectedItem = pointToPosition((int)e.getX(), (int)e.getY()); } return true; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } /** * 滑动删除的主要响应方法。 */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //如果删除按钮没有显示,并且手势滑动符合我们的条件 //此处可以根据需要进行手势滑动的判断,如限制左滑还是右滑,我这里是左滑右滑都可以 if (!isDeleteShow && Math.abs(velocityX) > Math.abs(velocityY)) { //在当前布局上,动态添加我们的删除按钮,设置按钮的各种参数、事件,按钮的点击事件响应我们的删除项监听器 btnDelete = LayoutInflater.from(getContext()).inflate(R.layout.layout_button, null); btnDelete.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //btnHide(btnDelete); viewGroup.removeView(btnDelete); btnDelete = null; isDeleteShow = false; onItemDeleteListener.onItemDelete(selectedItem); } }); viewGroup = (ViewGroup)getChildAt(selectedItem - getFirstVisiblePosition()); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); layoutParams.addRule(RelativeLayout.CENTER_VERTICAL); btnDelete.setLayoutParams(layoutParams); viewGroup.addView(btnDelete); btnShow(btnDelete); isDeleteShow = true; }else{ setOnTouchListener(this); } return false; } /** * @类名称: OnItemDeleteListener * @描述: 删除按钮监听器 * @throws * @author 徐纪伟 * 2014年11月9日上午11:25:37 */ public interface OnItemDeleteListener{ public void onItemDelete(int selectedItem); } /** * @方法名称: btnShow * @描述: 按钮显示时的动画 * @param @param v * @return void * @throws * @author 徐纪伟 * 2014年11月9日 上午11:25:12 */ private void btnShow(View v){ v.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.btn_show)); } /** * @方法名称: btnHide * @描述: 按钮隐藏时的动画 * @param @param v * @return void * @throws * @author 徐纪伟 * 2014年11月9日 上午11:25:23 */ private void btnHide(View v){ v.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.btn_hide)); } }
4、使用方法,布局文件,activity,很简单activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.viewtest.MyListView android:id="@+id/my_listview" android:layout_width="match_parent" android:layout_height="match_parent"> </com.example.viewtest.MyListView> </RelativeLayout>
listview的每一个item的布局文件,一个textview,item.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="50dp" android:text="TextView" /> </RelativeLayout>
activity,初始化listview,adapter的使用就不在介绍,跟普通的一样,唯一不同的就是,要给我们的自定义listview添加我们自定义的删除按钮单击事件,以此来响应我们的删除事件,MainActivity.java:
package com.example.viewtest; import java.util.LinkedList; import java.util.List; import android.content.Context; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.example.viewtest.MyListView.OnItemDeleteListener; public class MainActivity extends ActionBarActivity { /** * 自定义listview对象 */ private MyListView myListview; /** * listView的数据集合 */ private List<String> contentList = new LinkedList<String>(); /** * 自定义数据适配器 */ private MyAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化数据 setData(); myListview = (MyListView)findViewById(R.id.my_listview); adapter = new MyAdapter(this); myListview.setAdapter(adapter); //添加自定义listview的按钮单击事件,处理删除结果,和普通listview使用的唯一不同之处, myListview.setOnItemDeleteListener(new OnItemDeleteListener() { @Override public void onItemDelete(int index) { contentList.remove(index); adapter.notifyDataSetChanged(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } /** * @类名称: MyAdapter * @描述: 自定义数据适配器 * @throws * @author 徐纪伟 * 2014年11月9日下午12:20:19 */ class MyAdapter extends BaseAdapter{ private Context context; public MyAdapter(Context context) { this.context = context; } @Override public int getCount() { // TODO Auto-generated method stub return contentList.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return contentList.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.item, null); } TextView textView = (TextView)convertView.findViewById(R.id.textView1); textView.setText(contentList.get(position)); return convertView; } } /** * @方法名称: setData * @描述: 初始化数据 * @param * @return void * @throws * @author 徐纪伟 * 2014年11月9日 下午12:20:32 */ private void setData() { for (int i = 0; i < 30; i++) { contentList.add("Item "+i); } } }
运行效果:
再给button加上selector背景,更好看一些:selector_btn_red.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_pressed="true" android:drawable="@drawable/btn_style_zero_pressed"></item> <item android:state_pressed="false" android:drawable="@drawable/btn_style_zero_normal"></item> </selector>
资源图片在附件源码中上传。
最终效果:
图片显示的位置在自定义listview中可以调整。
相关推荐
尝试在SwipeListView的顶部添加布局,实现一个自定义的可以下拉刷新的SwipeListView。 至于SwipeListView可以Github中下载项目库源代码。 其中需要用到NineOldAndroids_library,已包含提供的Demo中。
[四次元]仿QQ消息列表(ListView)滑动删除效果源码.rar [四次元]仿QQ的头像选择弹出的对话框,酷似!.zip [四次元]前面部分可以编辑后面部分不可编辑的EditText.zip [四次元]动态添加RadioGroup的RadioButton.zip [四...
最近项目需要用到可以滑动删除并且带有上拉加载下拉刷新的Listview,查阅了一些资料,大多都是在SwipeMenuListView的基础上去添加头部和底部View,来扩展上拉加载和下拉刷新的功能,不过需要手动的去绘制UI及处理一些...
可以增加、删除来电,添加桌面快捷方式,代码分层架构。采用 Tabhost 自定义ListView 滑动显示删除按钮技术,耗时两周的成果,绝对值得借鉴。
它具有以下功能: 触控效果: 支持的api的波纹效果,否则为普通的触摸效果自定义背景可绘制选择动作时自定义可绘制多选和操作 滑动即可删除添加分频器: 高度颜色PS:因为这是我的第一个库,所以我不能保证它会提供...
添加拖拽、滑动删除 开启,监听即可,就是这么简单。 树形列表 比ExpandableListView还要强大,支持多级。 自定义ViewHolder 支持自定义ViewHolder,让开发者随心所欲。 扩展框架 组合第三方框架,轻松实现更多需求...
|--ListView之动态添加子view |--ListView优化之分页加载 |--ListView优化之动态加载 |--ListView优化之控制getView实现复杂显示 |--ListView优化之标准写法 |--listview老虎机 界面设计 水果机 |--listview页面...
本书是一本Android进阶类书籍,采用理论、源码和实践相结合的... 15.1.5 ListView和Bitmap优化 501 15.1.6 线程优化 501 15.1.7 一些性能优化建议 501 15.2 内存泄露分析之MAT工具 502 15.3 提高程序的可维护性 506
10.18 为列表添加自定义的缩略图图标 10.19 创建列表日历的效果 10.20 动态创建listview列表项 10.21 动态加载和切换页面 10.22 在页面切换时显示加载进度框 10.23 在屏幕旋转时更改显示样式 10.24 在列表框中实现...
《Android开发艺术探索》是一本Android进阶类... 15.1.5 ListView和Bitmap优化 / 501 15.1.6 线程优化 / 501 15.1.7 一些性能优化建议 / 501 15.2 内存泄露分析之MAT工具 / 502 15.3 提高程序的可维护性 / 506
2、递归删除目录或文件 57 30、手动更新所有Widget 58 31、有关ListView 问题 58 32、在手机上打开文件的方法 59 33、使用系统自带的TabHost的问题 59 34、弹出菜单 61 35、Toast重叠显示时延迟解决 62 36、ADT新...
演示了不同的数据库的各种操作(连接、删除、添加……等等) ATL开发指南源码 内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举器和集合以及线程管理等等。 ATL实现的...
演示了不同的数据库的各种操作(连接、删除、添加……等等) ATL开发指南源码 内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举器和集合以及线程管理等等。 ATL实现的...
演示了不同的数据库的各种操作(连接、删除、添加……等等) ATL开发指南源码 内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举器和集合以及线程管理等等。 ATL实现的...
演示了不同的数据库的各种操作(连接、删除、添加……等等) ATL开发指南源码 内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举器和集合以及线程管理等等。 ATL实现的...
演示了不同的数据库的各种操作(连接、删除、添加……等等) ATL开发指南源码 内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举器和集合以及线程管理等等。 ATL实现的...
6.15 经典的ListView列表框 第7章 键盘操作和状态栏特效 7.1 按功能键返回首页 7.2 回车实现Tab键功能 7.3 Ctrl+Enter提交数据 7.4 IE中屏蔽退格建(Back Space) 7.5 屏蔽键盘所有键 7.6 JavaScript捕获方向键 7.7 ...