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

先看效果:

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 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() {
            @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);
 
  
一般会拦截下来给自己处理,如果被父级拦截了要用反拦截
或者自己处理拦截事件,在特定的情况下给自己的孩子处理
 
  
 
  
 
  

 
  

你可能感兴趣的:(Android自定义控件)