自定义控件<二> 通讯录的简单实现

来源:互联网 发布:重生天龙八部知乎 编辑:程序博客网 时间:2024/05/21 14:42

自定义控件<二> 通讯录的简单实现

自定义通讯录的核心就是listView中对item的自定义操作,item的联动,拦截,子孩子之间的位置变化;
简单来说就是item作为一个viewGroup对子孩子的简单操作,当然在这里用viewDragHelper很简单可以实现这个需求;
废话不多说,直接上代码:

首先创建listView 实现通讯录列表:

 @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ListView listview = (ListView) findViewById(R.id.listview);        listview.setAdapter(new MyAdapter());    }

接下来是关键是对listView中的item的自定义实现
ok~先看下布局文件

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"    android:layout_width="match_parent" android:layout_height="match_parent"    tools:context="com.itheima.swipedelete96.MainActivity">    <ListView        android:id="@+id/listview"        android:dividerHeight="2dp"        android:divider="@color/colorPrimary"        android:layout_width="match_parent"        android:layout_height="match_parent"/></RelativeLayout>

item的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">    <com.itheima.swipedelete96.SwipeLayout        android:id="@+id/swipeLayout"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <!--content布局-->        <include layout="@layout/layout_content"/>        <!--delete布局-->        <include layout="@layout/layout_delete"/>    </com.itheima.swipedelete96.SwipeLayout></LinearLayout>

应该有留意到item布局文件中自定义布局SwipeLayout;通过代码实现swipeLayout对子view的操作;

public class SwipeLayout extends FrameLayout {    private View content;    private View delete;    private ViewDragHelper dragHelper;    public SwipeLayout(Context context) {        this(context, null);    }    public SwipeLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        dragHelper = ViewDragHelper.create(this, callback);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        content = getChildAt(0);        delete = getChildAt(1);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {//        super.onLayout(changed, left, top, right, bottom);        content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());        int L = content.getMeasuredWidth();        delete.layout(L, 0, L + delete.getMeasuredWidth(), delete.getMeasuredHeight());    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        boolean result = dragHelper.shouldInterceptTouchEvent(ev);        return result;    }    float downX, downY;    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                downX = event.getX();                downY = event.getY();                if(listener!=null){                    listener.onTouchDown(this);                }                break;            case MotionEvent.ACTION_MOVE:                float moveX = event.getX();                float moveY = event.getY();                //1.获取移动的dx和dy                float dx = moveX - downX;                float dy = moveY - downY;                //2.判断谁大就是偏向于谁的方向                if(Math.abs(dx)>Math.abs(dy)){                    //说明偏向于水平,我们就认为是想滑动条目,则请求listview不要拦截                    requestDisallowInterceptTouchEvent(true);                }                break;            case MotionEvent.ACTION_UP:                break;        }        dragHelper.processTouchEvent(event);        return true;    }    ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {        @Override        public boolean tryCaptureView(View child, int pointerId) {            return true;        }        @Override        public int getViewHorizontalDragRange(View child) {            return 1;        }        /**         * 修正和限制移动的         * @param child         * @param left         * @param dx         * @return         */        @Override        public int clampViewPositionHorizontal(View child, int left, int dx) {            if (child == content) {                //限制content                if (left > 0) {                    left = 0;                } else if (left < -delete.getMeasuredWidth()) {                    left = -delete.getMeasuredWidth();                }            } else if (child == delete) {                //限制delete                if (left > content.getMeasuredWidth()) {                    left = content.getMeasuredWidth();                } else if (left < (content.getMeasuredWidth() - delete.getMeasuredWidth())) {                    left = (content.getMeasuredWidth() - delete.getMeasuredWidth());                }            }            return left;        }        /**         * 伴随移动         * @param changedView         * @param left         * @param dx         */        @Override        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {            super.onViewPositionChanged(changedView, left, top, dx, dy);            //如果移动是content,那么让delete进行伴随移动            if (changedView == content) {                int newLeft = delete.getLeft() + dx;                delete.layout(newLeft, 0, newLeft + delete.getMeasuredWidth(), delete.getBottom());            } else if (changedView == delete) {                //如果移动是delete,那么让content进行伴随移动                int newLeft = content.getLeft() + dx;                content.layout(newLeft, 0, newLeft + content.getMeasuredWidth(), content.getBottom());            }            //回调接口的方法            if(content.getLeft()==0){                //说明关闭                if(listener!=null){                    listener.onClose(SwipeLayout.this);                }            }else if(content.getLeft()==-delete.getMeasuredWidth()){                //说明打开                if(listener!=null){                    listener.onOpen(SwipeLayout.this);                }            }        }        @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            super.onViewReleased(releasedChild, xvel, yvel);            if (content.getLeft() > -delete.getMeasuredWidth() / 2) {                //关闭                close();            } else {                //打开                open();            }        }    };    /**     * 打开     */    public void open() {        dragHelper.smoothSlideViewTo(content, -delete.getMeasuredWidth(), 0);        ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);    }    /**     * 关闭     */    public void close() {        dragHelper.smoothSlideViewTo(content, 0, 0);        ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);    }    @Override    public void computeScroll() {        super.computeScroll();        if (dragHelper.continueSettling(true)) {            //再次刷新            ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);        }    }    private OnSwipeListener listener;    public void setOnSwipeListener(OnSwipeListener listener){        this.listener = listener;    }    public interface OnSwipeListener{        void onOpen(SwipeLayout swipeLayout);        void onClose(SwipeLayout swipeLayout);        void onTouchDown(SwipeLayout swipeLayout);    }}

在MainActivity中listView设置Adapter实现通讯录的功能;

    SwipeLayout currentLayout = null;//用来记录当前打开的SwipeLayout    class MyAdapter extends BaseAdapter implements SwipeLayout.OnSwipeListener{        @Override        public int getCount() {            return Constant.NAMES.length;        }        @Override        public Object getItem(int position) {            return null;        }        @Override        public long getItemId(int position) {            return 0;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            ViewHolder holder = null;            if(convertView== null){                convertView = View.inflate(parent.getContext(), R.layout.adapter_list, null);                holder = new ViewHolder(convertView);                convertView.setTag(holder);            }else {                holder = (ViewHolder) convertView.getTag();            }            holder.tvName.setText(Constant.NAMES[position]);            //给SwipeLayout添加打开关闭的监听器            holder.swipeLayout.setOnSwipeListener(this);            return convertView;        }        @Override        public void onOpen(SwipeLayout layout) {            //先关闭之间已经打开的            if(currentLayout!=null && currentLayout!=layout){                currentLayout.close();            }            //记录一下            currentLayout = layout;        }        @Override        public void onClose(SwipeLayout layout) {            //关闭的时候清除一下            if(currentLayout==layout){                currentLayout = null;            }        }        @Override        public void onTouchDown(SwipeLayout swipeLayout) {            if(currentLayout!=null&&currentLayout!=swipeLayout){                currentLayout.close();            }        }    }    static class ViewHolder {        @Bind(R.id.tv_name)        TextView tvName;        @Bind(R.id.tv_delete)        TextView tvDelete;        @Bind(R.id.swipeLayout)        SwipeLayout swipeLayout;        ViewHolder(View view) {            ButterKnife.bind(this, view);        }    }

下面是完整代码:

package com.itheima.swipedelete96;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import java.util.ArrayList;import butterknife.Bind;import butterknife.ButterKnife;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ListView listview = (ListView) findViewById(R.id.listview);        listview.setAdapter(new MyAdapter());    }    SwipeLayout currentLayout = null;//用来记录当前打开的SwipeLayout    class MyAdapter extends BaseAdapter implements SwipeLayout.OnSwipeListener{        @Override        public int getCount() {            return Constant.NAMES.length;        }        @Override        public Object getItem(int position) {            return null;        }        @Override        public long getItemId(int position) {            return 0;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            ViewHolder holder = null;            if(convertView== null){                convertView = View.inflate(parent.getContext(), R.layout.adapter_list, null);                holder = new ViewHolder(convertView);                convertView.setTag(holder);            }else {                holder = (ViewHolder) convertView.getTag();            }            holder.tvName.setText(Constant.NAMES[position]);            //给SwipeLayout添加打开关闭的监听器            holder.swipeLayout.setOnSwipeListener(this);            return convertView;        }        @Override        public void onOpen(SwipeLayout layout) {            //先关闭之间已经打开的            if(currentLayout!=null && currentLayout!=layout){                currentLayout.close();            }            //记录一下            currentLayout = layout;        }        @Override        public void onClose(SwipeLayout layout) {            //关闭的时候清除一下            if(currentLayout==layout){                currentLayout = null;            }        }        @Override        public void onTouchDown(SwipeLayout swipeLayout) {            if(currentLayout!=null&&currentLayout!=swipeLayout){                currentLayout.close();            }        }    }    static class ViewHolder {        @Bind(R.id.tv_name)        TextView tvName;        @Bind(R.id.tv_delete)        TextView tvDelete;        @Bind(R.id.swipeLayout)        SwipeLayout swipeLayout;        ViewHolder(View view) {            ButterKnife.bind(this, view);        }    }}package com.itheima.swipedelete96;import android.content.Context;import android.support.v4.view.ViewCompat;import android.support.v4.widget.ViewDragHelper;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.FrameLayout;/** * Created by lxj on 2016/12/13. */public class SwipeLayout extends FrameLayout {    private View content;    private View delete;    private ViewDragHelper dragHelper;    public SwipeLayout(Context context) {        this(context, null);    }    public SwipeLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        dragHelper = ViewDragHelper.create(this, callback);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        content = getChildAt(0);        delete = getChildAt(1);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {//        super.onLayout(changed, left, top, right, bottom);        content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());        int L = content.getMeasuredWidth();        delete.layout(L, 0, L + delete.getMeasuredWidth(), delete.getMeasuredHeight());    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        boolean result = dragHelper.shouldInterceptTouchEvent(ev);        return result;    }    float downX, downY;    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                downX = event.getX();                downY = event.getY();                if(listener!=null){                    listener.onTouchDown(this);                }                break;            case MotionEvent.ACTION_MOVE:                float moveX = event.getX();                float moveY = event.getY();                //1.获取移动的dx和dy                float dx = moveX - downX;                float dy = moveY - downY;                //2.判断谁大就是偏向于谁的方向                if(Math.abs(dx)>Math.abs(dy)){                    //说明偏向于水平,我们就认为是想滑动条目,则请求listview不要拦截                    requestDisallowInterceptTouchEvent(true);                }                break;            case MotionEvent.ACTION_UP:                break;        }        dragHelper.processTouchEvent(event);        return true;    }    ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {        @Override        public boolean tryCaptureView(View child, int pointerId) {            return true;        }        @Override        public int getViewHorizontalDragRange(View child) {            return 1;        }        /**         * 修正和限制移动的         * @param child         * @param left         * @param dx         * @return         */        @Override        public int clampViewPositionHorizontal(View child, int left, int dx) {            if (child == content) {                //限制content                if (left > 0) {                    left = 0;                } else if (left < -delete.getMeasuredWidth()) {                    left = -delete.getMeasuredWidth();                }            } else if (child == delete) {                //限制delete                if (left > content.getMeasuredWidth()) {                    left = content.getMeasuredWidth();                } else if (left < (content.getMeasuredWidth() - delete.getMeasuredWidth())) {                    left = (content.getMeasuredWidth() - delete.getMeasuredWidth());                }            }            return left;        }        /**         * 伴随移动         * @param changedView         * @param left         * @param dx         */        @Override        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {            super.onViewPositionChanged(changedView, left, top, dx, dy);            //如果移动是content,那么让delete进行伴随移动            if (changedView == content) {                int newLeft = delete.getLeft() + dx;                delete.layout(newLeft, 0, newLeft + delete.getMeasuredWidth(), delete.getBottom());            } else if (changedView == delete) {                //如果移动是delete,那么让content进行伴随移动                int newLeft = content.getLeft() + dx;                content.layout(newLeft, 0, newLeft + content.getMeasuredWidth(), content.getBottom());            }            //回调接口的方法            if(content.getLeft()==0){                //说明关闭                if(listener!=null){                    listener.onClose(SwipeLayout.this);                }            }else if(content.getLeft()==-delete.getMeasuredWidth()){                //说明打开                if(listener!=null){                    listener.onOpen(SwipeLayout.this);                }            }        }        @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            super.onViewReleased(releasedChild, xvel, yvel);            if (content.getLeft() > -delete.getMeasuredWidth() / 2) {                //关闭                close();            } else {                //打开                open();            }        }    };    /**     * 打开     */    public void open() {        dragHelper.smoothSlideViewTo(content, -delete.getMeasuredWidth(), 0);        ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);    }    /**     * 关闭     */    public void close() {        dragHelper.smoothSlideViewTo(content, 0, 0);        ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);    }    @Override    public void computeScroll() {        super.computeScroll();        if (dragHelper.continueSettling(true)) {            //再次刷新            ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);        }    }    private OnSwipeListener listener;    public void setOnSwipeListener(OnSwipeListener listener){        this.listener = listener;    }    public interface OnSwipeListener{        void onOpen(SwipeLayout swipeLayout);        void onClose(SwipeLayout swipeLayout);        void onTouchDown(SwipeLayout swipeLayout);    }}
原创粉丝点击