需求:如题,要做出类似QQ左滑删除的效果。
分析:Android中什么组件自带了水平滑动? 我首当其冲就想到HorizontalScrollView。既然是简单实现,那我们何方不继承一下HorizontalScrollView呢?
接下来我们将HorizontalScrollView分成ItemView + 抽屉部分。
我们只需要监听用户的滑动事件,当用户滑动超过指定距离时,就移动HorizontalScrollView,将隐藏的“抽屉部分”显示出来,当用户做相反的滑动时,隐藏“抽屉部分”即可。
GitHub下载地址:https://github.com/yanjunhui2014/SlidingDeleteView
需求分析已定,先给大家看效果。
各位看官是不是急不可耐的想看代码了,这就上:
package com.sliding.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.sliding.R;
/**
* 滑动删除widget
*
* @author Junhui
*/
public class SlidingDeleteView extends HorizontalScrollView {
private static final String TAG = "SlidingDeleteView";
/**
* 抽屉视图(注意:recyclerview/listview中不能使用button,button会抢夺焦点) - 父件
*/
private LinearLayout slidingParent;
/**
* 是否开启滑动抽屉
*/
public boolean isEnable = true;
/**
* 抽屉视图是否可见
*/
public boolean deleteViewVisibile = false; //
private boolean isFirst = true;
private OnDeleteViewStateChangedListener onStateChangedListener;//监听器
/**
* 抽屉视图状态变化回调接口
*/
public interface OnDeleteViewStateChangedListener {
void onVisibile();
void onGone();
void onDownOrMove();
}
public SlidingDeleteView(Context context) {
this(context, null);
}
public SlidingDeleteView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingDeleteView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (isFirst) {
init();
isFirst = false;
}
}
private void init() {
slidingParent = (LinearLayout) findViewById(R.id.lay_sliding);
}
public void setOnDeleteViewStateChangedListener(OnDeleteViewStateChangedListener onStateChangedListener) {
this.onStateChangedListener = onStateChangedListener;
}
public boolean isEnable() {
return isEnable;
}
public void setEnable(boolean enable) {
isEnable = enable;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
if (!isEnable) {
return false;
}
case MotionEvent.ACTION_DOWN:
if (onStateChangedListener != null) {
onStateChangedListener.onDownOrMove();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
measureScrollX();
return true;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 计算X轴滑动距离,并做出相应操作
*/
private void measureScrollX() {
if (getScrollX() < slidingParent.getWidth() / 3) {
//TODO 当滑动距离小于 抽屉视图宽度 * 1/3 时,隐藏删除视图
setDeleteViewGone();
} else {
setDeleteViewVisibile();
}
}
public void setDeleteViewGone() {
deleteViewVisibile = false;
this.smoothScrollTo(0, 0);
if (onStateChangedListener != null) {
onStateChangedListener.onGone();
}
}
public void setDeleteViewVisibile() {
Log.d(TAG, "抽屉的固定宽度为 == " + slidingParent.getWidth());
deleteViewVisibile = true;
this.smoothScrollTo(slidingParent.getWidth(), 0);
if (onStateChangedListener != null) {
onStateChangedListener.onVisibile();
}
}
}
package com.sliding;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.sliding.utils.ScreenUtils;
import com.sliding.widget.SlidingDeleteView;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
RecyclerView recyclerView;
MyAdapter myAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
myAdapter = new MyAdapter();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayout.VERTICAL));
recyclerView.setAdapter(myAdapter);
}
class MyAdapter extends RecyclerView.Adapter {
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(getBaseContext()).inflate(R.layout.sample_slidingview, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
//TODO 这里需要重新计算 item - containerView的宽度,否则containerView会显示错误(重要)
LinearLayout containerView = (LinearLayout) holder.slidingDeleteView.findViewById(R.id.lay_container);
containerView.getLayoutParams().width = ScreenUtils.getScreenWidth(getBaseContext());
holder.slidingDeleteView.setEnable(true);
holder.slidingDeleteView.setOnDeleteViewStateChangedListener(new SlidingDeleteView.OnDeleteViewStateChangedListener() {
@Override
public void onVisibile() {
Log.i(TAG, "显示抽屉视图");
}
@Override
public void onGone() {
Log.i(TAG, "隐藏抽屉视图");
}
@Override
public void onDownOrMove() {
}
});
holder.tvKey.setText("key");
holder.tvValue.setText("" + position);
holder.tvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getBaseContext(), "position == " + position + " onClick", Toast.LENGTH_LONG).show();
}
});
}
@Override
public int getItemCount() {
return 20;
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
SlidingDeleteView slidingDeleteView;
TextView tvKey;
TextView tvValue;
TextView tvDelete;
public MyViewHolder(View itemView) {
super(itemView);
slidingDeleteView = (SlidingDeleteView) itemView.findViewById(R.id.slidingview);
tvKey = (TextView) itemView.findViewById(R.id.tv_key);
tvValue = (TextView) itemView.findViewById(R.id.tv_value);
tvDelete = (TextView) itemView.findViewById(R.id.tv_delete);
}
}
}
github下载地址:https://github.com/yanjunhui2014/SlidingDeleteView