自定义view之——联系人列表

来源:互联网 发布:淘宝发顺丰多少钱一个 编辑:程序博客网 时间:2024/05/16 09:43

先看效果:

1、自定义一个索引view,就是右边红色的部分:

package com.example.contact;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.Typeface;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;/** * Created by yang on 2017/7/8. */public class IndexView extends View {    private String Textarr[];    private int TextX;    private int TextY;    private int itemwidth;    private int itemheight;    private Paint paint;    private Context Mycontext;    private int currentindex=-1;    public IndexView(Context context, AttributeSet attrs) {        super(context, attrs);        this.Mycontext=context;        initdata();    }    private void initdata() {        Textarr=new String[] {"A", "B", "C", "D", "E", "F", "G", "H", "I",                "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",                "W", "X", "Y", "Z"};        paint=new Paint();        paint.setColor(Color.WHITE);        paint.setTextSize(20);        paint.setTypeface(Typeface.DEFAULT_BOLD);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        for (int i=0;i<Textarr.length;i++){            initdata();            String word=Textarr[i];            if (i==currentindex){                paint.setColor(Color.RED);            }            Rect rect=new Rect();            //返回边界(由调用者分配的)最小的矩形,它包含所有的字符,在(0,0)处有一个隐含的原点。            paint.getTextBounds(word,0,1,rect);            int rectwidth=rect.width();            int rectheight=rect.height();            TextX=(itemwidth-rectwidth)/2;            TextY=itemheight-rectheight/2+i*itemheight;            canvas.drawText(word,TextX,TextY,paint);        }    }    private int startX;    private int startY;    @Override    public boolean onTouchEvent(MotionEvent event) {        super.onTouchEvent(event);        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:            case MotionEvent.ACTION_MOVE:                startX= (int)event.getX();                startY= (int) event.getY();                int index=(int)startY/itemheight;                currentindex=index;                OnindexchangeListener.change(Textarr[currentindex]);                invalidate();                break;            case MotionEvent.ACTION_UP:                currentindex=-1;                invalidate();        }        return true;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        itemwidth=getMeasuredWidth();        itemheight=getMeasuredHeight()/Textarr.length;    }    public interface OnindexchangeListener{        /*        当当前索引改变的时候调用         */        void change(String text);    }    private OnindexchangeListener OnindexchangeListener;    public void setOnindexchangeListener(IndexView.OnindexchangeListener onindexchangeListener) {        OnindexchangeListener = onindexchangeListener;    }}
自定义联系人条目的view,效果如下:
package com.example.contact;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.FrameLayout;/** * Created by yang on 2017/7/8.
这里要继承relativelayout或framelayout */public class listviewitem extends FrameLayout {    private String TAG=getClass().getSimpleName();    private View contentview;    private View deleteview;    private int deletewidth;    private  int contentwidth;    private int contentheight;    private boolean isshow=false;    public listviewitem(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onFinishInflate() {        contentview=getChildAt(0);        deleteview=getChildAt(1);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        contentview.layout(0,0,getWidth(),getHeight());        deleteview.layout(getWidth(),0,getWidth()+deletewidth,getHeight());    }    int startX;    int startY;    int downx;    int downy;    @Override    public boolean onTouchEvent(MotionEvent event) {        super.onTouchEvent(event);            switch (event.getAction()){                case MotionEvent.ACTION_DOWN:                    downx=startX= (int) event.getX();                    downy=startY= (int) event.getY();                    break;                case MotionEvent.ACTION_MOVE:                     int endx= (int) event.getX();                     int endy= (int) event.getY();                    int dx=endx-startX;                    int toscrollx=getScrollX()-dx;                    if (toscrollx<0){                        toscrollx=0;                    } else if (toscrollx > deletewidth) {                        toscrollx=deletewidth;                    }                   // Log.d(TAG, "onTouchEvent: startX="+startX+"endx="+endx);                    scrollTo(toscrollx,getScrollY());                    startX= (int) event.getX();                    startY= (int) event.getY();                    int DX=Math.abs(endx-downx);                    int DY=Math.abs(endy-downy);                    if (DX>DY&&DX>10){                        getParent().requestDisallowInterceptTouchEvent(true);                    }                    break;                case MotionEvent.ACTION_UP:                    int upx= (int) event.getX();                    int upy= (int) event.getY();                    if ((upx-downx)>deletewidth/2){                        //隐藏                        hintdelete();                    }else if ((upx-downx)<-(deletewidth/2)){                        showdelete();                    }                    else {                        //回弹                        if (isshow){                            showdelete();                        }                        else {                            hintdelete();                        }                    }                    break;            }        return true;    }    int StartX=0;    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        boolean intercep=false;        super.onInterceptTouchEvent(ev);        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN:                if (OnitemstatechangeListener!=null){                    OnitemstatechangeListener.onitemstatechange(listviewitem.this);                }                downx= StartX= (int) ev.getX ();                break;            case MotionEvent.ACTION_MOVE:                int endx= (int) ev.getX();                int DX=Math.abs(endx-StartX);                Log.d(TAG, "onInterceptTouchEvent: DX="+DX);                if (DX>10){                    intercep=true;                }                break;            case MotionEvent.ACTION_UP:                break;        }        return intercep;    }    public void showdelete() {         isshow=false;            scrollTo(deletewidth,0);            OnitemstatechangeListener.open(listviewitem.this);             invalidate();    }    public void hintdelete() {        isshow=false;        scrollTo(0,0);        OnitemstatechangeListener.close(listviewitem.this);        invalidate();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        deletewidth=deleteview.getMeasuredWidth();        contentwidth=contentview.getMeasuredWidth();        contentheight=getMeasuredHeight();    }    interface OnitemstatechangeListener{        void  onitemstatechange(View v);        void close(View v);        void open(View v);    }    private OnitemstatechangeListener OnitemstatechangeListener;    public void setOnitemstatechangeListener(listviewitem.OnitemstatechangeListener onitemstatechangeListener) {        OnitemstatechangeListener = onitemstatechangeListener;    }}
上主类
package com.example.contact;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Comparator;public class MainActivity extends AppCompatActivity {    private TextView tv_1;    private IndexView indexView;    private ListView listView;    private ArrayList<people> list;    private listviewitem listviewitem;    private Handler handler=new Handler(){        @Override        public void handleMessage(Message msg) {            tv_1.setVisibility(View.GONE);        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initview();        initdata();        initlistener();    }    private void initlistener() {        listView.setAdapter(new Myadpter());        indexView.setOnindexchangeListener(new IndexView.OnindexchangeListener() {            @Override            public void change(String text) {                int movetoposition=movetoitem(text);                listView.setSelection(movetoposition);                handler.removeCallbacksAndMessages(null);                tv_1.setText(text);                tv_1.setVisibility(View.VISIBLE);                handler.sendEmptyMessageDelayed(0,2000);            }        });    }    private int movetoitem(String text) {        int near=0;        for (int i=0;i<list.size();i++){            String newtext=list.get(i).getPinyin().substring(0,1);            if (newtext.compareTo(text)<=0){                near=i;                if (text.equals(newtext)){                    return i;                }            }            else {                return near+1;            }        }        return near+1;    }    private class Myadpter extends BaseAdapter{        @Override        public int getCount() {            return list.size();        }        @Override        public Object getItem(int position) {            return list.get(position);        }        @Override        public long getItemId(int position) {            return 0;        }        @Override        public View getView(final int position, View convertView, ViewGroup parent) {            Viewholder viewhloder;            View view;            if (convertView==null){                view=View.inflate(MainActivity.this,R.layout.mylistview,null);                viewhloder=new Viewholder();                viewhloder.content= (TextView) view.findViewById(R.id.contect_item);                viewhloder.meun= (TextView) view.findViewById(R.id.tv_menu);                viewhloder.delete= (TextView) view.findViewById(R.id.delete_item);                viewhloder.listviewitem1= (com.example.contact.listviewitem) view.findViewById(R.id.mylistview);                view.setTag(viewhloder);            }else{                view=convertView;                viewhloder= (Viewholder) view.getTag();            }            viewhloder.content.setText(list.get(position).getname());            String code=list.get(position).getPinyin().substring(0,1);            viewhloder.meun.setText(code);            if (position==0) {                viewhloder.meun.setVisibility(View.VISIBLE);            }else {                String currentmenu=list.get(position-1).getPinyin().substring(0,1);                if (currentmenu.equals(code)){                    viewhloder.meun.setVisibility(View.GONE);                }else {                    viewhloder.meun.setVisibility(View.VISIBLE);                }            }            viewhloder.delete.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    listviewitem l= (com.example.contact.listviewitem) v.getParent();                    l.hintdelete();                    list.remove(position);                    notifyDataSetChanged();                }            });            viewhloder.content.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    Toast.makeText(MainActivity.this,"position="+position,Toast.LENGTH_SHORT).show();                }            });            listviewitem mylistviewitem=viewhloder.listviewitem1;            mylistviewitem.setOnitemstatechangeListener(new listviewitem.OnitemstatechangeListener() {                @Override                public void onitemstatechange(View v) {                        if (v!=listviewitem&&listviewitem!=null){                            listviewitem.hintdelete();                        }                }                @Override                public void close(View v) {                        listviewitem=null;                }                @Override                public void open(View v) {                    listviewitem= (com.example.contact.listviewitem) v;                }            });            return view;        }        class Viewholder{            private TextView content;            private TextView meun;            private TextView delete;            private listviewitem listviewitem1;        }    }    private void initdata() {        list=new ArrayList<>();        list.add(new people("张晓飞"));        list.add(new people("杨光福"));        list.add(new people("胡继群"));        list.add(new people("刘畅"));        list.add(new people("钟泽兴"));        list.add(new people("尹革新"));        list.add(new people("安传鑫"));        list.add(new people("张骞壬"));        list.add(new people("温松"));        list.add(new people("李凤秋"));        list.add(new people("刘甫"));        list.add(new people("娄全超"));        list.add(new people("张猛"));        list.add(new people("王英杰"));        list.add(new people("李振南"));        list.add(new people("孙仁政"));        list.add(new people("唐春雷"));        list.add(new people("牛鹏伟"));        list.add(new people("姜宇航"));        list.add(new people("刘挺"));        list.add(new people("张洪瑞"));        list.add(new people("张建忠"));        list.add(new people("侯亚帅"));        list.add(new people("刘帅"));        list.add(new people("乔竞飞"));        list.add(new people("徐雨健"));        list.add(new people("吴亮"));        list.add(new people("王兆霖"));        list.add(new people("阿三"));        list.add(new people("李博俊"));        //根据拼音首字母大小排序        Collections.sort(list, new Comparator<people>() {            @Override            public int compare(people p1, people p2) {                return (p1.getPinyin().substring(0,1)).compareTo(p2.getPinyin().substring(0,1));            }        });    }    private void initview() {        tv_1= (TextView) findViewById(R.id.tv_1);        indexView= (IndexView) findViewById(R.id.iv_1);        listView = (ListView) findViewById(R.id.lv_main);        tv_1.setVisibility(View.GONE);        tv_1.setAlpha((float) 0.8);    }}

新建个Javabean类转成拼音
package com.example.contact;/** * Created by yang on 2017/7/8. */public class people {    private String name;    private String pinyin;    public people(String name) {        this.name = name;    }    public String getPinyin() {        pinyin=PinYinUtils.getPinYin(name);        return pinyin;    }    public String getname() {        return name;    }}
转成拼音的jar包 pinyin4j.jar
package com.example.contact;import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;/** * 作者:杨光福 on 2016/4/14 13:57 * 微信:yangguangfu520 * QQ号:541433511 * 作用:把汉字转换成拼音 * 阿福 * AFU */public class PinYinUtils {    /**     * 得到指定汉字的拼音     * 注意:不应该被频繁调用,它消耗一定内存     * @param hanzi     * @return     */    public static String getPinYin(String hanzi){        String pinyin = "";        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();//控制转换是否大小写,是否带音标        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);//大写        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);        //由于不能直接对多个汉字转换,只能对单个汉字转换        char[] arr = hanzi.toCharArray();        for (int i = 0; i < arr.length; i++) {            if(Character.isWhitespace(arr[i]))continue;//如果是空格,则不处理,进行下次遍历            //汉字是2个字节存储,肯定大于127,所以大于127就可以当为汉字转换            if(arr[i]>127){                try {                    //由于多音字的存在,单 dan shan                    String[] pinyinArr = PinyinHelper.toHanyuPinyinStringArray(arr[i], format);                    if(pinyinArr!=null){                        pinyin += pinyinArr[0];                    }else {                        pinyin += arr[i];                    }                } catch (BadHanyuPinyinOutputFormatCombination e) {                    e.printStackTrace();                    //不是正确的汉字                    pinyin += arr[i];                }            }else {                //不是汉字,                pinyin += arr[i];            }        }        return pinyin;    }}


上布局:
<?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.example.contact.MainActivity">   <ListView        android:id="@+id/lv_main"        android:layout_width="match_parent"        android:layout_height="wrap_content">    </ListView>    <TextView        android:layout_centerInParent="true"        android:id="@+id/tv_1"        android:layout_width="80dp"        android:layout_height="80dp"        android:background="#22000000"        android:textColor="#000000"        android:text="A"        android:gravity="center"        android:textSize="50sp"        />    <com.example.contact.IndexView        android:id="@+id/iv_1"        android:layout_width="30dp"        android:layout_height="wrap_content"        android:background="#ee0000"        android:layout_alignParentRight="true"        /></RelativeLayout>

、、、、、、、、、、、、、、、、、、、、、、

<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:textColor="#000000"    android:paddingLeft="5dp"    android:textSize="20sp"    android:padding="3dp"    ></TextView>
、、、、、、、、、、、、、、、、、、、
<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="Delete"    android:textSize="20sp"    android:textColor="#ff0000"    android:padding="3dp"    android:gravity="center"    ></TextView>
、、、、、、、、、、、、、、、、、、、、、、、
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <TextView        android:id="@+id/tv_menu"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:textSize="30sp"        android:background="#44000000"        android:textColor="#000000"        android:text="A"        />   <com.example.contact.listviewitem       android:id="@+id/mylistview"       android:layout_below="@id/tv_menu"       android:layout_width="match_parent"       android:layout_height="wrap_content">       <include           android:id="@+id/contect_item"           layout="@layout/content">       </include>       <include           android:id="@+id/delete_item"           layout="@layout/delte">       </include>   </com.example.contact.listviewitem></RelativeLayout>
里面有很多自定义接口的知识,还有拦截与反拦截机制
拦截 return TRUE的时候会拦截事件 会直接把事件给ontouch事件:
public boolean onInterceptTouchEvent(MotionEvent ev) {    boolean intercep=false;    super.onInterceptTouchEvent(ev);    switch (ev.getAction()){        case MotionEvent.ACTION_DOWN:            if (OnitemstatechangeListener!=null){                OnitemstatechangeListener.onitemstatechange(listviewitem.this);            }            downx= StartX= (int) ev.getX ();            break;        case MotionEvent.ACTION_MOVE:            int endx= (int) ev.getX();            int DX=Math.abs(endx-StartX);            Log.d(TAG, "onInterceptTouchEvent: DX="+DX);            if (DX>10){                intercep=true;            }            break;        case MotionEvent.ACTION_UP:            break;    }    return intercep;}

反拦截--反拦截大于拦截

getParent().requestDisallowInterceptTouchEvent(true);
一般会拦截下来给自己处理,如果被父级拦截了要用反拦截
或者自己处理拦截事件,在特定的情况下给自己的孩子处理

原创粉丝点击