Android listView item側滑實現刪除和置頂功能
第一次寫部落格,先說下大概思路吧~
要顯示item側滑顯示刪除,置頂。首先要隱藏一部分item的佈局(自定義隱藏佈局寬度,在adapter裡設定LayoutParams)。然後重寫listview的onInterceptTouchEvent()和onTouchEvent()方法,然後對listview的滑動進行判斷,最後進行相應的操作(刪除啦,置頂啦,取消置頂bulabula)。刪除需要dataList.remove(position),置頂就是將點選的item先執行dataList.add(0,object),然後執行dataList.remove(position),最後adapter.notifyDataSetChanged();先來兩張效果圖
1.新建attrs.xml,設定好自定義屬性(其實就是右邊隱藏佈局的寬度啦),程式碼很簡單,直接貼上來了
[html] view plain copy print?- <?xmlversion=“1.0”encoding=“utf-8”?>
- <resources>
- <declare-styleablename=“slidingitemlistview”>
- <attrname=“right_width”format=“dimension”></attr>
- </declare-styleable>
- </
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="slidingitemlistview">
<attr name="right_width" format="dimension"></attr>
</declare-styleable>
</resources>
2.繼承listview實現我們自己想要的效果~
(1)第一步在構造方法裡獲取自定義的寬度(右邊區域性隱藏的寬度)
- public SlidingItemListView(Context context, AttributeSet attrs) {
- super(context, attrs);
- TypedArray typedArray = context.obtainStyledAttributes(attrs,
- R.styleable.slidingitemlistview);
- mRightViewWidth = (int) typedArray.getDimension(
- R.styleable.slidingitemlistview_right_width, 200);
- typedArray.recycle();
- }
public SlidingItemListView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.slidingitemlistview);
mRightViewWidth = (int) typedArray.getDimension(
R.styleable.slidingitemlistview_right_width, 200);
typedArray.recycle();
}
(2)重寫onInterceptTouchEvent()和onTouchEvent()方法,在ACTION_DOWN裡獲取mCurrentItemView,mPreItemView,mFirstX,mFirstY等。ACTION_UP裡對是否在展示做簡單的判斷,在顯示則隱藏。
[java] view plain copy print?- @Override
- publicboolean onInterceptTouchEvent(MotionEvent ev) {
- float lastX = ev.getX();
- float lastY = ev.getY();
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mIsHorizontal = null;
- mFirstX = lastX;
- mFirstY = lastY;
- int position = pointToPosition((int) mFirstX, (int) mFirstY);
- if (position >= 0) {
- View view = getChildAt(position - getFirstVisiblePosition());
- mPreItemView = mCurrentItemView;
- mCurrentItemView = view;
- }
- Log.i(”TAG”, “onInterceptTouchEvent—–>ACTION_DOWN”);
- break;
- case MotionEvent.ACTION_MOVE:
- break;
- case MotionEvent.ACTION_UP:
- Log.i(”TAG”, “onInterceptTouchEvent—–>ACTION_UP”);
- /**點選隱藏佈局會執行MotionEvent.ACTION_UP*/
- if (mIsShown) {
- hideRightView(mCurrentItemView);
- }
- break;
- default:
- break;
- }
- returnsuper.onInterceptTouchEvent(ev);
- }
- @Override
- publicboolean onTouchEvent(MotionEvent ev) {
- float lastX = ev.getX();
- float lastY = ev.getY();
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- Log.i(”TAG”, “onTouchEvent—->ACTION_DOWN”);
- break;
- case MotionEvent.ACTION_MOVE:
- float dx = lastX - mFirstX;
- float dy = lastY - mFirstY;
- Log.i(”TAG”, “onTouchEvent—->ACTION_MOVE”);
- if (mIsHorizontal == null) {
- if (!judgeScrollDirection(dx, dy)) {
- // 沒判斷出方向
- break;
- }
- }
- if (mIsHorizontal) {
- if (mIsShown&&mPreItemView!=mCurrentItemView) {
- //正在展示,前檢視不等於後檢視
- //則隱藏前檢視
- hideRightView(mPreItemView);
- }
- // 在mPreItemView!=mCurrentItemView執行 顯示隱藏的寬度
- if (dx < 0 && dx > -mRightViewWidth) {
- Log.i(”TAG”, “onTouchEvent—->MOVE -dx=” + -dx);
- mCurrentItemView.scrollTo((int) (-dx), 0);
- }
- // return true;
- } else {
- if (mIsShown) {
- //豎直方向滾動
- //則隱藏前檢視
- hideRightView(mPreItemView);
- }
- }
- break;
- case MotionEvent.ACTION_UP:
- if (mIsShown) {
- //點選時如果有在顯示的View
- //則隱藏前檢視
- Log.i(”TAG”, “MotionEvent.ACTION_UP 隱藏前檢視”);
- // hideRightView(mCurrentItemView);
- hideRightView(mPreItemView);
- }
- if (mIsHorizontal != null && mIsHorizontal) {
- if (mFirstX - lastX > mRightViewWidth / 2) {
- showRight(mCurrentItemView);
- } else {
- // 不到一半則隱藏
- hideRightView(mCurrentItemView);
- }
- Log.i(”TAG”, “成功接管OnTouchEvent CANCLE return TRUE”);
- returntrue;
- }
- break;
- default:
- break;
- }
- returnsuper.onTouchEvent(ev);
- }
- /**
- * 展示隱藏的佈局
- * @param mCurrentItemView2
- */
- privatevoid showRight(View mCurrentItemView2) {
- mCurrentItemView2.scrollTo(mRightViewWidth, 0);
- mIsShown = true;
- }
- /**隱藏佈局*/
- privatevoid hideRightView(View mCurrentItemView2) {
- mCurrentItemView2.scrollTo(0, 0);
- mIsShown = false;
- }
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
float lastX = ev.getX();
float lastY = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mIsHorizontal = null;
mFirstX = lastX;
mFirstY = lastY;
int position = pointToPosition((int) mFirstX, (int) mFirstY);
if (position >= 0) {
View view = getChildAt(position - getFirstVisiblePosition());
mPreItemView = mCurrentItemView;
mCurrentItemView = view;
}
Log.i("TAG", "onInterceptTouchEvent----->ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
Log.i("TAG", "onInterceptTouchEvent----->ACTION_UP");
/**點選隱藏佈局會執行MotionEvent.ACTION_UP*/
if (mIsShown) {
hideRightView(mCurrentItemView);
}
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
float lastX = ev.getX();
float lastY = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("TAG", "onTouchEvent---->ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
float dx = lastX - mFirstX;
float dy = lastY - mFirstY;
Log.i("TAG", "onTouchEvent---->ACTION_MOVE");
if (mIsHorizontal == null) {
if (!judgeScrollDirection(dx, dy)) {
// 沒判斷出方向
break;
}
}
if (mIsHorizontal) {
if (mIsShown&&mPreItemView!=mCurrentItemView) {
//正在展示,前檢視不等於後檢視
//則隱藏前檢視
hideRightView(mPreItemView);
}
// 在mPreItemView!=mCurrentItemView執行 顯示隱藏的寬度
if (dx < 0 && dx > -mRightViewWidth) {
Log.i("TAG", "onTouchEvent---->MOVE -dx=" + -dx);
mCurrentItemView.scrollTo((int) (-dx), 0);
}
// return true;
} else {
if (mIsShown) {
//豎直方向滾動
//則隱藏前檢視
hideRightView(mPreItemView);
}
}
break;
case MotionEvent.ACTION_UP:
if (mIsShown) {
//點選時如果有在顯示的View
//則隱藏前檢視
Log.i("TAG", "MotionEvent.ACTION_UP 隱藏前檢視");
// hideRightView(mCurrentItemView);
hideRightView(mPreItemView);
}
if (mIsHorizontal != null && mIsHorizontal) {
if (mFirstX - lastX > mRightViewWidth / 2) {
showRight(mCurrentItemView);
} else {
// 不到一半則隱藏
hideRightView(mCurrentItemView);
}
Log.i("TAG", "成功接管OnTouchEvent CANCLE return TRUE");
return true;
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 展示隱藏的佈局
* @param mCurrentItemView2
*/
private void showRight(View mCurrentItemView2) {
mCurrentItemView2.scrollTo(mRightViewWidth, 0);
mIsShown = true;
}
/**隱藏佈局*/
private void hideRightView(View mCurrentItemView2) {
mCurrentItemView2.scrollTo(0, 0);
mIsShown = false;
}
這裡面涉及到一個方法judgeScrollDirection,判斷滑動方向,我是這麼判斷的
[java] view plain copy print?- <span style=“white-space:pre”> </span>/**
- * @param 水平距離差
- * @param 豎直距離差
- * @return 水平滑動或者豎直滑動都返回true 沒有判斷出滑動方向則返回false
- */
- privateboolean judgeScrollDirection(float dx, float dy) {
- if (Math.abs(dx) > 30 && Math.abs(dx) > Math.abs(dy) * 2) {
- mIsHorizontal = true;
- returntrue;
- }
- if (Math.abs(dy) > 30 && Math.abs(dy) > Math.abs(dx) * 2) {
- mIsHorizontal = false;
- returntrue;
- }
- returnfalse;
- }
<span style="white-space:pre"> </span>/**
* @param 水平距離差
* @param 豎直距離差
* @return 水平滑動或者豎直滑動都返回true 沒有判斷出滑動方向則返回false
*/
private boolean judgeScrollDirection(float dx, float dy) {
if (Math.abs(dx) > 30 && Math.abs(dx) > Math.abs(dy) * 2) {
mIsHorizontal = true;
return true;
}
if (Math.abs(dy) > 30 && Math.abs(dy) > Math.abs(dx) * 2) {
mIsHorizontal = false;
return true;
}
return false;
}
(3)啊,最後還有一個get setRightViewWidth方法不要我忘了,後面例項化adapter時還要用 [java] view plain copy print?
- <span style=“white-space:pre”> </span>publicint getRightViewWidth() {
- return mRightViewWidth;
- }
- publicvoid setRightViewWidth(int mRightViewWidth) {
- this.mRightViewWidth = mRightViewWidth;
- }
<span style="white-space:pre"> </span>public int getRightViewWidth() {
return mRightViewWidth;
}
public void setRightViewWidth(int mRightViewWidth) {
this.mRightViewWidth = mRightViewWidth;
}
自定義listview到此就大功告成了,是不是直接就可以使用了呢?我很負責任的告訴你:絕對不可以!adapter表示自己不樂意!
下面就來寫一個adapter吧。繼承BaseAdapter重寫getCount,getItem,getItemId,getView。當然最重要的是getView。這些比較簡單,直接貼程式碼了
[java] view plain copy print?- private Context mContext;
- private LayoutInflater mInflater;
- private List<SlidingItembean> list;
- privateint mRightViewWidth;
- public SlidingItemListViewAdapter(Context mContext,
- List<SlidingItembean> list, int mRightViewWidth) {
- super();
- this.mContext = mContext;
- this.list = list;
- this.mRightViewWidth = mRightViewWidth;
- mInflater = LayoutInflater.from(mContext);
- }
- @Override
- publicint getCount() {
- // TODO Auto-generated method stub
- return list.size();
- }
- @Override
- public Object getItem(int position) {
- // TODO Auto-generated method stub
- return list.get(position);
- }
- @Override
- publiclong getItemId(int position) {
- // TODO Auto-generated method stub
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- ViewHolder viewHolder;
- onClick listener;
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.item_sliding_listview,
- null);
- viewHolder = new ViewHolder();
- listener = new onClick();// 例項化
- viewHolder.Re_left = (RelativeLayout) convertView
- .findViewById(R.id.Re_left);
- viewHolder.ll_right = (LinearLayout) convertView
- .findViewById(R.id.ll_right);
- viewHolder.num = (TextView) convertView
- .findViewById(R.id.tv_num_Re_left);
- viewHolder.name = (TextView) convertView
- .findViewById(R.id.tv_name_Re_left);
- viewHolder.path = (TextView) convertView
- .findViewById(R.id.tv_path_Re_left);
- viewHolder.play = (ImageView) convertView
- .findViewById(R.id.img_play_Re_left);
- viewHolder.setTop= (TextView) convertView.findViewById(R.id.tv_setTop);
- viewHolder.ll_delete = (LinearLayout) convertView
- .findViewById(R.id.ll_delete_ll_right);
- viewHolder.ll_setTop = (LinearLayout) convertView
- .findViewById(R.id.ll_setTop_ll_right);
- viewHolder.ll_setTop.setOnClickListener(listener);// 監聽
- viewHolder.ll_delete.setOnClickListener(listener);// 監聽
- viewHolder.play.setOnClickListener(listener);// 監聽
- convertView.setTag(viewHolder.play.getId(), listener);// 設定tag
- convertView.setTag(viewHolder);
- } else {
- viewHolder = (ViewHolder) convertView.getTag();
- listener = (onClick) convertView.getTag(viewHolder.play.getId());// 獲取例項
- }
- listener.setPosition(position);// 傳遞position
- // 設定佈局引數
- LayoutParams lp_left = new LayoutParams(
- android.widget.LinearLayout.LayoutParams.MATCH_PARENT,
- android.widget.LinearLayout.LayoutParams.MATCH_PARENT);
- viewHolder.Re_left.setLayoutParams(lp_left);
- LayoutParams lp_right = new LayoutParams(mRightViewWidth,
- android.widget.LinearLayout.LayoutParams.MATCH_PARENT);
- viewHolder.ll_right.setLayoutParams(lp_right);
- SlidingItembean slidingItembean = list.get(position);
- viewHolder.num.setText(slidingItembean.getNum());
- viewHolder.name.setText(slidingItembean.getName());
- viewHolder.path.setText(slidingItembean.getPath());
- viewHolder.setTop.setText(slidingItembean.getSetTop());
- return convertView;
- }
private Context mContext;
private LayoutInflater mInflater;
private List<SlidingItembean> list;
private int mRightViewWidth;
public SlidingItemListViewAdapter(Context mContext,
List<SlidingItembean> list, int mRightViewWidth) {
super();
this.mContext = mContext;
this.list = list;
this.mRightViewWidth = mRightViewWidth;
mInflater = LayoutInflater.from(mContext);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.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) {
ViewHolder viewHolder;
onClick listener;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_sliding_listview,
null);
viewHolder = new ViewHolder();
listener = new onClick();// 例項化
viewHolder.Re_left = (RelativeLayout) convertView
.findViewById(R.id.Re_left);
viewHolder.ll_right = (LinearLayout) convertView
.findViewById(R.id.ll_right);
viewHolder.num = (TextView) convertView
.findViewById(R.id.tv_num_Re_left);
viewHolder.name = (TextView) convertView
.findViewById(R.id.tv_name_Re_left);
viewHolder.path = (TextView) convertView
.findViewById(R.id.tv_path_Re_left);
viewHolder.play = (ImageView) convertView
.findViewById(R.id.img_play_Re_left);
viewHolder.setTop= (TextView) convertView.findViewById(R.id.tv_setTop);
viewHolder.ll_delete = (LinearLayout) convertView
.findViewById(R.id.ll_delete_ll_right);
viewHolder.ll_setTop = (LinearLayout) convertView
.findViewById(R.id.ll_setTop_ll_right);
viewHolder.ll_setTop.setOnClickListener(listener);// 監聽
viewHolder.ll_delete.setOnClickListener(listener);// 監聽
viewHolder.play.setOnClickListener(listener);// 監聽
convertView.setTag(viewHolder.play.getId(), listener);// 設定tag
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
listener = (onClick) convertView.getTag(viewHolder.play.getId());// 獲取例項
}
listener.setPosition(position);// 傳遞position
// 設定佈局引數
LayoutParams lp_left = new LayoutParams(
android.widget.LinearLayout.LayoutParams.MATCH_PARENT,
android.widget.LinearLayout.LayoutParams.MATCH_PARENT);
viewHolder.Re_left.setLayoutParams(lp_left);
LayoutParams lp_right = new LayoutParams(mRightViewWidth,
android.widget.LinearLayout.LayoutParams.MATCH_PARENT);
viewHolder.ll_right.setLayoutParams(lp_right);
SlidingItembean slidingItembean = list.get(position);
viewHolder.num.setText(slidingItembean.getNum());
viewHolder.name.setText(slidingItembean.getName());
viewHolder.path.setText(slidingItembean.getPath());
viewHolder.setTop.setText(slidingItembean.getSetTop());
return convertView;
}
[java] view plain copy print?- staticclass ViewHolder {
- RelativeLayout Re_left;
- LinearLayout ll_right;
- LinearLayout ll_delete;
- LinearLayout ll_setTop;
- TextView num;
- TextView name;
- TextView path;
- ImageView play;
- TextView setTop;
- }
- }
static class ViewHolder {
RelativeLayout Re_left;
LinearLayout ll_right;
LinearLayout ll_delete;
LinearLayout ll_setTop;
TextView num;
TextView name;
TextView path;
ImageView play;
TextView setTop;
}
}
細心的同學可能會發現onClick 物件,listener。這個listener是幹什麼的呢?原來啊這是個繼承OnClickListener的類,目的和ViewHolder一樣,複用item。以前只是複用item控制元件,這下連監聽事件都可以複用了,嘿嘿。程式碼是不會騙人的,來看看這個Onclick類吧
[java] view plain copy print?- class onClick implements OnClickListener {
- int position;
- publicvoid setPosition(int position) {
- this.position = position;
- }
- @Override
- publicvoid onClick(View v) {
- switch (v.getId()) {
- case R.id.img_play_Re_left:
- Toast.makeText(mContext, ”play—>position=” + position,
- Toast.LENGTH_SHORT).show();
- break;
- case R.id.ll_delete_ll_right:
- list.remove(position);
- SlidingItemListViewAdapter.this.notifyDataSetChanged();
- break;
- case R.id.ll_setTop_ll_right:
- if (mySetTopInterface!=null) {
- mySetTopInterface.Onclick_ll_setTop_ll_right(v,position);
- }else {
- Toast.makeText(mContext, ”mySetTopInterface==null”,
- Toast.LENGTH_SHORT).show();
- }
- break;
- default:
- break;
- }
- }
- }
class onClick implements OnClickListener {
int position;
public void setPosition(int position) {
this.position = position;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.img_play_Re_left:
Toast.makeText(mContext, "play--->position=" + position,
Toast.LENGTH_SHORT).show();
break;
case R.id.ll_delete_ll_right:
list.remove(position);
SlidingItemListViewAdapter.this.notifyDataSetChanged();
break;
case R.id.ll_setTop_ll_right:
if (mySetTopInterface!=null) {
mySetTopInterface.Onclick_ll_setTop_ll_right(v,position);
}else {
Toast.makeText(mContext, "mySetTopInterface==null",
Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
}
這裡用到了一個自己定義的介面MySetTopInterface,作用顯而易見,設定置頂的時候呼叫此介面,傳遞兩個引數,一個是被點選的View,另一個是position。
[java] view plain copy print?- MySetTopInterface mySetTopInterface;
- publicinterface MySetTopInterface {
- void Onclick_ll_setTop_ll_right(View view,int position);
- }
- publicvoid setMySetTopInterface(MySetTopInterface mySetTopInterface) {
- this.mySetTopInterface = mySetTopInterface;
- }
MySetTopInterface mySetTopInterface;
public interface MySetTopInterface {
void Onclick_ll_setTop_ll_right(View view,int position);
}
public void setMySetTopInterface(MySetTopInterface mySetTopInterface) {
this.mySetTopInterface = mySetTopInterface;
}
adapter表示自己作用已完成,等待領導指示!
領導表示listview的item佈局忘貼上來了,,,
下面貼item_sliding_listview佈局,,,
- <?xmlversion=“1.0”encoding=“utf-8”?>
- <LinearLayoutxmlns:android=“http://schemas.android.com/apk/res/android”
- android:layout_width=“match_parent”
- android:layout_height=“55dp”
- android:background=“#fff”
- android:orientation=“horizontal”>
- <RelativeLayout
- android:id=“@+id/Re_left”
- android:layout_width=“match_parent”
- android:layout_height=“match_parent”>
- <TextView
- android:id=“@+id/tv_num_Re_left”
- android:layout_width=“20dp”
- android:layout_height=“20dp”
- android:layout_centerVertical=“true”
- android:layout_marginLeft=“10dp”
- android:layout_marginRight=“10dp”
- android:background=“@drawable/tv_num_bg”
- android:gravity=“center”
- android:text=“1”
- android:textColor=“#fff”
- android:textSize=“12sp”/>
- <RelativeLayout
- android:layout_width=“match_parent”
- android:layout_height=“wrap_content”
- android:layout_centerVertical=“true”
- android:layout_toRightOf=“@id/tv_num_Re_left”>
- <TextView
- android:id=“@+id/tv_name_Re_left”
- android:layout_width=“match_parent”
- android:layout_height=“wrap_content”
- android:layout_marginBottom=“5dp”
- android:text=“《好久不見》”
- android:textColor=“#000”
- android:textSize=“16sp”/>
- <TextView
- android:id=“@+id/tv_path_Re_left”
- android:layout_width=“match_parent”
- android:layout_height=“wrap_content”
- android:layout_below=“@id/tv_name_Re_left”
- android:text=“/var/mobile/Contalners/Application”
- android:textSize=“10sp”/>
- </RelativeLayout>
- <ImageView
- android:id=“@+id/img_play_Re_left”
- android:layout_width=“30dp”
- android:layout_height=“30dp”
- android:layout_alignParentRight=“true”
- android:layout_centerVertical=“true”
- android:layout_marginRight=“10dp”
- android:scaleType=“fitXY”
- android:src=“@drawable/wechat_icon”/>
- </RelativeLayout>
- <LinearLayout
- android:id=“@+id/ll_right”
- android:layout_width=“wrap_content”
- android:layout_height=“match_parent”
- android:orientation=“horizontal”>
- <LinearLayout
- android:id=“@+id/ll_delete_ll_right”
- android:layout_width=“0dp”
- android:layout_height=“match_parent”
- android:layout_weight=“1”
- android:background=“#F77D48”
- android:gravity=“center”
- android:orientation=“vertical”
- android:padding=“5dp”>
- <ImageView
- android:layout_width=“30dp”
- android:layout_height=“30dp”
- android:scaleType=“fitXY”
- android:src=“@drawable/del_icon_normal”/>