您的位置:首页 > 其它

自定义一个带删除按钮的ListView

2016-08-12 23:17 357 查看
OK,回顾一下ListView的内容。

要把数据通过ListView显示到屏幕,那么就要有三个东西,ListView&Adapter&data。

先把全部代码放给大家看吧。

首先是布局文件,分别为Activity.xml布局文件,delete_button.xml布局文件,item_show.xml布局文件。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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"
tools:context="com.example.listviewdemo.MainActivity">

<com.example.listviewdemo.MyListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/my_ListView" />

</RelativeLayout>


<?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">

<Button
android:id="@+id/delete_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="删除"/>

</LinearLayout>


<?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:layout_width="match_parent"
android:layout_height="50dp"
android:id="@+id/item_text"
android:layout_centerVertical="true"/>

</RelativeLayout>


接下来放代码。

首先是activity的代码。

public class MainActivity extends Activity {

private MyListView myListView;
private ArrayList<String> itemList;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myListView = (MyListView) findViewById(R.id.my_ListView);
//new一个ArrayList,方便存储和提取数据。
itemList = new ArrayList<String>();
//制造数据
init();
final MyAdapter myAdapter = new MyAdapter();
myListView.setAdapter(myAdapter);
myListView.setOnDeleteListener(new MyListView.onDeleteListener() {
@Override
public void onDelete(int index) {
//利用返回的itemIndex,移除对应的item。
itemList.remove(index);
//通知对应的视图进行改变
myAdapter.notifyDataSetChanged();
}
});
}

public class MyAdapter extends BaseAdapter {
//listView里面,一行一行的视图。
private View itemView;

@Override
public int getCount() {
return itemList.size();
}

@Override
public Object getItem(int i) {
return null;
}

@Override
public long getItemId(int i) {
return 0;
}

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null) {
itemView = View.inflate(MainActivity.this, R.layout.item_show, null);
} else {
itemView = view;
}
TextView itemText = (TextView) itemView.findViewById(R.id.item_text);
itemText.setText(itemList.get(i));
return itemView;
}
}

public void init() {
for (int i = 1; i < 100; i++) {
StringBuilder itemContent = new StringBuilder("内容");
itemContent.append(i);
itemList.add(itemContent.toString());
}
}

}


然后到自定义ListView的代码

/**
* 自定义一个ListView,实现一些手势功能。
* 实现GestureDetector.OnGestureListener这个手势监听接口
* Created by Administrator on 2016/8/10.
*/
public class MyListView extends ListView implements GestureDetector.OnGestureListener {

//内部接口
private onDeleteListener listener;

//选择的第几个item
private int selectedItemIndex;

//手势检测
private GestureDetector mGestureDetector;

//屏幕内,选择的item的布局。
private RelativeLayout itemLayout;

//删除按钮
private Button deleteButton;

//全局控制删除按钮变量,boolean默认值是false。
private boolean deleteButtonIsVisible;

private ViewGroup deleteButtonLayout;

public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
//new一个手势检测对象,表明在MyListView这个类注册手势探测
mGestureDetector = new GestureDetector(context, this);
}

/**
* 按下的时候触发事件
*
* @param motionEvent 按下时候触发的事件。
* @return
*/
@Override
public boolean onDown(MotionEvent motionEvent) {
//通过pointToPosition获得点选的item
selectedItemIndex = pointToPosition(((int) motionEvent.getX()), ((int) motionEvent.getY()));

//通过getChildAt获得选择的布局。
itemLayout = (RelativeLayout) getChildAt(selectedItemIndex - getFirstVisiblePosition());
return false;
}

@Override
public void onShowPress(MotionEvent motionEvent) {

}

@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
return false;
}

@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
return false;
}

@Override
public void onLongPress(MotionEvent motionEvent) {

}

/**
* 滑动触发事件
*
* @param e1        开始滑动触发的事件
* @param e2        结束滑动触发的事件
* @param velocityX X轴的滑动速度,为矢量,左向右滑,大于零。右向左滑,小于零。
* @param velocityY Y轴的滑动速度,同上。
* @return
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

/**
*触发条件为:没有删除按钮,并且X轴的滑动速度大于Y轴滑动速度,并且是从右向左滑。
*/
if (!deleteButtonIsVisible && Math.abs(velocityX) > Math.abs(velocityY) && velocityX < 0) {
//获取删除按钮View
deleteButtonLayout = (ViewGroup) View.inflate(getContext(), R.layout.delete_button, null);
deleteButton = (Button) deleteButtonLayout.findViewById(R.id.delete_button);

//把删除按钮从原先的布局去除,方便等会被添加到另一个布局中。
deleteButtonLayout.removeView(deleteButton);

//布局参数设定
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);

//把删除按钮添加入选定的滑动item
itemLayout.addView(deleteButton, params);

//由于添加了,更改deleteButtonIsVisible的值。
deleteButtonIsVisible = true;

deleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//把结果反馈给Acitivity,然后移除对应的数据。
listener.onDelete(selectedItemIndex);
itemLayout.removeView(deleteButton);
deleteButtonIsVisible = false;
}
});

}
//由于由右向左滑动时,改变了deleteButtonIsVisible的值,所以现在是按钮存在的情况下,X轴速度大于Y轴速度,并且是从由左向右滑动,触发。
else if (deleteButtonIsVisible && Math.abs(velocityX) > Math.abs(velocityY) && velocityX > 0) {
itemLayout.removeView(deleteButton);
deleteButtonIsVisible = false;
}
return false;
}

/**
* 事件先传递到这,然后再传递到手势探测的事件里
*
* @param ev 触摸事件
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
//把触摸事件传递给手势探测器
mGestureDetector.onTouchEvent(ev);
return super.onTouchEvent(ev);
}

//实现一个内部接口,用于把结果反馈回Activity。
public interface onDeleteListener {
void onDelete(int index);
}

/**
* 提供给外部,从外部传递进来一个接口,用于等会的回调
*
* @param listener
*/
public void setOnDeleteListener(onDeleteListener listener) {
this.listener = listener;
}
}


实现了从右向左滑动,出现删除按钮,从左向右滑动,删除按钮消失,点击删除按钮,则删除item。

效果图

从右向左滑动,出现删除按钮。



从左向右滑动,删除按钮消失。



点击删除按钮,删除项目。



接下来说一下这个方法。
getFirstVisiblePosition()
,这个方法有什么作用呢?它的作用是得到当前显示在屏幕上的该列表视图的第一项。这个Position跟List内的数据的位置类似,0代表第一行,9代表第十行。下面我们做个简单的测试。

我们在
public boolean onDown(MotionEvent motionEvent){......}
里加入两个方法。

System.out.println("selectedItemIndex的意义:"+selectedItemIndex);
System.out.println("getFirstVisiblePosition的意义:"+getFirstVisiblePosition());


然后我们随便在列表的界面点击,会有结果反馈。我们点击内容18好了。

selectedItemIndex的意义:17
getFirstVisiblePosition的意义:11


根据点击得到的反馈结果,相信对之前的这句话“当前显示在屏幕上的该列表视图的第一项”也能够理解了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐