Android开发中HorizontalScrollView即可实现横向水平滑动,若想实现左滑弹出菜单,右滑隐藏菜单需要修改HorizontalScrollView默认滑动事件。假设菜单长度为100像素,即左滑View向右移动100像素,右滑View向左移动100像素。
核心代码如下:
SwipeScrollView 封装的滑动页
public class SwipeScrollView extends HorizontalScrollView {
private RelativeLayout container;//主内容容器
private LinearLayout operate;//操作子项容器
private int scrollWidth=0,scroll;//滚动距离
private boolean swipe = false;//是否滑动
private OnSwipeListener onSwipeListener;
public SwipeScrollView(Context context) {
super(context);
}
public SwipeScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
this.onSwipeListener = onSwipeListener;
}
/***
* 关闭菜单
*/
public void closeMenu(){
swipe = false;
scroll=0;
smoothScrollTo(0,0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
container = (RelativeLayout)findViewById(R.id.item_container);
operate = (LinearLayout)findViewById(R.id.item_operate);
//设置容器宽度
container.setLayoutParams(new LinearLayout.LayoutParams(ScreenHelper.getScreenWidth(getContext()), ViewGroup.LayoutParams.MATCH_PARENT));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
//滑动距离大于10弹出隐藏菜单
@Override
public boolean onTouchEvent(MotionEvent ev) {
if(MotionEvent.ACTION_DOWN==ev.getAction())
scroll=getScrollX();
else if(MotionEvent.ACTION_UP==ev.getAction()){
scroll = getScrollX()-scroll;
if(scroll>10 || scroll<-10){
scroll = swipe?0:scrollWidth;
swipe = !swipe;
if(onSwipeListener!=null)
onSwipeListener.onSwipe(swipe,SwipeScrollView.this);
}
else
scroll = swipe?scrollWidth:0;
//View移动动画
smoothScrollTo(scroll,0);
return true;
}
return super.onTouchEvent(ev);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//onMeasure计算后设置滑动的滚动宽度
scrollWidth = operate.getMeasuredWidth();
for(int i=0;i<operate.getChildCount();i++){
final int position = i;
operate.getChildAt(i).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//菜单点击事件
onSwipeListener.onMenuClick(position);
}
});
}
container.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//主内容点击事件 若菜单栏已打开关闭滑动菜单
if(swipe){
swipe = false;
if(onSwipeListener!=null)
onSwipeListener.onSwipe(swipe,SwipeScrollView.this);
}
else{
if(onSwipeListener!=null)
onSwipeListener.onClick();
}
}
});
super.onLayout(changed, l, t, r, b);
}
}
OnSwipeListener 滑动监听接口
/***
* 滑动菜单监听
*/
public interface OnSwipeListener {
/***
* 滑动
* @param swipe
* @param view
*/
void onSwipe(boolean swipe, View view);
/***
* 主内容点击
*/
void onClick();
/***
* 子菜单点击
* @param menuPosition
*/
void onMenuClick(int menuPosition);
}
OnItemClickListener RecyclerView子项单击接口
public interface OnItemClickListener {
void onItemClick(RecyclerView.ViewHolder viewHolder,int position);
}
OnMenuClickListener 菜单单击接口
public interface OnMenuClickListener {
void onMenuClick(SwipeScrollAdapter.ItemViewHolder viewHolder,int position, int operatePosition);
}
SwipeScrollAdapter 滑动页适配器
public class SwipeScrollAdapter extends RecyclerView.Adapter<SwipeScrollAdapter.ItemViewHolder>{
private List<PushMessage> mMessageList;
private int mLayout;
private int swipePosition=-1;
private View swipeView;
private OnItemClickListener onItemClickListener;
private OnMenuClickListener onMenuClickListener;
public void setOnMenuClickListener(OnMenuClickListener onMenuClickListener) {
this.onMenuClickListener = onMenuClickListener;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public SwipeScrollAdapter(int layout,List<PushMessage> messageList) {
mMessageList = messageList;
mLayout = layout;
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(mLayout, parent, false);
ItemViewHolder itemViewHolder = new ItemViewHolder(view);
return itemViewHolder;
}
/***
* 获取当前滑动菜单位置 -1没有滑动菜单
* @return
*/
public int getSwipePosition() {
return swipePosition;
}
/***
* 初始化当前菜单
* @param position
* @param view
*/
public void openMenu(int position,View view){
swipePosition = position;
swipeView = view;
}
/***
* 删除子项
* @param position 子项位置
*/
public void closeMenu(int position){
((SwipeScrollView)swipeView).closeMenu();
swipePosition=-1;
swipeView=null;
mMessageList.remove(position);
notifyItemRemoved(position);
}
/***
* 关闭当前滑动菜单
*/
public void closeMenu(){
((SwipeScrollView)swipeView).closeMenu();
swipePosition=-1;
swipeView=null;
}
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
//先执行自定义TouchListener事件,再执行SwipeScrollView的onTouchEvent事件
holder.swipeScrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//若未有滑动菜单或者滑动的菜单为当前菜单执行SwipeScrollView的onTouchEvent事件,否则关闭当前菜单
if (swipePosition == -1 || swipePosition ==holder.getAdapterPosition())
return false;
else {
closeMenu();
return true;
}
}
});
holder.swipeScrollView.setOnSwipeListener(new OnSwipeListener() {
//左滑弹出菜单,右滑隐藏菜单
@Override
public void onSwipe(boolean swipe, View view) {
if (swipe)
openMenu(holder.getAdapterPosition(), view);
else
closeMenu();
}
@Override
public void onClick() {
//其他菜单子项点击后关闭当前菜单
if (swipePosition != -1)
closeMenu();
else{
if(onItemClickListener!=null)
onItemClickListener.onItemClick(holder,holder.getAdapterPosition());
}
}
@Override
public void onMenuClick(int operatePosition) {
if(onMenuClickListener!=null){
onMenuClickListener.onMenuClick(holder,holder.getAdapterPosition(),operatePosition);
}
}
});
holder.read.setVisibility(mMessageList.get(position).isRead()?View.INVISIBLE:View.VISIBLE);
holder.text.setText(mMessageList.get(position).getContent());
holder.time.setText(DateHelper.toDate(mMessageList.get(position).getDate(),"HH:mm"));
}
@Override
public int getItemCount() {
return mMessageList.size();
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
public SwipeScrollView swipeScrollView;
public TextView text;
public TextView time;
public ImageView read;
public RelativeLayout container;
public ItemViewHolder(View itemView) {
super(itemView);
swipeScrollView = (SwipeScrollView)itemView.findViewById(R.id.scrollView);
read = (ImageView)itemView.findViewById(R.id.item_read);
text = (TextView)itemView.findViewById(R.id.item_text);
time = (TextView)itemView.findViewById(R.id.item_time);
container = (RelativeLayout)itemView.findViewById(R.id.item_container);
}
}
}
RoomFragment 实例页
public class RoomFragment extends BaseFragment {
private RecyclerView recyclerView;
private SwipeScrollAdapter adapter;
private List<PushMessage> messageList;
@Override
public void onUpdateView(Object data) {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recycyclerview, container, false);
messageList = new ArrayList<>();
messageList.add(new PushMessage(1,String.valueOf(0),"A区"+0,false,new Date()));
messageList.add(new PushMessage(1,String.valueOf(1),"A区"+1,false,new Date()));
for(int i=2;i<10;i++){
messageList.add(new PushMessage(1,String.valueOf(i),"A区"+i,true,new Date()));
}
adapter = new SwipeScrollAdapter(R.layout.fragment_room_item,messageList);
recyclerView = (RecyclerView)view.findViewById(R.id.list);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//recyclerView上下滑动执行,若当前菜单不为空关闭当前菜单
if (adapter.getSwipePosition() != -1) {
adapter.closeMenu();
return true;
}
return false;
}
});
//子项单击事件
adapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(RecyclerView.ViewHolder viewHolder, int position) {
startActivity(new Intent(getContext(), CheckActivity.class));
}
});
//子项菜单单击事件
adapter.setOnMenuClickListener(new OnMenuClickListener() {
@Override
public void onMenuClick(SwipeScrollAdapter.ItemViewHolder viewHolder, int position, int operatePosition) {
switch (operatePosition){
case 0:clean(viewHolder,position,operatePosition);break;
default:delete(position);break;
}
}
});
return view;
}
//未读改为已读
private void clean(SwipeScrollAdapter.ItemViewHolder viewHolder, int position, int operatePosition){
View menu = viewHolder.swipeScrollView.getChildAt(operatePosition);
menu.setClickable(false);
try {
Thread.sleep(2000);
}
catch (Exception e){
e.printStackTrace();
}
delete(position);
}
//删除
private void delete(int position){
adapter.closeMenu(position);
}
}
PushMessage 数据实体
public class PushMessage {
private int type;
private String id;
private String content;
private boolean read;
private Date date;
public PushMessage(){
}
public PushMessage(int type, String id, String content,boolean read, Date date) {
this.type = type;
this.id = id;
this.content = content;
this.date = date;
this.read = read;
}
public boolean isRead() {
return read;
}
public void setRead(boolean read) {
this.read = read;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
fragment_recycyclerview.xml 实例布局页
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
fragment_room_item.xml 实例菜单子项布局页
<?xml version="1.0" encoding="utf-8"?>
<com.room.control.scrollview.SwipeScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@id/scrollView"
android:scrollbars="none"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="60dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:orientation="horizontal"
android:id="@id/item_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_alignParentBottom="true"
android:background="@color/grey"
android:layout_width="match_parent"
android:layout_height="2px"/>
<ImageView
android:id="@id/item_read"
android:layout_marginTop="1dp"
android:visibility="visible"
android:background="@drawable/read"
android:layout_width="30dp"
android:layout_height="30dp" />
<LinearLayout
android:padding="10dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:id="@id/item_text"
android:textSize="20dp"
android:textColor="#555"
android:gravity="left|center"
android:layout_marginRight="50dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@id/item_time"
android:gravity="right|center"
android:layout_marginLeft="-40dp"
android:layout_width="40dp"
android:layout_height="match_parent" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:orientation="horizontal"
android:id="@id/item_operate"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<Button
android:id="@id/item_check"
android:text="@string/checked"
android:background="#fe9d00"
android:textColor="@color/white"
android:layout_width="80dp"
android:layout_height="match_parent" />
<Button
android:id="@id/item_delete"
android:text="@string/delete"
android:background="@color/orangered"
android:textColor="@color/white"
android:layout_width="80dp"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</com.room.control.scrollview.SwipeScrollView>