第一次写博客,先说下大概思路吧~
要显示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,设置好自定义属性(其实就是右边隐藏布局的宽度啦),代码很简单,直接贴上来了
- <?xml version=“1.0” encoding=“utf-8”?>
- <resources>
- <declare-styleable name=“slidingitemlistview”>
- <attr name=“right_width” format=“dimension”></attr>
- </declare-styleable>
- </resources>
<?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里对是否在展示做简单的判断,在显示则隐藏。
- @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;
- }
@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,判断滑动方向,我是这么判断的
- <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;
- }
<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时还要用
- <span style=“white-space:pre”> </span>public int getRightViewWidth() {
- return mRightViewWidth;
- }
- public void 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。这些比较简单,直接贴代码了
- 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;
- }
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;
}
- 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;
- }
- }
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类吧
- 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;
- }
- }
- }
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。
- MySetTopInterface mySetTopInterface;
- public interface MySetTopInterface {
- void Onclick_ll_setTop_ll_right(View view,int position);
- }
- public void 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布局,,,
- <?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=“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” />
- <TextView
- android:layout_width=“wrap_content”
- android:layout_height=“wrap_content”
- android:text=“删除”
- android:textColor=“#fff”
- android:textSize=“16sp” />
- </LinearLayout>
- <LinearLayout
- android:id=“@+id/ll_setTop_ll_right”
- android:layout_width=“0dp”
- android:layout_height=“match_parent”
- android:layout_weight=“1”
- android:background=“#FED33F”
- android:gravity=“center”
- android:orientation=“vertical”
- android:padding=“5dp” >
- <ImageView
- android:layout_width=“30dp”
- android:layout_height=“30dp”
- android:scaleType=“fitXY”
- android:src=“@drawable/qq_icon” />
- <TextView
- android:id=“@+id/tv_setTop”
- android:layout_width=“wrap_content”
- android:layout_height=“wrap_content”
- android:text=“置顶”
- android:textColor=“#fff”
- android:textSize=“12sp” />
- </LinearLayout>
- </LinearLayout>
- </LinearLayout>
<?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="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" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除"
android:textColor="#fff"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_setTop_ll_right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FED33F"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp" >
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="fitXY"
android:src="@drawable/qq_icon" />
<TextView
android:id="@+id/tv_setTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="置顶"
android:textColor="#fff"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
至此,listview的初始化算完事了。
下面来看看怎么应用吧(实现item置顶,取消置顶)
(1)在activity_main.xml里添加自定义的listview。其中 xmlns:dyk=”http://schemas.Android.com/apk/res/com.example.qqslidingitem”为自定义命名空间
- <com.example.qqslidingitem.SlidingItemListView
- xmlns:dyk=“http://schemas.android.com/apk/res/com.example.qqslidingitem”
- android:id=“@+id/listview”
- android:layout_width=“match_parent”
- android:layout_height=“match_parent”
- android:background=“#fff4f7f9”
- android:cacheColorHint=“#00000000”
- android:divider=“#dddbdb”
- android:dividerHeight=“1dp”
- dyk:right_width=“120dp” />
<com.example.qqslidingitem.SlidingItemListView
xmlns:dyk="http://schemas.android.com/apk/res/com.example.qqslidingitem"
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff4f7f9"
android:cacheColorHint="#00000000"
android:divider="#dddbdb"
android:dividerHeight="1dp"
dyk:right_width="120dp" />
(2)接下来就该实现刚留的MySetTopInterface接口,复写Onclick_ll_setTop_ll_right方法。(初始化工作直接贴代码)
- <span style=“white-space:pre”> </span>private SlidingItemListView mListView;
- private SlidingItemListViewAdapter adapter;
- private List<SlidingItembean> list = new ArrayList<SlidingItembean>();
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- initView();
- initData();
- initEvent();
- }
- private void initEvent() {
- adapter = new SlidingItemListViewAdapter(MainActivity.this, list,
- mListView.getRightViewWidth());
- mListView.setAdapter(adapter);
- adapter.setMySetTopInterface(this);
- // mListView.setSelection(position);
- mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view,
- int position, long id) {
- Toast.makeText(MainActivity.this,
- ”item onclick ” + list.get(position).getNum(),
- Toast.LENGTH_SHORT).show();
- }
- });
- }
- private void initData() {
- for (int i = 0; i < 50; i++) {
- SlidingItembean slidingItembean = null;
- if (i % 3 == 0) {
- slidingItembean = new SlidingItembean(String.valueOf(i),
- ”你会不会忽然的出现”, “/var/mobile/Contalners/Application”,
- ”置顶”);
- } else if (i % 3 == 1) {
- slidingItembean = new SlidingItembean(String.valueOf(i),
- ”在街角的咖啡店”, “/var/mobile/Contalners/Application”,
- ”置顶”);
- } else {
- slidingItembean = new SlidingItembean(String.valueOf(i),
- ”我会带着笑脸,和你,坐着聊聊天”, “/var/mobile/Contalners/Application”,
- ”置顶”);
- }
- list.add(slidingItembean);
- }
- }
- /**
- * 初始化界面
- */
- private void initView() {
- mListView = (SlidingItemListView) findViewById(R.id.listview);
- }
<span style="white-space:pre"> </span>private SlidingItemListView mListView;
private SlidingItemListViewAdapter adapter;
private List<SlidingItembean> list = new ArrayList<SlidingItembean>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
initData();
initEvent();
}
private void initEvent() {
adapter = new SlidingItemListViewAdapter(MainActivity.this, list,
mListView.getRightViewWidth());
mListView.setAdapter(adapter);
adapter.setMySetTopInterface(this);
// mListView.setSelection(position);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(MainActivity.this,
"item onclick " + list.get(position).getNum(),
Toast.LENGTH_SHORT).show();
}
});
}
private void initData() {
for (int i = 0; i < 50; i++) {
SlidingItembean slidingItembean = null;
if (i % 3 == 0) {
slidingItembean = new SlidingItembean(String.valueOf(i),
"你会不会忽然的出现", "/var/mobile/Contalners/Application",
"置顶");
} else if (i % 3 == 1) {
slidingItembean = new SlidingItembean(String.valueOf(i),
"在街角的咖啡店", "/var/mobile/Contalners/Application",
"置顶");
} else {
slidingItembean = new SlidingItembean(String.valueOf(i),
"我会带着笑脸,和你,坐着聊聊天", "/var/mobile/Contalners/Application",
"置顶");
}
list.add(slidingItembean);
}
}
/**
* 初始化界面
*/
private void initView() {
mListView = (SlidingItemListView) findViewById(R.id.listview);
}
接下来重点完成置顶和取消置顶功能~
- @Override
- public void Onclick_ll_setTop_ll_right(View view, int position) {
- if (list.get(position).getSetTop().equals(“置顶”)) {
- setTop(position);
- } else if (list.get(position).getSetTop().equals(“取消置顶”)) {
- unSetTop(position);
- }
- }
@Override
public void Onclick_ll_setTop_ll_right(View view, int position) {
if (list.get(position).getSetTop().equals("置顶")) {
setTop(position);
} else if (list.get(position).getSetTop().equals("取消置顶")) {
unSetTop(position);
}
}
置顶setTop
- <span style=“white-space:pre”> </span>/**
- * 置顶
- * @param position
- */
- private void setTop(int position) {
- list.get(position).setSetTop(”取消置顶”);
- list.add(0, list.get(position));
- // 置顶后list.size增加一 所以要position+1
- list.remove(position + 1);
- adapter.notifyDataSetChanged();
- }
<span style="white-space:pre"> </span>/**
* 置顶
* @param position
*/
private void setTop(int position) {
list.get(position).setSetTop("取消置顶");
list.add(0, list.get(position));
// 置顶后list.size增加一 所以要position+1
list.remove(position + 1);
adapter.notifyDataSetChanged();
}
取消置顶我采用的策略是先遍历datalist,然后找到前一项比他小后一项比他大的位置然后插入。细心的同学会发现这样写有一个小小的bug要是选择项就是最小的没法处理,所以会有些特殊情况要单独拿出来讨论。
- <span style=“white-space:pre”> </span>/**
- * 取消置顶
- * @param position
- */
- private void unSetTop(int position) {
- boolean isAdd = false;
- /** 差值 */
- int min = 9999999;
- /** 当前position的数值 */
- int num;
- // 差值最小处的行数
- int j = 0;
- int num2 = 0;
- int jumpNum = 0;
- list.get(position).setSetTop(”置顶”);
- num = Integer.parseInt(list.get(position).getNum());
- // list长度为2特殊处理
- if (list.size() == 2) {
- // 第一行确定为取消置顶
- if (list.get(1).getSetTop().equals(“取消置顶”)) {
- if (position == 0) {
- if (num == 0) {
- list.add(2, list.get(position));
- }
- if (num == 1) {
- list.add(2, list.get(position));
- }
- list.remove(position);
- adapter.notifyDataSetChanged();
- } else {
- list.add(2, list.get(position));
- list.remove(position);
- adapter.notifyDataSetChanged();
- }
- } else {
- if (num == 0) {
- list.add(1, list.get(position));
- }
- if (num == 1) {
- list.add(2, list.get(position));
- }
- list.remove(position);
- adapter.notifyDataSetChanged();
- }
- } else {
- for (int i = 0; i < list.size(); i++) {
- if (num > Integer.parseInt(list.get(i).getNum())
- && num < Integer.parseInt(list.get(i + 1).getNum())) {
- list.add(i + 1, list.get(position));
- isAdd = true;
- break;
- }
- }
- // 如果没有比自己小的值 例如0 则isAdd=false
- // 遍历list 寻找差值最小的地方插入list
- if (!isAdd) {
- for (int i = 0; i < list.size(); i++) {
- if (i == position || list.get(i).getSetTop().equals(“取消置顶”)) {
- // 排除与自身相比较
- // 排除置顶item比较
- Log.i(”TAG”, “调过” + i);
- jumpNum++;
- if (jumpNum == list.size()) {
- j = list.size();
- }
- continue;
- }
- num2 = Integer.parseInt(list.get(i).getNum());
- if (num2 - num < min) {
- min = num2 - num;
- // 记录行号
- j = i;
- Log.i(”TAG”, “插入行数J=” + j);
- }
- }
- // 遍历完成后拿到差值min
- int number = min + num;
- list.add(j, list.get(position));
- Log.i(”TAG”, “*********插入行数J=” + j);
- }
- list.remove(position);
- adapter.notifyDataSetChanged();
- }
- }
<span style="white-space:pre"> </span>/**
* 取消置顶
* @param position
*/
private void unSetTop(int position) {
boolean isAdd = false;
/** 差值 */
int min = 9999999;
/** 当前position的数值 */
int num;
// 差值最小处的行数
int j = 0;
int num2 = 0;
int jumpNum = 0;
list.get(position).setSetTop("置顶");
num = Integer.parseInt(list.get(position).getNum());
// list长度为2特殊处理
if (list.size() == 2) {
// 第一行确定为取消置顶
if (list.get(1).getSetTop().equals("取消置顶")) {
if (position == 0) {
if (num == 0) {
list.add(2, list.get(position));
}
if (num == 1) {
list.add(2, list.get(position));
}
list.remove(position);
adapter.notifyDataSetChanged();
} else {
list.add(2, list.get(position));
list.remove(position);
adapter.notifyDataSetChanged();
}
} else {
if (num == 0) {
list.add(1, list.get(position));
}
if (num == 1) {
list.add(2, list.get(position));
}
list.remove(position);
adapter.notifyDataSetChanged();
}
} else {
for (int i = 0; i < list.size(); i++) {
if (num > Integer.parseInt(list.get(i).getNum())
&& num < Integer.parseInt(list.get(i + 1).getNum())) {
list.add(i + 1, list.get(position));
isAdd = true;
break;
}
}
// 如果没有比自己小的值 例如0 则isAdd=false
// 遍历list 寻找差值最小的地方插入list
if (!isAdd) {
for (int i = 0; i < list.size(); i++) {
if (i == position || list.get(i).getSetTop().equals("取消置顶")) {
// 排除与自身相比较
// 排除置顶item比较
Log.i("TAG", "调过" + i);
jumpNum++;
if (jumpNum == list.size()) {
j = list.size();
}
continue;
}
num2 = Integer.parseInt(list.get(i).getNum());
if (num2 - num < min) {
min = num2 - num;
// 记录行号
j = i;
Log.i("TAG", "插入行数J=" + j);
}
}
// 遍历完成后拿到差值min
int number = min + num;
list.add(j, list.get(position));
Log.i("TAG", "*********插入行数J=" + j);
}
list.remove(position);
adapter.notifyDataSetChanged();
}
}
大功告成!接下来做一个小总结吧。首先是自定义属性,其次是对布局隐藏的处理,第三是对getView中item的复用,最后是对自定义接口中删除,置顶,取消置顶功能实现的处理。第一次写的博客,不好的地方请谅解。