android 滑动删除的listview(自定义view)
2016-03-29 09:26
519 查看
本篇文章算是对郭霖前辈的一篇文章的详述:
一方面是笔者自己尝试从demo中理解了一下自定义view,另一方面是笔者希望通过更详细的注释已经解说,能帮助新手更容易地理解自定义view的使用。
郭霖前辈原文地址:http://blog.csdn.net/guolin_blog/article/details/17357967
首先还是展示一下效果:(源码在文章结尾)
新手比较难理解的几点:(此处新手不懂可以根据源码来看)
1、onFling()函数,新手可以暂且认为他就是设置滑动效果的函数。
onFling函数的参数的解释如下:
e1: 起点
e2: 终点
velocityX: x轴速度
velocityY: y轴速度
2、
相信大家都可以理解,这个函数是获取listview中的某个item。另外我们可以看到,itemLayout是viewgroup类型的,而之后它获取到的是textview的父布局RelativeLayout。(布局可见my_list_view_item.xml)
为什么不直接给ArrayAdapter设置一个textview而要用一个RelativeLayout来包含呢?因为我们之后需要在这个RelativeLayout中添加一个删除的button。
代码截图:
MainActivity:
package com.example.deleteitemlist;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private MyListView myListView;
private MyAdapter adapter;
private List<String> contentList = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化自定的listview中的信息
initList();
myListView = (MyListView) findViewById(R.id.my_list_view);
//实现onDelete接口
myListView.setOnDeleteListener(new MyListView.OnDeleteListener() {
@Override
public void onDelete(int index) {
//删除传过来的位置的item,并且刷新adapter
contentList.remove(index);
adapter.notifyDataSetChanged();
}
});
adapter = new MyAdapter(this, 0, contentList);
myListView.setAdapter(adapter);
}
private void initList() {
contentList.add("Content Item 1");
contentList.add("Content Item 2");
contentList.add("Content Item 3");
contentList.add("Content Item 4");
contentList.add("Content Item 5");
contentList.add("Content Item 6");
contentList.add("Content Item 7");
contentList.add("Content Item 8");
contentList.add("Content Item 9");
contentList.add("Content Item 10");
contentList.add("Content Item 11");
contentList.add("Content Item 12");
contentList.add("Content Item 13");
contentList.add("Content Item 14");
contentList.add("Content Item 15");
contentList.add("Content Item 16");
contentList.add("Content Item 17");
contentList.add("Content Item 18");
contentList.add("Content Item 19");
contentList.add("Content Item 20");
}
}
MyAdapter:
package com.example.deleteitemlist;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
/**
* 项目名称:DeleteItemList
* 类描述:
* 创建人:佳佳
* 创建时间:2016/3/28 11:16
* 修改人:佳佳
* 修改时间:2016/3/28 11:16
* 修改备注:
*/
public class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(R.layout.my_list_view_item, null);
} else {
view = convertView;
}
TextView textView = (TextView) view.findViewById(R.id.text_view);
textView.setText(getItem(position));
return view;
}
}
MyListView:
package com.example.deleteitemlist;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.RelativeLayout;
/**
* 项目名称:DeleteItemList
* 类描述:
* 创建人:佳佳
* 创建时间:2016/3/28 11:14
* 修改人:佳佳
* 修改时间:2016/3/28 11:14
* 修改备注:
*/
public class MyListView extends ListView implements View.OnTouchListener,
GestureDetector.OnGestureListener {
private GestureDetector gestureDetector;
//设置OnDeleteListener的接口,在MainActivity使用的时候实现
private OnDeleteListener listener;
private View deleteButton;
private ViewGroup itemLayout;
private int selectedItem;
private boolean isDeleteShown;
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
gestureDetector = new GestureDetector(getContext(), this);
setOnTouchListener(this);
}
public void setOnDeleteListener(OnDeleteListener l) {
listener = l;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
//如果点击这个自定义的listview的时候已经显示了一个deleteButton了
//那么就让这个deleteButton消失,并且让isDeleteShown表示没有deleteButton显示
if (isDeleteShown) {
itemLayout.removeView(deleteButton);
deleteButton = null;
isDeleteShown = false;
return false;
} else {
//如果没有显示deleteButton,很可能是第一次开启这个view
//就使用GestureDetector来检测是否触发了特定的手势动作
return gestureDetector.onTouchEvent(event);
}
}
@Override
public boolean onDown(MotionEvent e) {
//如果deleteButton已经显示,那么通过他的xy的位置来获取它在listview中的位置
if (!isDeleteShown) {
selectedItem = pointToPosition((int) e.getX(), (int) e.getY());
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
//如果deleteButton不可见 ,而且X的速度的绝对值大于Y的速度的绝对值的时候(手势横向滑动的时候)
if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) {
deleteButton = LayoutInflater.from(getContext()).inflate(
R.layout.delete_button, null);
deleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
itemLayout.removeView(deleteButton);
deleteButton = null;
isDeleteShown = false;
listener.onDelete(selectedItem);
}
});
//此处itemLayout获取到的是textview的父布局RelativeLayout
itemLayout = (ViewGroup) getChildAt(selectedItem
- getFirstVisiblePosition());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.addRule(RelativeLayout.CENTER_VERTICAL);
//设置好了deleteButton的点击效果、布局,添加这个button
itemLayout.addView(deleteButton, params);
//设置isDeleteShown为true,表示deleteButton已经显示
isDeleteShown = true;
}
return false;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
//设置OnDeleteListener的接口,在MainActivity使用的时候实现
public interface OnDeleteListener {
void onDelete(int index);
}
}
activity_main:
<?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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<com.example.deleteitemlist.MyListView
android:id="@+id/my_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"></com.example.deleteitemlist.MyListView>
</RelativeLayout>
delete_button:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delete">
</Button>
my_list_view_item:
<?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/text_view"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:gravity="left|center_vertical"
android:textColor="#000" />
</RelativeLayout>
源码地址:http://download.csdn.net/detail/double2hao/9475061
一方面是笔者自己尝试从demo中理解了一下自定义view,另一方面是笔者希望通过更详细的注释已经解说,能帮助新手更容易地理解自定义view的使用。
郭霖前辈原文地址:http://blog.csdn.net/guolin_blog/article/details/17357967
首先还是展示一下效果:(源码在文章结尾)
新手比较难理解的几点:(此处新手不懂可以根据源码来看)
1、onFling()函数,新手可以暂且认为他就是设置滑动效果的函数。
onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY)
onFling函数的参数的解释如下:
e1: 起点
e2: 终点
velocityX: x轴速度
velocityY: y轴速度
2、
相信大家都可以理解,这个函数是获取listview中的某个item。另外我们可以看到,itemLayout是viewgroup类型的,而之后它获取到的是textview的父布局RelativeLayout。(布局可见my_list_view_item.xml)
为什么不直接给ArrayAdapter设置一个textview而要用一个RelativeLayout来包含呢?因为我们之后需要在这个RelativeLayout中添加一个删除的button。
代码截图:
MainActivity:
package com.example.deleteitemlist;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private MyListView myListView;
private MyAdapter adapter;
private List<String> contentList = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化自定的listview中的信息
initList();
myListView = (MyListView) findViewById(R.id.my_list_view);
//实现onDelete接口
myListView.setOnDeleteListener(new MyListView.OnDeleteListener() {
@Override
public void onDelete(int index) {
//删除传过来的位置的item,并且刷新adapter
contentList.remove(index);
adapter.notifyDataSetChanged();
}
});
adapter = new MyAdapter(this, 0, contentList);
myListView.setAdapter(adapter);
}
private void initList() {
contentList.add("Content Item 1");
contentList.add("Content Item 2");
contentList.add("Content Item 3");
contentList.add("Content Item 4");
contentList.add("Content Item 5");
contentList.add("Content Item 6");
contentList.add("Content Item 7");
contentList.add("Content Item 8");
contentList.add("Content Item 9");
contentList.add("Content Item 10");
contentList.add("Content Item 11");
contentList.add("Content Item 12");
contentList.add("Content Item 13");
contentList.add("Content Item 14");
contentList.add("Content Item 15");
contentList.add("Content Item 16");
contentList.add("Content Item 17");
contentList.add("Content Item 18");
contentList.add("Content Item 19");
contentList.add("Content Item 20");
}
}
MyAdapter:
package com.example.deleteitemlist;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
/**
* 项目名称:DeleteItemList
* 类描述:
* 创建人:佳佳
* 创建时间:2016/3/28 11:16
* 修改人:佳佳
* 修改时间:2016/3/28 11:16
* 修改备注:
*/
public class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(R.layout.my_list_view_item, null);
} else {
view = convertView;
}
TextView textView = (TextView) view.findViewById(R.id.text_view);
textView.setText(getItem(position));
return view;
}
}
MyListView:
package com.example.deleteitemlist;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.RelativeLayout;
/**
* 项目名称:DeleteItemList
* 类描述:
* 创建人:佳佳
* 创建时间:2016/3/28 11:14
* 修改人:佳佳
* 修改时间:2016/3/28 11:14
* 修改备注:
*/
public class MyListView extends ListView implements View.OnTouchListener,
GestureDetector.OnGestureListener {
private GestureDetector gestureDetector;
//设置OnDeleteListener的接口,在MainActivity使用的时候实现
private OnDeleteListener listener;
private View deleteButton;
private ViewGroup itemLayout;
private int selectedItem;
private boolean isDeleteShown;
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
gestureDetector = new GestureDetector(getContext(), this);
setOnTouchListener(this);
}
public void setOnDeleteListener(OnDeleteListener l) {
listener = l;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
//如果点击这个自定义的listview的时候已经显示了一个deleteButton了
//那么就让这个deleteButton消失,并且让isDeleteShown表示没有deleteButton显示
if (isDeleteShown) {
itemLayout.removeView(deleteButton);
deleteButton = null;
isDeleteShown = false;
return false;
} else {
//如果没有显示deleteButton,很可能是第一次开启这个view
//就使用GestureDetector来检测是否触发了特定的手势动作
return gestureDetector.onTouchEvent(event);
}
}
@Override
public boolean onDown(MotionEvent e) {
//如果deleteButton已经显示,那么通过他的xy的位置来获取它在listview中的位置
if (!isDeleteShown) {
selectedItem = pointToPosition((int) e.getX(), (int) e.getY());
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
//如果deleteButton不可见 ,而且X的速度的绝对值大于Y的速度的绝对值的时候(手势横向滑动的时候)
if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) {
deleteButton = LayoutInflater.from(getContext()).inflate(
R.layout.delete_button, null);
deleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
itemLayout.removeView(deleteButton);
deleteButton = null;
isDeleteShown = false;
listener.onDelete(selectedItem);
}
});
//此处itemLayout获取到的是textview的父布局RelativeLayout
itemLayout = (ViewGroup) getChildAt(selectedItem
- getFirstVisiblePosition());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.addRule(RelativeLayout.CENTER_VERTICAL);
//设置好了deleteButton的点击效果、布局,添加这个button
itemLayout.addView(deleteButton, params);
//设置isDeleteShown为true,表示deleteButton已经显示
isDeleteShown = true;
}
return false;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
//设置OnDeleteListener的接口,在MainActivity使用的时候实现
public interface OnDeleteListener {
void onDelete(int index);
}
}
activity_main:
<?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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<com.example.deleteitemlist.MyListView
android:id="@+id/my_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"></com.example.deleteitemlist.MyListView>
</RelativeLayout>
delete_button:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delete">
</Button>
my_list_view_item:
<?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/text_view"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:gravity="left|center_vertical"
android:textColor="#000" />
</RelativeLayout>
源码地址:http://download.csdn.net/detail/double2hao/9475061
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories