您的位置:首页 > 移动开发 > 微信开发

Android 自定义seekbar【仿微信联系人】

2016-01-03 22:06 726 查看
/**

 *

 * 转载请标明出处:http://blog.csdn.net/u013598111/article/details/50452578

 *   @author:【JunTao_sun】
 *

 *

*/



 

汉子转拼音 需要依赖 pinyin4j 架包

public class MainActivity extends Activity implements Select2String {
private static final String TAG = null;
//自定义 seekbar
private MySeekBar seekbar;
private ListView listView;
// 联系人信息
private ArrayList<String> Names;
//自定义比较器
private PinyinComparator comparator;
// 实体类
private List<NamesModel> namesData = new ArrayList<NamesModel>();

private ListViewadapte adapat;
private TextView text;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
comparator = new PinyinComparator();

initViews();
initData();
sortData();

}

/**
* 将数据NamesModel排序
*/
private void sortData() {
Collections.sort(namesData, comparator);
adapat = new ListViewadapte(namesData, this);
listView.setAdapter(adapat);

}

private void initViews() {
text = (TextView) this.findViewById(R.id.text_tag);
listView = (ListView) this.findViewById(R.id.listview);

View head = View.inflate(MainActivity.this, R.layout.head, null);
listView.addHeaderView(head);

seekbar = (MySeekBar) this.findViewById(R.id.seekbar);
seekbar.setOnSelect2StringListener(this);
listView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if(position!=0){
Toast.makeText(MainActivity.this,
namesData.get(position-1).getName(), Toast.LENGTH_SHORT)
.show();
}

}
});

}

/*
*
* 接口回调的
* @str字母
*/

@Override
public void getSelect(String str) {

for (int i = 0; i < namesData.size(); i++) {

if (str.equals("↑")) {

listView.setSelection(0);
}

if (str.equals(namesData.get(i).getNameLeftPinying())) {
int select = adapat.getSelectPosition(i);
int point = adapat.getSelectItem(select);
listView.setSelection(point);
}}}

private void initData() {
// 先添加数据
Names = new ArrayList<String>();
Names.add("浅蓝色大海");
Names.add("梦幻彩虹");
Names.add("湛蓝天空");
Names.add("美丽故乡");
Names.add("离城梦");
Names.add("梦仙境");
Names.add("羽化尘");
Names.add("人来疯");
Names.add("苦恋伊");
Names.add("淡年华");
Names.add("追梦少年");
Names.add("曼陀罗");
Names.add("石头人");
Names.add("忆往昔");
Names.add("夜未央");
Names.add("巴黎港");
Names.add("温暖");
Names.add("幻想爱");
Names.add("笄发醒");
Names.add("Elisc");
Names.add("Ahiso");
Names.add("goiso");
Names.add("苦酒满");
Names.add("@魅力");
Names.add("U可爱");
Names.add("t天空");
Names.add("&money$");
Names.add("*雪花*");
Names.add("吖美呀");
Names.add("大话水浒");
Names.add("一沙一世界");
Names.add("花儿朵朵");
Names.add("韩国旅游");
Names.add("富士山");
Names.add("旧金山");
Names.add("太阳");
Names.add("月亮");
Names.add("温暖的旧时光");
Names.add("记忆美好的");
Names.add("喝点小酒");
Names.add("几碟花生");
// 将上面的数据 添加到NameModel中 并加入部首拼音
for (int i = 0; i < Names.size(); i++) {
NamesModel name = new NamesModel();
String str = Names.get(i);
char[] ch = str.toCharArray();

name.setName(str);
String saveLeft=null;
String firstWord=str.substring(0, 1);
//检查str 第一个string是否 是字母开头
boolean isEnglish=firstWord.matches("[a-z-A-Z]");
Log.e(TAG, "isEnglish"+isEnglish);
if(isEnglish){
saveLeft=PinyingTrasfrom.getInstance().english2Left(str);
}else if(!isEnglish){//如果不是字母开头 是汉字 则调用拼音转换工具
//如果是中文 再调用拼音转换 不然会抛异常
if(str.matches("^[\u4E00-\u9FFF]+$")){
String s=PinyingTrasfrom.getInstance().HanZid2Pinying(ch[0]);
s = s.substring(0, 1);
saveLeft = s.matches("[A-Z]") ? s : "#";
}else {
saveLeft="#";
}

}

// 判断是否为字母

name.setNameLeftPinying(saveLeft);
namesData.add(name);

}

}

@Override
public void onHidden() {
text.setVisibility(View.GONE);

}

@Override
public void onAppear(String info) {
text.setVisibility(View.VISIBLE);
text.setText(info);

}

}
拼音转换工具类:

package com.example.pingyin.utils;

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 PinyingTrasfrom {

private static PinyingTrasfrom py;
private PinyingTrasfrom() {
super();

}

public static PinyingTrasfrom getInstance(){

if(py==null){
//为什么不放在方法 因为不必要每次都检查 效率低
//为什么放在中间 里面还要判断一次 因为防止里面有多余线程 多次创建
synchronized (PinyingTrasfrom.class) {

if(py==null){
py= new PinyingTrasfrom();

}

}

}
return py;

}
public String HanZid2Pinying(char ch){
//拼音转换格式
HanyuPinyinOutputFormat outputFormat = new HanyuPinyinOutputFormat();
// 大小写
outputFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
// outputFormat.setVCharType(HanyuPinyinVCharType.WITH_U_AND_COLON);
// 音调 返回有带数字
// outputFormat.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);

String[] st=null;
try {
//得到 每一个字符的拼音 String
st = PinyinHelper.toHanyuPinyinStringArray(ch, outputFormat);
} catch (BadHanyuPinyinOutputFormatCombination e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return st[0];

};

/**
*
* 得到是英语名字的时候 第一个大写字母
* @param english
* @return
*/
public String english2Left(String english){

String en=english.substring(0, 1);
return en.toUpperCase();

}

}
ListView适配器:

package com.example.pingyin;

import java.util.Arrays;
import java.util.List;

import com.example.pingyin.utils.PinyingTrasfrom;
import com.hp.hpl.sparta.xpath.PositionEqualsExpr;

import android.R.array;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class ListViewadapte extends BaseAdapter {
private static final String TAG = null;
private List<NamesModel> data;
private Context c;

public ListViewadapte() {
super();

}

public ListViewadapte(List<NamesModel> t, Context c) {
super();
data = (List<NamesModel>) t;
this.c = c;

}

@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return data.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

static class ViewHold {

TextView textLeft;
TextView text;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHold hold;

if (convertView == null) {
convertView = View.inflate(c, R.layout.list_item, null);
hold = new ViewHold();
hold.textLeft = (TextView) convertView.findViewById(R.id.left);
hold.text = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(hold);
} else {
hold = (ViewHold) convertView.getTag();
}

int selection = getSelectPosition(position);

//判断是否是首字母的位置
if (position == getSelectItem(selection)) {
hold.textLeft.setVisibility(View.VISIBLE);
hold.textLeft.setTextSize(20);
hold.textLeft.setText(data.get(position).getNameLeftPinying());

} else {
hold.textLeft.setVisibility(View.GONE);
}
hold.text.setText(data.get(position).getName());
return convertView;

}

/*
* 根据ListView的当前位置获取分类的首字母的Char ascii值
*
* @param position
*
* @return 该position 对应的数据 拼音对应的ascii值
*/
public int getSelectPosition(int position) {
NamesModel namesModel = data.get(position);

String s = namesModel.getNameLeftPinying();

char[] charResult = s.toCharArray();
char charFirst = charResult[0];
int selection = 0;
return selection = charFirst;

}

/**
* @param postion
* 数据position 是否是第一次出现 归类 @selection Char ascii值
* @return
*/
public int getSelectItem(int selection) {
NamesModel str = null;
for (int i = 0; i < data.size(); i++) {

str = data.get(i);

char[] cs = str.getNameLeftPinying().toCharArray();
//得到汉子 第一个字的拼音字符
char c = cs[0];

if (c == selection) {
return i;
}
}

return -1;
}

}
排序比较器
package com.example.pingyin.utils;

import java.util.Comparator;
import j
e129
ava.util.List;

import com.example.pingyin.NamesModel;

public class PinyinComparator implements Comparator<NamesModel> {

@Override
public int compare(NamesModel o1, NamesModel o2) {

//# >@
if (o1.getNameLeftPinying().equals("@")
|| o2.getNameLeftPinying().equals("#")) {
return -1;
} else if (o1.getNameLeftPinying().equals("#")
|| o2.getNameLeftPinying().equals("@")) {
return 1;
} else {
return o1.getNameLeftPinying().compareTo(o2.getNameLeftPinying());
}

}}
自定义seekbar:

package com.example.pingyin;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Rect;
import android.graphics.pdf.PdfDocument;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;

public class MySeekBar extends View {
private static final String TAG = null;
private String[] pinyin = 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", "#" };

public MySeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

rect = new Rect();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(0xff0000ff);
paint.setDither(true);
paint.setTextSize(sp2px(45));
}

public MySeekBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);

}

public MySeekBar(Context context) {
this(context, null);

}

private Paint paint;
private Rect rect;
private int textWidth;
private int textHheiht;
private int padding = 16;
//字母中 最大的宽度
private int maxWdith;
private float choose;
//是否画背景
private boolean showBkg;
//间隙 可以忽略
private float gap;
private int shengxia;

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
maxWdith = 0;
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
paint.setTextSize(sp2px(16));
for (int i = 0; i < pinyin.length; i++) {
textMeasure(pinyin[i]);
maxWdith = Math.max(maxWdith, rect.width());
}
// 得到最宽的字母长度
int w = maxWdith + 2 * padding;
setMeasuredDimension(w, getMeasuredHeight());

}

private void textMeasure(String str) {

paint.getTextBounds(str, 0, str.length(), rect);

}

private int getTextHeight() {
FontMetrics fm = paint.getFontMetrics();
return (int) (fm.ascent + fm.descent);
}

@Override
protected void onDraw(Canvas canvas) {

if (showBkg) {
canvas.drawColor(Color.parseColor("#40000000"));
}
int height = 0;
//得到控件宽度
int width = getWidth();

for (int i = 0; i < pinyin.length; i++) {
//在循环设置大小 因为下边paint设置重置了
paint.setTextSize(sp2px(16));

textMeasure(pinyin[i]);
//开始画字体的起始
int startLeft = (width) / 2 - maxWdith / 2;

if (choose == i) {

paint.setColor(0xffff0000);
paint.setFakeBoldText(true);

}
if (i == 1)

startLeft = startLeft - maxWdith / 4;
// 为了让最后个字符串 与末端有间隔 第一个字母开始的Y不变 所以把总体向上移动 一半个字体高度
canvas.drawText(pinyin[i], startLeft, (mEachHeight + gap) * i
+ mEachHeight - getTextHeight() + getTextHeight() / 2,
paint);

paint.reset();

}

}

private float mEachHeight;
private float downY;
private boolean isChoose = false;
// 选择区域的 位置
private int c;
private Select2String callback;

@Override
public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

downY = (float) event.getY();
//得到点击 字母的位置
c = (int) (downY / getMeasuredHeight() * pinyin.length);
//刷新 那个字母变色
choose = c;
//控制是否画背景
showBkg = true;

if (callback != null) {

callback.onAppear(pinyin[c]);
}
invalidate();

break;
case MotionEvent.ACTION_MOVE:

break;
case MotionEvent.ACTION_UP:
if (callback != null) {

callback.getSelect(pinyin[c]);
callback.onHidden();
}
showBkg = false;
invalidate();
break;

}

return true;
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);
mEachHeight = (h - getPaddingBottom() - getPaddingTop()) / 32;
// 除了字母占据的空间大小
shengxia = (int) (h - 27 * mEachHeight) + (-getTextHeight() * 2);
// 字母间的间隙
gap = shengxia / 54;
}

// 回调接口 当点击那个字母的时候进行回调
interface Select2String {

void getSelect(String str);

void onHidden();

void onAppear(String pinyin);
}

public void setOnSelect2StringListener(Select2String select) {
this.callback = select;
}

/**
* sp 2 px
*
* @param spVal
* @return
*/
protected int sp2px(int spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, getResources().getDisplayMetrics());

}

}
实体类NamesModel:
package com.example.pingyin;

public class NamesModel {

public NamesModel() {

}
//汉子
private String name;
//汉子第一个字的 拼音
private String nameLeftPinying;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNameLeftPinying() {
return nameLeftPinying;
}
public void setNameLeftPinying(String nameLeftPinying) {
this.nameLeftPinying = nameLeftPinying;
}

}


下边是布局实现:

<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"
tools:context=".MainActivity" >

<ListView
android:id="@+id/listview"
android:listSelector="#CCCCCC"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:dividerHeight="0dp"
android:scrollbars="none" >
</ListView>

<com.example.pingyin.MySeekBar
android:id="@+id/seekbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
<TextView android:layout_width="120dp"
android:layout_height="120dp"
android:text="A"
android:textColor="#ffffffff"
android:id="@+id/text_tag"
android:layout_centerInParent="true"
android:gravity="center"
android:textSize="40sp"
android:visibility="gone"
android:background="@drawable/tip"/>

</RelativeLayout>

List_Item:

<LinearLayout 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"
android:orientation="vertical" >

<TextView
android:id="@+id/left"
android:layout_width="fill_parent"
android:layout_height="45dp"
android:gravity="center_vertical"
android:background="@drawable/leftpy" />
<TextView
android:id="@+id/text"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="35dp"
/>

</LinearLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: