• Scroller应用:ListView滑动删除


    1、设计思路

    Scroller的应用--滑屏实现中使用Scroller实现滑屏效果,这里使用Scroller与ListView实现相似QQ滑动。然后点击删除功能。设计思路是Item使用Scroller实现滑动,ListView依据触摸推断是横向滑动还是竖直滑动。关于点击事件处理思路:对于View的onClick事件跟寻常一样,里面针对OnItemClick做了处理,推断触摸距离来推断。假设小于5的话,在Item的onTouchEvent方法中的MotionEvent.ACTION_UP里面返回false,这样ListView里面的dispatchTouchEvent的super.dispatchTouchEvent(event)就会返回false,依据x,y获取当前position以及点击的view。调用super.performItemClick(view, position, view.getId());来告诉ListView出发onItemClick事件。

    2、Item的代码

    package com.jwzhangjie.scrollview;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.LinearLayout;
    import android.widget.Scroller;
    
    public class ListItemDelete extends LinearLayout {
    
    	private Scroller mScroller;// 滑动控制
    	private float mLastMotionX;// 记住上次触摸屏的位置
    	private int deltaX;
    	private int back_width;
    	private float downX;
    
    	public ListItemDelete(Context context) {
    		this(context, null);
    	}
    
    	public ListItemDelete(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		init(context);
    	}
    
    	private void init(Context context) {
    		mScroller = new Scroller(context);
    	}
    
    	@Override
    	public void computeScroll() {
    		if (mScroller.computeScrollOffset()) {// 会更新Scroller中的当前x,y位置
    			scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    			postInvalidate();
    		}
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    		int count = getChildCount();
    		for (int i = 0; i < count; i++) {
    			measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
    			if (i == 1) {
    				back_width = getChildAt(i).getMeasuredWidth();
    			}
    		}
    
    	}
    
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		int action = event.getAction();
    		float x = event.getX();
    		switch (action) {
    		case MotionEvent.ACTION_DOWN:
    			Log.e("test", "item  ACTION_DOWN");
    			mLastMotionX = x;
    			downX = x;
    			break;
    		case MotionEvent.ACTION_MOVE:
    			Log.e("test", back_width + "  item  ACTION_MOVE  " + getScrollX());
    			deltaX = (int) (mLastMotionX - x);
    			mLastMotionX = x;
    			int scrollx = getScrollX() + deltaX;
    			if (scrollx > 0 && scrollx < back_width) {
    				scrollBy(deltaX, 0);
    			} else if (scrollx > back_width) {
    				scrollTo(back_width, 0);
    			} else if (scrollx < 0) {
    				scrollTo(0, 0);
    			}
    			break;
    		case MotionEvent.ACTION_UP:
    			Log.e("test", "item  ACTION_UP");
    			int scroll = getScrollX();
    			if (scroll > back_width / 2) {
    				scrollTo(back_width, 0);
    			} else {
    				scrollTo(0, 0);
    			}
    			if (Math.abs(x - downX) < 5) {// 这里依据点击距离来推断是否是itemClick
    				return false;
    			}
    			break;
    		case MotionEvent.ACTION_CANCEL:
    			scrollTo(0, 0);
    			break;
    		}
    		return true;
    	}
    
    	@Override
    	protected void onLayout(boolean changed, int l, int t, int r, int b) {
    		int margeLeft = 0;
    		int size = getChildCount();
    		for (int i = 0; i < size; i++) {
    			View view = getChildAt(i);
    			if (view.getVisibility() != View.GONE) {
    				int childWidth = view.getMeasuredWidth();
    				// 将内部子孩子横排排列
    				view.layout(margeLeft, 0, margeLeft + childWidth,
    						view.getMeasuredHeight());
    				margeLeft += childWidth;
    			}
    		}
    	}
    }
    


    3、ListView的代码

    package com.jwzhangjie.scrollview;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.ListView;
    
    public class ScrollListviewDelete extends ListView {
    
    	private float minDis = 10;
    	private float mLastMotionX;// 记住上次X触摸屏的位置
    	private float mLastMotionY;// 记住上次Y触摸屏的位置
    	private boolean isLock = false;
    
    	public ScrollListviewDelete(Context context, AttributeSet attrs) {
    		super(context, attrs);
    	}
    
    	/**
    	 * 假设一个ViewGroup的onInterceptTouchEvent()方法返回true。说明Touch事件被截获,
    	 * 子View不再接收到Touch事件。而是转向本ViewGroup的
    	 * onTouchEvent()方法处理。

    从Down開始,之后的Move,Up都会直接在onTouchEvent()方法中处理。 * 先前还在处理touch event的child view将会接收到一个 ACTION_CANCEL。

    * 假设onInterceptTouchEvent()返回false。则事件会交给child view处理。

    */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (!isIntercept(ev)) { return false; } return super.onInterceptTouchEvent(ev); } @Override public boolean dispatchTouchEvent(MotionEvent event) { boolean dte = super.dispatchTouchEvent(event); if (MotionEvent.ACTION_UP == event.getAction() && !dte) {//onItemClick int position = pointToPosition((int)event.getX(), (int)event.getY()); View view = getChildAt(position); super.performItemClick(view, position, view.getId()); } return dte; } @Override // 处理点击事件,假设是手势的事件则不作点击事件 普通View public boolean performClick() { return super.performClick(); } @Override // 处理点击事件。假设是手势的事件则不作点击事件 ListView public boolean performItemClick(View view, int position, long id) { return super.performItemClick(view, position, id); } /** * 检測是ListView滑动还是item滑动 isLock 一旦判读是item滑动。则在up之前都是返回false */ private boolean isIntercept(MotionEvent ev) { float x = ev.getX(); float y = ev.getY(); int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.e("test", "isIntercept ACTION_DOWN "+isLock); mLastMotionX = x; mLastMotionY = y; break; case MotionEvent.ACTION_MOVE: Log.e("test", "isIntercept ACTION_MOVE "+isLock); if (!isLock) { float deltaX = Math.abs(mLastMotionX - x); float deltay = Math.abs(mLastMotionY - y); mLastMotionX = x; mLastMotionY = y; if (deltaX > deltay && deltaX > minDis) { isLock = true; return false; } } else { return false; } break; case MotionEvent.ACTION_UP: Log.e("test", "isIntercept ACTION_UP "+isLock); isLock = false; break; case MotionEvent.ACTION_CANCEL: Log.e("test", "isIntercept ACTION_CANCEL "+isLock); isLock = false; break; } return true; } }



    4、Activity代码

    package com.jwzhangjie.scrollview;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.os.Bundle;
    import android.support.v4.app.FragmentActivity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.BaseAdapter;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class ScrollerDeleteActivity extends FragmentActivity implements
    		OnItemClickListener {
    
    	private Toast mToast;
    	private ScrollListviewDelete listviewDelete;
    	private DeleteAdapter adapter;
    	private String[] datas = { "第一项", "第二项", "第三项", "第四项", "第五项", "第六项", "第七项",
    			"第八项", "第九项", "第十项" };
    	private List<String> listDatas = new ArrayList<String>();
    
    	@Override
    	protected void onCreate(Bundle bundle) {
    		super.onCreate(bundle);
    		setContentView(R.layout.activity_scroller_delete);
    		int len = datas.length;
    		for (int i = 0; i < len; i++) {
    			listDatas.add(datas[i]);
    		}
    		listviewDelete = (ScrollListviewDelete) findViewById(android.R.id.list);
    		adapter = new DeleteAdapter();
    		listviewDelete.setAdapter(adapter);
    		listviewDelete.setOnItemClickListener(this);
    	}
    
    	class DeleteAdapter extends BaseAdapter {
    
    		@Override
    		public int getCount() {
    			return listDatas.size();
    		}
    
    		@Override
    		public Object getItem(int position) {
    			return listDatas.get(position);
    		}
    
    		@Override
    		public long getItemId(int position) {
    			return position;
    		}
    
    		@Override
    		public View getView(final int position, View convertView,
    				ViewGroup parent) {
    			ViewHolder holder;
    			if (convertView == null) {
    				holder = new ViewHolder();
    				convertView = LayoutInflater.from(getApplicationContext())
    						.inflate(R.layout.item_delete, null);
    				holder.itemData = (TextView) convertView
    						.findViewById(R.id.itemData);
    				holder.btnDelete = (Button) convertView
    						.findViewById(R.id.btnDelete);
    				holder.btnNao = (Button) convertView.findViewById(R.id.btnNao);
    				convertView.setTag(holder);
    			} else {
    				holder = (ViewHolder) convertView.getTag();
    			}
    			holder.btnDelete.setOnClickListener(new OnClickListener() {
    				@Override
    				public void onClick(View v) {
    					showInfo("点击删除了");
    				}
    			});
    			holder.itemData.setOnClickListener(new OnClickListener() {
    
    				@Override
    				public void onClick(View v) {
    					showInfo("点击了数据: " + listDatas.get(position));
    				}
    			});
    			holder.btnNao.setOnClickListener(new OnClickListener() {
    				@Override
    				public void onClick(View v) {
    					showInfo("点击了闹铃");
    				}
    			});
    			holder.itemData.setText(listDatas.get(position));
    			return convertView;
    		}
    
    		class ViewHolder {
    			TextView itemData;
    			Button btnDelete;
    			Button btnNao;
    		}
    	}
    
    	@Override
    	public void onItemClick(AdapterView<?

    > parent, View view, int position, long id) { showInfo("onItemClick : " + position); } public void showInfo(String text) { if (mToast == null) { mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT); } else { mToast.setText(text); mToast.setDuration(Toast.LENGTH_SHORT); } mToast.show(); } }



    5、XML代码

    <?

    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="match_parent" android:orientation="vertical" > <com.jwzhangjie.scrollview.ScrollListviewDelete android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>


    <?xml version="1.0" encoding="utf-8"?>
    <com.jwzhangjie.scrollview.ListItemDelete xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
    
        <LinearLayout
            android:id="@+id/front"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_item_list_8"
            android:gravity="center"
            android:orientation="horizontal" >
    
            <TextView
                android:id="@+id/itemData"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="測试数据" />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal" >
    
            <Button
                android:id="@+id/btnNao"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="@drawable/bg_item_list_4"
                android:text="闹铃" />
    
            <Button
                android:id="@+id/btnDelete"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="@drawable/bg_item_list_5"
                android:text="删除" />
        </LinearLayout>
    
    </com.jwzhangjie.scrollview.ListItemDelete>

    6、界面效果

    不保证上面的代码是最新的。更新代码地址:https://github.com/jwzhangjie/-ScrollerDelete


    V1.0版本号:解决提供改动数据多时。item滑动底部数据反复。解决方式:推断是否有滑动的item,假设有则复位

    地址:https://github.com/jwzhangjie/-ScrollerDelete  里面有编译好的apk

  • 相关阅读:
    TFS 服务器更换后工作区无法绑定
    导出你的GAC Assembly中的DLLS
    MICROSOFT REPORT VIEWER 2012之无法加载相关的dll
    查询可用的Nuget服务地址
    认识k_BackingField【转】
    EntityFramework 中生成的类加注释
    Bat命令知识[转]
    利用bat批量执行脚本文件
    SQL Server 2012 LocalDB 管理之旅
    【转】Windows环境下.NET 操作Oracle问题
  • 原文地址:https://www.cnblogs.com/lytwajue/p/6760484.html
Copyright © 2020-2023  润新知