實現(xiàn)了一個可側(cè)滑刪除的listView刹淌,這個view是一個繼承自listView的自定義view,
實現(xiàn)側(cè)滑刪除穴张,可以通過很多種方式巩剖,今天我介紹的方式是通過PopupWindow的方式來實現(xiàn)的。
效果圖
思路
當(dāng)一個listView在屏幕上顯示的時候敦迄,它上面(屏幕上面)發(fā)生的各種事件恋追,我們是可以捕捉到的,我們只需要判斷一下是不是我們需要的事件罚屋,如果是的話苦囱,就產(chǎn)生反饋,對事件進(jìn)行處理沿后,否則就不處理即可沿彭。
當(dāng)我們發(fā)現(xiàn)用戶是在一個item上面產(chǎn)生了滑動事件,并且是從右向左滑尖滚,并且滿足我們對有效滑動長度的定義的話,那么這次事件我們就判斷是有效的瞧柔,我們就計算到相應(yīng)的位置漆弄,并且產(chǎn)生相應(yīng)的刪除的按鈕就可以了。
當(dāng)我們發(fā)現(xiàn)用戶的單擊事件的時候造锅,我們就讓刪除的按鈕消失就可以了撼唾。
實現(xiàn)思路來自于:鴻洋的博客
實現(xiàn)代碼
/**
* Created by linSir
* date at 2017/5/1.
* describe: listView,主要是實現(xiàn)可以側(cè)滑刪除
*/
public class MyListView extends ListView {
private static final String TAG = MyListView.class.getSimpleName();
private int touchSlop; //用戶滑動的最小距離
private boolean isSliding; //是否相應(yīng)滑動
private int xDown; //按下的x坐標(biāo)
private int yDown; //按下的y坐標(biāo)
private int xMove; //手指移動時x的坐標(biāo)
private int yMove; //手指移動是y的坐標(biāo)
private LayoutInflater mInflater; //一個layoutInflater
private PopupWindow mPopupWindow; //彈出一個用于展示的popupWindow
private int mPopupWindowHeight; //該展示的popupWindow的高度
private int mPopupWindowWidth; //該展示的popupWindow的寬度
private TextView delete; //側(cè)滑后刪除的按鈕
private DeleteClickListener mListener; //點(diǎn)擊刪除后回調(diào)的接口
private View mCurrentView; //當(dāng)前展示刪除按鈕的view
private int mCurrentViewPos; //當(dāng)前展示刪除按鈕的view的位置(下標(biāo))
/**
* 該自定義view的構(gòu)造方法
*/
public MyListView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context); //一個Inflater
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); //最小的滑動距離
View view = mInflater.inflate(R.layout.delete_btn, null); //找到刪除按鈕的view
delete = (TextView) view.findViewById(R.id.delete); //找到刪除按鈕的控件
mPopupWindow = new PopupWindow(view, LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT); //彈出的popupWindow
mPopupWindow.getContentView().measure(0, 0); //初始化
mPopupWindowHeight = mPopupWindow.getContentView().getMeasuredHeight(); //獲取到該view的高度
mPopupWindowWidth = mPopupWindow.getContentView().getMeasuredWidth(); //獲取到該view的寬度
}
/**
* 觸摸事件的派發(fā)
*/
@Override public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getAction();
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN: //action_down 即點(diǎn)擊事件哥蔚,這個時候需要關(guān)閉popupWindow
xDown = x;
yDown = y;
if (mPopupWindow.isShowing()) {
dismissPopWindow();
return false;
}
mCurrentViewPos = pointToPosition(xDown, yDown); //根據(jù)x,y坐標(biāo)獲取到自己的下標(biāo)
View view = getChildAt(mCurrentViewPos - getFirstVisiblePosition());//當(dāng)前可見view的小標(biāo)減去第一個可見的view的下標(biāo)就可以找到當(dāng)前的這個view
mCurrentView = view;
break;
case MotionEvent.ACTION_MOVE: //當(dāng)發(fā)生移動時間的時候
xMove = x;
yMove = y;
int dx = xMove - xDown;
int dy = yMove - yDown;
if (xMove < xDown && Math.abs(dx) > touchSlop && Math.abs(dy) < touchSlop) { //判斷向左滑動倒谷,并且滑動了一定距離
isSliding = true; //滿足這個條件就符合了打開的popupWindow的條件
}
break;
}
return super.dispatchTouchEvent(ev);
}
@Override public boolean onTouchEvent(MotionEvent ev) {
if (mCurrentView == null) { //判斷當(dāng)前的view不存在之后,則直接return不進(jìn)行處理這次時間
return false;
}
int action = ev.getAction();
if (isSliding) {
switch (action) {
case MotionEvent.ACTION_MOVE:
int[] location = new int[2];
mCurrentView.getLocationOnScreen(location);
mPopupWindow.update();
delete.setHeight(getMeasuredHeight()/getChildCount()); //計算出來每一個條目的高度
mPopupWindow.showAtLocation(mCurrentView, Gravity.LEFT | Gravity.TOP,
location[0] + mCurrentView.getWidth(), location[1] + mCurrentView.getHeight() / 2
- mPopupWindowHeight ); //設(shè)置顯示的位置
delete.setOnClickListener(new OnClickListener() {
@Override public void onClick(View view) {
if (mListener != null) {
mListener.onClickDelete(mCurrentViewPos);
mPopupWindow.dismiss();
}
}
});
break;
case MotionEvent.ACTION_UP:
isSliding = false;
break;
}
return true;
}
return super.onTouchEvent(ev);
}
private void dismissPopWindow() {
if (mPopupWindow != null && mPopupWindow.isShowing()) {
mPopupWindow.dismiss();
}
}
public void setDelButtonClickListener(DeleteClickListener listener) {
mListener = listener;
}
}
/**
* Created by linSir
* date at 2017/5/1.
* describe: 用于點(diǎn)擊刪除按鈕的回調(diào)
*/
public interface DeleteClickListener {
void onClickDelete(int position);
}
//測試用例
public class MainActivity extends AppCompatActivity {
private MyListView mListView;
private ArrayAdapter<String> mAdapter;
private List<String> mDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (MyListView) findViewById(R.id.id_listview);
mDatas = new ArrayList<String>(Arrays.asList("111", "222", "333", "444", "555", "666",
"777", "888", "999", "000"));
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDatas);
mListView.setAdapter(mAdapter);
mListView.setDelButtonClickListener(new DeleteClickListener() {
@Override public void onClickDelete(int position) {
Toast.makeText(MainActivity.this, position + " : " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show();
mAdapter.remove(mAdapter.getItem(position));
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, position + " : " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show();
}
});
}
}
//主界面布局文件
<?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.dotengine.linsir.myrecyclerview.MyListView
android:id="@+id/id_listview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.dotengine.linsir.myrecyclerview.MyListView>
</LinearLayout>
//刪除按鈕的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="刪除"
android:textSize="18sp"
android:gravity="center"
android:textColor="#FFF"
android:background="#b4f72626"
android:paddingLeft="12dp"
android:paddingRight="12dp"
/>
</LinearLayout>
以上便是這次分享的自定義view糙箍,最近一直在看自定義view渤愁,還有事件傳遞機(jī)制這里,也寫了很多測試程序深夯,有空的時候會分享出來的~然后再強(qiáng)調(diào)一下抖格,本文的全部思路來自于張鴻洋的博客。