android:模仿微信联系人效果

实现思路:首先说下布局,整个是一个相对布局,最下面是一个listview,listview上面是一个自定义的view(右边显示字母),最上面是一个textview(屏幕中间的方块)

首先说一下右边自定义view,字母是画到view上面的,首先计算一下view的高度,然后除以存放字母数组的长的,得到每个字符的高度;每个字母的宽度都是一样的,所以这里直接设置30sp;

listview显示的是108个梁山好汉的名字;

项目里面使用了一个pinyin4j.jar把每个名字转换为拼音,然后使用charAt(0)获得拼音的第一个字母

listview的每个item是一个线性布局包裹的两个textview,上面的tv显示的是拼音的第一个字母,下面的tv显示的就是名字;在adapter判断当前条目和上一个条目的拼音首字母是否相同,如果相同隐藏当前item上面的tv;

然后在自定义view设置一个自定义监听;当点击自定义view的时候根据高度判断当前点击的是那个字母,然后根据字母设置listview要跳转的位置;

 

首先看下布局:

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cacheColorHint="@android:color/transparent" >
    </ListView>

    <com.wxcontacts.www.view.QuickIndexBar
        android:id="@+id/quickindexbar"
        android:layout_width="30dp"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
         />
    
    <!-- 默认隐藏,当点击自定义view的时候显示 -->
    <TextView 
        android:visibility="gone"
        android:id="@+id/tv_hint"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@drawable/bg_text"
        android:text="A"
        android:textSize="24sp"/>

</RelativeLayout>


先不着急看MainActivity代码首先看下自定义view的代码:

 

 

//自定义view
public class QuickIndexBar extends View{

	//画笔
	private Paint paint;
	
	String[] lettres={"↑","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","↓"};

	//自定义view的宽高
	private int viewHight;
	private int viewWidth;
	//每个文本的高度;(文本高度等于view高度除以文本个数)
	private int cellHeight;

	//文本的高度
	private float textHeight;

	private int currentIndex=-1;

	public OnLetterChangeListen onLetterChangeListen;
	
	public OnLetterChangeListen getOnLetterChangeListen(){
		return onLetterChangeListen;
	}
	
	
	public void setOnLetterChangeListener(OnLetterChangeListen onLetterChangeListen){
		this.onLetterChangeListen=onLetterChangeListen;
	}
	//自定义一个字母改变的监听
	public interface OnLetterChangeListen{
		void onLetterChange(String letter);
		void onResert();
	}
	
	public QuickIndexBar(Context context) {
		this(context,null);
	}
	public QuickIndexBar(Context context, AttributeSet attrs) {
		this(context, attrs,0);
	}

	public QuickIndexBar(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		paint=new Paint();
		//设置字体颜色;默认为黑色;我们这里使用黑色
		//paint.setColor(Color.WHITE);
		//设置字体大小
		paint.setTextSize(20);
		//抗锯齿
		paint.setAntiAlias(true);
		//获取字体宽高,因为每个字体宽度不一样,所以获得宽度必须放在循环中做
		//首先获取字体的属性
		FontMetrics fontMetrics = paint.getFontMetrics();
		//下边界 - 上边界
		textHeight = (float) Math.ceil(fontMetrics.descent-fontMetrics.ascent);
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		//获取文本的宽高
//		getTextWH();
		//每个文本的高度;
		cellHeight=viewHight/lettres.length;
		
		//通过循环把字母画出来
		for(int x=0;x<lettres.length;x++){
			String text=lettres[x];
			
			//paint给我们提供了一个测量字体宽度的方法
			float textWidth = paint.measureText(text);
			if(currentIndex==x){
				//当点击某个字母的时候变色
				paint.setColor(Color.GRAY);
			}else{
				paint.setColor(Color.BLACK);
			}
			
			/*
			 * 参数1:要画的内容     参数23:要画的位置     参数4:画笔
			 * 参数23所画的位置指的是字母左下角坐标
			 */
			canvas.drawText(text,viewWidth/2-textWidth/2,cellHeight/2+textHeight/2+cellHeight*x,paint);
		}
		
	}
	
	//测量view的宽高
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		viewHight =getMeasuredHeight();
		viewWidth =getMeasuredWidth();
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		
		case MotionEvent.ACTION_DOWN:
			//计算当前点击的字母,宽度不用考虑,因为宽度都是一样的,计算高度即可,根据你点击或者移动的高度计算你当前所点击的是哪个字母
			float downY=event.getY();
			currentIndex = (int)downY/cellHeight;
			if(currentIndex<0 || currentIndex>lettres.length-1){
			}else{
				if(onLetterChangeListen!=null){
					onLetterChangeListen.onLetterChange(lettres[currentIndex]);
				}
			}
			//重新绘制;相当于重新调用onDraw()方法
			invalidate();
			break;
		case MotionEvent.ACTION_MOVE:
			float moveY=event.getY();
			currentIndex = (int)moveY/cellHeight;
			if(currentIndex<0 || currentIndex>lettres.length-1){
			}else{
				if(onLetterChangeListen!=null){
					onLetterChangeListen.onLetterChange(lettres[currentIndex]);
				}
			}
			//重新绘制
			invalidate();
			break;
		case MotionEvent.ACTION_UP:
			currentIndex=-1;
			if(onLetterChangeListen!=null){
				onLetterChangeListen.onResert();
			}
			break;

		default:
			break;
		}
		return true;
	}

}


下面我为大家准备了一张计算字母xy坐标的图片:

 

 

最后是MainActivity的代码:

 

public class MainActivity extends Activity {

	private com.wxcontacts.www.view.QuickIndexBar quickIndexBar;
	private ListView mListView;
	//当点击自定义view的时候屏幕中间显示一个方块,显示当前点击的字母,默认是隐藏的,当点击的时候才显示
	private TextView tvHint;
	
	private List<HaoHan> hhList=new ArrayList<HaoHan>();
	Context context;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		tvHint=(TextView) findViewById(R.id.tv_hint);
		context=this;
		//listview 和 自定义view
		mListView=(ListView) findViewById(R.id.listview);
		quickIndexBar=(QuickIndexBar) findViewById(R.id.quickindexbar);
		
		initHHListData();
		
		mListView.setAdapter(new MainListViewAdapter(context,hhList));
		
		//给自定义view设置自定义监听,当点击到某个字母的时候弹出吐司显示这个字母;
		//当点击字母的时候遍历集合,找到首字母为点击字母的HaoHan的下标,让listview跳转到响应位置
		quickIndexBar.setOnLetterChangeListener(new QuickIndexBar.OnLetterChangeListen() {
			
			@Override
			public void onLetterChange(String letter) {
				
				quickIndexBar.setBackgroundResource(R.drawable.bg_text);
				
				tvHint.setVisibility(View.VISIBLE);
				tvHint.setText(letter);
				
				for(int x=0;x<hhList.size();x++){
					if((hhList.get(x).pinyin.charAt(0)+"").equals(letter)){
						mListView.setSelection(x);
						//找到第一个字母相同的直接结束,不再向下找;
						break;
					}
				}
			}

			@Override
			//当手指弹起的时候此方法执行
			public void onResert() {
				tvHint.setVisibility(View.GONE);
				quickIndexBar.setBackgroundResource(Color.TRANSPARENT);
			}
		});
	}
	
	//初始化集合数据
	private void initHHListData() {
		
		HaoHan hh;
		for(int x=0;x<Cheeses.NAMES.length;x++){
			hh=new HaoHan(Cheeses.NAMES[x]);
			hhList.add(hh);
		}
		
		//给集合排序
		Collections.sort(hhList);
		
	}

}


源码下载地址:

 

http://download.csdn.net/detail/zheng_jiao/9513284

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值