在Android程序中如果有很多数据的话(比如通讯录)就需要能够方便地,快速地定位到用户想要的位置。正好Android中有一种能够实现这种功能的UI。想必大家都见过这种UI。

这个图是我的S4实测图:

图片有点大(1920*1080),sorry.


这个UI有如下2个要点:

1、右侧的A-Z的布局实现;

2、拼音和汉字的转换;

那么,解决了这两个问题,这个UI就基本上实现了。对于第一个问题,我们使用FrameLayout布局能够比较好的解决问题;而第二个问题,我们需要使用pinyin4j-2.5.0.jar文件,可以从文章后面下载完整的pinyin4j-2.5.0压缩包。

看代码吧:


主布局main.xml文件:(自定义View指定宽高,并添加在布局的右边:android:layout_gravity="right")

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <FrameLayout        android:id="@+id/flParent"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:orientation="vertical" >        <ListView            android:id="@+id/lvShow"            android:layout_width="fill_parent"            android:layout_height="fill_parent" />        <TextView            android:id="@+id/tvLetter"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:background="@drawable/show_head_toast_bg"            android:gravity="center"            android:maxWidth="80sp"            android:minWidth="70dip"            android:padding="10dip"            android:textColor="#32b6e7"            android:textSize="50sp" >        </TextView>        <com.smiling.mysidebar.MySideBarView            android:background="#60606060"            android:id="@+id/myView"            android:layout_width="30dip"            android:layout_height="fill_parent"            android:layout_gravity="right" >        </com.smiling.mysidebar.MySideBarView>    </FrameLayout></LinearLayout>

自定义的View:

package com.smiling.mysidebar;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Typeface;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.widget.TextView;public class MySideBarView extends View{private String str[]={"#","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"};private int srcChoose=-1;private boolean showBkg=false;private Paint paint=new Paint();private OnTouchingLetterChangedListener onTouchingLetterChangedListener;private TextView tv;//private Animation anim;private Context context;public MySideBarView(Context context) {super(context);// TODO 自动生成的构造函数存根}public MySideBarView(Context context, AttributeSet attrs) {super(context, attrs);// TODO 自动生成的构造函数存根}public MySideBarView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// TODO 自动生成的构造函数存根}public void setContext(Context c){this.context=c;}//protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//setMeasuredDimension(width, height);//}protected void onDraw(Canvas c){   //最后调用onDraw();super.onDraw(c);if(showBkg){//c.drawColor(Color.RED);}int height=super.getHeight()-super.getHeight()/96;int width=super.getWidth();       //宽度为90pixels,在main.xml中设置的width=30dip;System.out.println("Height="+getHeight()+",Width="+getWidth());int singleHeight=height/str.length;for(int i=0;i<str.length;i++){paint.setColor(Color.BLACK);paint.setAntiAlias(true);paint.setTextSize(super.getHeight()/42);if(i==srcChoose){paint.setColor(Color.RED);paint.setFakeBoldText(true);}float xPos=(width-paint.measureText(str[i]))/2 ;float yPos=singleHeight*i+singleHeight;c.drawText(str[i], xPos, yPos, paint);paint.reset();}}//============================================================================================================public boolean dispatchTouchEvent(MotionEvent e){float y=e.getY();int oldChoose=srcChoose;  //srcChoose==-1;int currentPosition=(int)(y/getHeight()*str.length);System.out.println("CurrentPosition="+currentPosition);switch(e.getAction()){case MotionEvent.ACTION_DOWN:this.showBkg=true;if(oldChoose != currentPosition && this.onTouchingLetterChangedListener != null){if(currentPosition >= 0 && currentPosition < str.length){this.onTouchingLetterChangedListener.onTouchingLetterChanged(str[currentPosition],currentPosition);srcChoose=currentPosition;super.invalidate();}}break;case MotionEvent.ACTION_MOVE:if(oldChoose != currentPosition && this.onTouchingLetterChangedListener != null){if(currentPosition >= 0&¤tPosition < str.length){this.onTouchingLetterChangedListener.onTouchingLetterChanged(str[currentPosition],currentPosition);srcChoose=currentPosition;super.invalidate();}}break;case MotionEvent.ACTION_UP:showBkg=false;srcChoose=-1;super.invalidate();tv.setVisibility(View.GONE);break;}return true;}//============================================================================================================public boolean onTouchEvent(MotionEvent e){System.out.println("onTouchEvent()");return super.onTouchEvent(e);}//============================================================================================================public interface OnTouchingLetterChangedListener{    public void onTouchingLetterChanged(String string,int position);}public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener TCL){this.onTouchingLetterChangedListener=TCL;}//==============================================================================================================public void setTextView(TextView tv){this.tv=tv;}public String[] getAtoZAlpha(){return str;}//================================================================================================================}
PinYin工具类:这个类的主要作用是根据给出的汉字串返回第一个字的首字母的大写。

可以先看看这里的教程:http://blog.csdn.net/hfhwfw/article/details/6030816

package com.smiling.mysidebar;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.HanyuPinyinVCharType;import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;public class PinYinUtil {public static String getPinYinFirst_u(String inputString) {HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();format.setCaseType(HanyuPinyinCaseType.LOWERCASE);format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);format.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);char[] input = inputString.trim().toCharArray();StringBuffer output = new StringBuffer("");try {for (int i = 0; i < input.length; i++) {if (Character.toString(input[i]).matches("[\u4E00-\u9FA5]+")) {String[] temp = PinyinHelper.toHanyuPinyinStringArray(input[i], format);output.append(temp[0]);output.append(" ");} elseoutput.append(Character.toString(input[i]));}} catch (BadHanyuPinyinOutputFormatCombination e) {e.printStackTrace();}return output.toString().substring(0, 1).toUpperCase();}

主java文件:

package com.smiling.mysidebar;import java.util.HashMap;import java.util.Map;import com.smiling.mysidebar.MySideBarView.OnTouchingLetterChangedListener;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.view.View;import android.view.animation.AnimationSet;import android.view.animation.AnimationUtils;import android.widget.ListView;import android.widget.TextView;public class Main extends Activity implements OnTouchingLetterChangedListener{private TextView tv;private ListView lv;private MySideBarView myView;private MyBaseAdapter adapter;private Map<String,Integer> map=new HashMap<String,Integer>();private String str[]={ /*这里自己添加数据吧,我的是通讯录的数据,就不好意思放在这里啦 =.= */ };private String alphaArray[];private int touchPosition=-1;public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);super.setContentView(R.layout.main);tv=(TextView)super.findViewById(R.id.tvLetter);lv=(ListView)super.findViewById(R.id.lvShow);myView=(MySideBarView)super.findViewById(R.id.myView);myView.setTextView(tv);myView.setContext(this);myView.setOnTouchingLetterChangedListener(this); lv.setTextFilterEnabled(true);        tv.setVisibility(View.INVISIBLE);                  adapter=new MyBaseAdapter(this,str);        lv.setAdapter(adapter);        lv.setVerticalScrollBarEnabled(false);                alphaArray=myView.getAtoZAlpha();        initMap();       }public void initMap(){String tempAlpha="";for(int i=0;i<str.length;i++){String alpha=PinYinUtil.getPinYinFirst_u(str[i]);if(!alpha.equals(tempAlpha)){map.put(alpha,i);tempAlpha=alpha;}}System.out.println(map.toString());}//==========================================================================================================    private boolean hasFound=false;public void onTouchingLetterChanged(String string,int position){this.touchPosition=position;tv.setText(string);tv.startAnimation(AnimationUtils.loadAnimation(this,R.anim.toast_fade_out));        tv.setVisibility(View.VISIBLE);  //注意如果使用动画的话,动画结束时控件存在与否和动画开始前存在与否一致//        while(this.touchPosition != -1 && hasFound==false) {        if(map.containsKey(string)){        lv.setSelection(map.get(string));        hasFound=true;        }else{        touchPosition+=1;  //这里注意要加1,避免陷入死循环!        if(touchPosition < alphaArray.length){        string=alphaArray[touchPosition];        }                }           }        this.hasFound=false;}}

然后就是自定义BaseAdapter实现ListView了,这个代码就不在这里放出了,大家应该都会自己写吧。


我在实现每个UI项目的时候都能学到好多细节的东西,希望大家也能这样做,会有很多收获的。比如通过这个UI,我们能看到接口内部从注册到回调的这个细节实现。还有,控件如果使用动画的话,动画结束时控件存在与否和动画开始前存在与否一致,等等吧~


pinyin4j-2.5.0.zip的下载地址:点击打开链接


更多相关文章

  1. Android模拟开关按钮点击打开动画(属性动画之平移动画)
  2. Android(安卓)侧滑关闭Activity的实例
  3. Android属性动画-Property Animation(四) 组合动画
  4. Android之增长的数字(仿支付宝资产数字)
  5. Android(安卓)补间动画之平移动画TranslateAnimation
  6. 如何实现Android应用的启动画面(闪屏)?
  7. android viewPager滑动速度设置
  8. [置顶] Android中自定义View、ViewGroup理论基础详解
  9. 13-6-27 android布局include的用法

随机推荐

  1. 用React Native做一个填字游戏(3)——背景
  2. android 4.0以上版本横竖屏切换后不重建
  3. Android(安卓)Audio System 之三: AudioPo
  4. Android第十七课 Jni string空串跨模块使
  5. Android欢迎界面的实现
  6. No implementation found for long org.o
  7. 20145328 《Java程序设计》实验四实验报
  8. Android(安卓)高仿抖音双击点赞效果
  9. PermissionsDispatcher动态权限申请
  10. Android加载图片出现内存溢出攻略