Android--listview的item侧滑的实现

来源:互联网 发布:程序员考试难吗 编辑:程序博客网 时间:2024/06/02 02:29

前段时间的状态不是很好,和房东有一些矛盾,同时又犯了厌倦上班综合症。好在及时调整了心态,接下来还有继续努力。
好了,现在总结下前段时间前段时间自己学到的知识。

先是在郭霖大神的blog上看到了他对侧滑菜单的实现,自己就在想能不能实现了listview上item的侧滑。
最后虽然实现了效果,但是侧滑效果不是特别的流畅,还有待优化。

具体思想就是郭林大神博客中的思想。
效果大致如下:
这里写图片描述
基本思想是自定义一个view作为listview的子布局。

1.先完成这个自定义的view

/** * Created by gejiahui on 2015/9/8. */public class ItemSlideLayout extends LinearLayout implements View.OnTouchListener{private int screenWith;    private float xDown;    private float xMove;    private float xUp;    private int rightViewWidth = 200;    private int leftEdge = -rightViewWidth;    private View leftView;    private View rightView;    private final int rightEgde=0;    private boolean isRightVisibily=false;/**     * 左侧布局的参数,通过此参数来重新确定左侧布局的宽度,以及更改leftMargin的值。     */private MarginLayoutParams leftParams;/**     * 右侧布局的参数,通过此参数来重新确定右侧布局的宽度。     */private MarginLayoutParams rightParams;/**     * 用于监听侧滑事件的View。     */private View mBindView;    public ItemSlideLayout(Context context, AttributeSet attrs) {super(context, attrs);WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);screenWith = wm.getDefaultDisplay().getWidth();}public void setSrollView(View view)    {mBindView = view;mBindView.setOnTouchListener(this);}/**     * 在onLayout中重新设定左侧布局和右侧布局的参数。     */@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);        if (changed)        {//get left viewleftView =  getChildAt(0);leftParams = (MarginLayoutParams) leftView.getLayoutParams();leftParams.leftMargin = 0;leftParams.width = screenWith;leftView.setLayoutParams(leftParams);rightView  = getChildAt(1);rightParams = (MarginLayoutParams) rightView.getLayoutParams();rightParams.width = rightViewWidth;rightView.setLayoutParams(rightParams);}    }@Overridepublic boolean onTouch(View v, MotionEvent event) {switch(event.getAction())        {case MotionEvent.ACTION_DOWN:// 手指按下时,记录按下时的横坐标xDown = event.getRawX();                break;            case MotionEvent.ACTION_MOVE:// 手指移动时,对比按下时的横坐标,计算出移动的距离,来调整左侧布局的leftMargin值,从而显示和隐藏左侧布局xMove = event.getRawX();                int distanceX = (int) (xMove - xDown);                if(isRightVisibily)                {leftParams.leftMargin = distanceX + leftEdge;}else{leftParams.leftMargin = distanceX;}if(leftParams.leftMargin < leftEdge)                {leftParams.leftMargin = leftEdge;}if(leftParams.leftMargin > rightEgde)                {leftParams.leftMargin = rightEgde;}leftView.setLayoutParams(leftParams);                break;            case MotionEvent.ACTION_UP:xUp = event.getRawX();                if (wantToShowRightLayout())                {if(shouldScrollToRightLayout())                    {                        scrollToRightLayout();}else{                        scrollToLeftLayout();}                }if(wantToShowLeftLayout())               {if(shouldScrollToLeft())                   {                       scrollToLeftLayout();}else{                       scrollToRightLayout();}               }break;}return true;}/**     * 将屏幕滚动到左侧布局界面,滚动速度设定为30.     */public void scrollToLeftLayout() {new ScrollTask().execute(30);}/**     * 将屏幕滚动到右侧布局界面,滚动速度设定为-30.     */public void scrollToRightLayout() {new ScrollTask().execute(-30);}/**     *     * @return 当前手势想显示右侧布局返回true,否则返回false。     */private boolean wantToShowRightLayout()    {return xMove - xDown < 0 && !isRightVisibily;}/**     *     *     * @return 当前手势想显示左侧布局返回true,否则返回false。     */private boolean wantToShowLeftLayout()    {return xMove - xDown > 0 && isRightVisibily;}/**     *     * @return 如果应该滚动将左侧布局展示出来返回true,否则返回false。     */private boolean shouldScrollToRightLayout() {return   xDown -xUp > 100;}/**     *     * @return 如果应该滚动将右侧布局展示出来返回true,否则返回false。     */private boolean shouldScrollToLeft() {return  xUp - xMove > 100;}class ScrollTask extends AsyncTask<Integer, Integer, Integer> {@Overrideprotected Integer doInBackground(Integer... speed) {int leftMargin = leftParams.leftMargin;// 根据传入的速度来滚动界面,当滚动到达左边界或右边界时,跳出循环。while (true) {                leftMargin = leftMargin + speed[0];                if (leftMargin > rightEgde) {                    leftMargin = rightEgde;                    break;}if (leftMargin < leftEdge) {                    leftMargin = leftEdge;                    break;}                publishProgress(leftMargin);// 为了要有滚动效果产生,每次循环使线程睡眠20毫秒,这样肉眼才能够看到滚动动画。sleep(20);}if (speed[0] > 0) {isRightVisibily = false;} else {isRightVisibily = true;}return leftMargin;}@Overrideprotected void onProgressUpdate(Integer... leftMargin) {leftParams.leftMargin = leftMargin[0];leftView.setLayoutParams(leftParams);}@Overrideprotected void onPostExecute(Integer leftMargin) {leftParams.leftMargin = leftMargin;leftView.setLayoutParams(leftParams);}    }/**     * 使当前线程睡眠指定的毫秒数。     *     * @param millis*            指定当前线程睡眠多久,以毫秒为单位     */private void sleep(long millis) {try {            Thread.sleep(millis);} catch (InterruptedException e) {            e.printStackTrace();}    }}

这个布局的思想是实现郭霖的一篇博文,有兴趣的可以去郭大神的blog下查看一下,讲的非常细致。

2.完成布局文件和适配器
布局文件就是简单的listview,item布局就是上面的ItemSlideLayout
下面给过适配器的代码:

public class MyAdapter extends ArrayAdapter<String> {Context context;ArrayList<String> datas;ItemSlideLayout iTemSlideLayout;public MyAdapter(Context context, int resource, List<String> objects) {super(context, resource, objects);this.context=context;datas= (ArrayList<String>) objects;}@Overridepublic View getView(final int position, View convertView, ViewGroup parent) {View view = null;if(convertView == null){view = LayoutInflater.from(this.context).inflate(R.layout.item,parent,false);}else{view = convertView;}TextView txt = (TextView)view.findViewById(R.id.txt);txt.setText(getItem(position));TextView delete = (TextView)view.findViewById(R.id.delete);delete.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {datas.remove( position);notifyDataSetChanged();return false;}});iTemSlideLayout =(ItemSlideLayout)view.findViewById(R.id.item_slide);iTemSlideLayout.setSrollView(txt);return view;}}

3.主函数的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"><com.gejiahui.itemslide.MyListViewandroid:id="@+id/listview"android:layout_width="match_parent"android:layout_height="match_parent"></com.gejiahui.itemslide.MyListView></LinearLayout>

这里的MyListView就是继承了listview,只是简单重写的它的onInterceptTouchEvent来修改它的分发机制。

/*** Created by gejiahui on 2015/9/9.*/public class MyListView extends ListView {float xDown,yDown;float xUp ,yUp ;boolean result = false;public MyListView(Context context) {super(context);}public MyListView(Context context, AttributeSet attrs) {super(context, attrs);}public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {switch(ev.getAction()){case MotionEvent.ACTION_DOWN:xDown = ev.getRawX();yDown = ev.getRawY();Log.v("down1", "" + xDown + " : " + yDown);break;case MotionEvent.ACTION_MOVE:xUp = ev.getRawX();yUp = ev.getRawY();Log.v("movw2", "" + xUp + " : " + yUp);break;case MotionEvent.ACTION_UP:xUp = ev.getRawX();yUp = ev.getRawY();Log.v("UP2", "" + xUp + " : " + yUp);break;}float x,y;x = Math.abs(xUp - xDown);y = Math.abs(yUp - yDown);Log.v("many3",""+ x+ " : "+y);if(x >= y){return false;}else{return true;}}}

我的想法很简单,就是横着滑的距离大于竖着的时候,分发到item的自定义的ItemSlideLayout来响应;
当横滑的距离小于竖滑的距离时候,有listview来响应。
至于android的分发机制,可以点 这里

源代码下载,点 这里

如有错误,欢迎指正,不胜感激。

0 1
原创粉丝点击