侧滑菜单如同QQ往左侧滑动,可以删除对应的消息记录,如下图所示:
item_content.xml
item_menu.xml
item_main.xml
activity_main.xml
MainActivity.java
public class MainActivity extends AppCompatActivity {
//实例化
private ListView lv_main;
private ArrayList myBeens; //准备数据
private MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化
lv_main = (ListView) findViewById(R.id.lv_main);
//设置适配器
//准备数据
myBeens = new ArrayList<>();
for (int i = 0;i<100;i++){
myBeens.add(new MyBean("Content" + i));
}
//设置适配器
myAdapter = new MyAdapter();
lv_main.setAdapter(myAdapter);
}
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return myBeens.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
convertView = View.inflate(MainActivity.this,R.layout.item_main,null);
viewHolder = new ViewHolder();
viewHolder.item_content = (TextView) convertView.findViewById(R.id.item_content);
viewHolder.item_menu = (TextView) convertView.findViewById(R.id.item_menu);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
//根据位置得到内容
final MyBean myBean = myBeens.get(position);
viewHolder.item_content.setText(myBean.getName());
//点击item_content事件
viewHolder.item_content.setOnClickListener(new View.OnClickListener() { //监听写在里面
@Override
public void onClick(View v) {
MyBean myBean1 = myBeens.get(position);
Toast.makeText(MainActivity.this, myBean1.getName(), Toast.LENGTH_SHORT).show();
}
});
//点击item_menu删除事件
viewHolder.item_menu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SlideLayout slideLayout = (SlideLayout) v.getParent();
slideLayout.closeMeun();
myBeens.remove(myBean);
// myAdapter.notifyDataSetChanged();//刷新
notifyDataSetChanged(); //刷新,功能同上面的代码
}
});
SlideLayout slideLayout = (SlideLayout) convertView;
slideLayout.setOnStateChangeListenter(new MyOnStateChangeListenter()); //监听写在外面
return convertView;
}
}
private SlideLayout slideLayout;
class MyOnStateChangeListenter implements SlideLayout.OnStateChangeListenter {
@Override
public void onClose(SlideLayout layout) {
if (slideLayout == layout){
slideLayout = null;
}
}
@Override
public void onDown(SlideLayout layout) {
if (slideLayout != null && slideLayout != null){
slideLayout.closeMeun(); //优先把打开的关闭
}
}
@Override
public void onOpen(SlideLayout layout) {
slideLayout = layout;
}
}
static class ViewHolder{
TextView item_content;
TextView item_menu;
}
}
MyBean.java
public class MyBean {
private String name;
public MyBean(String name) { //生成构造器
this.name = name;
}
//Getter和Setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
SlideLayout.java
/**
* 作用:测滑菜单item
*/
public class SlideLayout extends FrameLayout {
private static final String TAG = SlideLayout.class.getSimpleName(); //得到类名SlideLayout
private View contentView;
private View menuView;
/**
* 滚动器
*/
private Scroller scroller;
/**
* Content的宽
*/
private int contentWidth;
private int menuWidth;
private int viewHeight; //他们的高都是相同的
public SlideLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
scroller = new Scroller(context);
}
/**
* 当布局文件加载完成的时候回调这个方法
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
contentView = getChildAt(0);
menuView = getChildAt(1);
}
/**
* 在测量方法里,得到各个控件的高和宽
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
contentWidth = contentView.getMeasuredWidth();
menuWidth = menuView.getMeasuredWidth();
viewHeight = getMeasuredHeight();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
menuView.layout(contentWidth,0,contentWidth+menuWidth,viewHeight); //默认把Delete隐藏了
}
private float startX;
private float startY;
private float downX; //只赋值一次
private float downY;
//触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.e(TAG,"SlideLayout-onTouchEvent-ACTION_DOWN");
//1.按下记录坐标
downX = startX = event.getX();
downY = startY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG,"SlideLayout-onTouchEvent-ACTION_MOVE");
//2.记录结束值
float endX = event.getX();
float endY = event.getY();
//3.计算偏移量
float distanceX = endX - startX;
int toScrollX = (int) (getScrollX() - distanceX);
//屏蔽非法值
if (toScrollX < 0){
toScrollX = 0;
}else if (toScrollX > menuWidth){
toScrollX = menuWidth;
}
scrollTo(toScrollX,getScrollY());
//重新赋值
startX = event.getX();
startY = event.getY();
//在X轴和Y轴滑动的距离
float DX = Math.abs(endX - downX);
float DY = Math.abs(endY - downY);
if (DX > DY && DX > 8){ //8是像素
//水平方向滑动
//响应测滑
//反拦截---事件给SlideLayout
getParent().requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_UP:
Log.e(TAG,"SlideLayout-onTouchEvent-ACTION_UP");
/**
* 回弹
*/
int totalScrollX = getScrollX(); //偏移量
if (totalScrollX < menuWidth/2){
//关闭 Menu
closeMeun();
}else {
//打开 Menu
openMenu();
}
break;
}
return true;
}
/**
* true:拦截孩子的事件,但会执行当前控件的onTouchEvent()方法
* false:不拦截孩子的事件,事件继续传递
* @param ev
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false; //默认是传给孩子
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
//1.按下记录坐标
downX = startX = ev.getX();
Log.e(TAG,"SlideLayout-onTouchEvent-ACTION_DOWN");
if (onStateChangeListenter != null){
onStateChangeListenter.onDown(this);
}
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG,"SlideLayout-onTouchEvent-ACTION_MOVE");
//2.记录结束值
float endX = ev.getX();
float endY = ev.getY();
//3.计算偏移量
float distanceX = endX - startX;
//重新赋值
startX = ev.getX();
//在X轴和Y轴滑动的距离
float DX = Math.abs(endX - downX);
if (DX > 8){ //8是像素
intercept = true; //拦截
}
break;
case MotionEvent.ACTION_UP:
break;
}
return intercept;
}
//打开menu
public void openMenu() {
// ----->menuWidth(目标
int distanceX = menuWidth - getScrollX();
scroller.startScroll(getScrollX(),getScrollY(),distanceX,getScrollY());
invalidate(); //强制刷新 会执行 onDraw()方法和computeScroll()方法
if (onStateChangeListenter != null){
onStateChangeListenter.onOpen(this);
}
}
//关闭menu
public void closeMeun() {
// ----->0(目标)代表隐藏Delete状态
int distanceX = 0 - getScrollX();
scroller.startScroll(getScrollX(),getScrollY(),distanceX,getScrollY());
invalidate(); //强制刷新 会执行 onDraw()方法和computeScroll()方法
if (onStateChangeListenter != null){
onStateChangeListenter.onClose(this);
}
}
@Override
public void computeScroll() {
super.computeScroll();
if (scroller.computeScrollOffset()){
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate(); //强制刷新
}
}
/**
* 1.监听SlideLayout状态的改变(接口)
*/
public interface OnStateChangeListenter{
void onClose(SlideLayout layout);
void onDown(SlideLayout layout);
void onOpen(SlideLayout layout);
}
//2.外界实例化出来,来方便接受
private OnStateChangeListenter onStateChangeListenter;
/**
* 设置SlideLayout状态的监听
* @param onStateChangeListenter
*/
public void setOnStateChangeListenter(OnStateChangeListenter onStateChangeListenter) { //3.Setter方法
this.onStateChangeListenter = onStateChangeListenter;
}
}