项目中遇到这样的一个需求:物流信息中会返回一个配送人员的手机号码,一个投诉电话,根据快递公司不同,有时候还会返回一个快递单号,这三个标签的字体显示为蓝色并且可点击。第一反应是放不同的TextView或者Button分别处理他们的点击事件,当然是不可取的,因为这些物流信息不止一条,我们看那些电商的物流信息就会发现它们其实是一个列表,数据更新后将最上面一条顶掉显示,就是说这是个listView,每个item里显示物流信息的是一个TextView。那么问题来了:一个TextView如何响应多个不同区域的点击事件呢?尝试了各种力所能及的办法之后做了如下效果
废话差不多了上代码:
public class MainActivity extends Activity {
private TextView mNum;
private Context context;
private String numbers;
private String phone;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
mNum = (TextView) findViewById(R.id.tv_num);
String str = "配送至融科14棟3单元702,配送员电话:18300000000,投诉电话:1211111";
initText(str);
}
private void initText(String str) {
if (getNumbers(str).size() > 0) { //数组长度大于0,取数组第一组数据get(0)
numbers = getNumbers(str).get(0);
}
if (getNumbers(str).size() > 1) { //数组长度大于1,取数组第二组数据get(1)
phone = getNumbers(str).get(1);
}
SpannableString spanableInfo = new SpannableString(str);
spanableInfo.setSpan(new Clickable(clickListener),
str.indexOf(numbers), str.indexOf(numbers) + numbers.length(), //设置需要监听的字符串位置
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spanableInfo.setSpan(new Clickable(click), str.indexOf(phone),
str.indexOf(phone) + phone.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mNum.setText(spanableInfo); //将处理过的数据set到View里
mNum.setMovementMethod(LinkMovementMethod.getInstance());
}
/**
* 判断字符串的正则
*/
private List<String> getNumbers(String content) {
List<String> digitList = new ArrayList<String>();
Pattern p = Pattern.compile("(\\d{5,})");//正则的意思是"大于5位的纯数字"
Matcher m = p.matcher(content);
while (m.find()) {
String find = m.group(1).toString();
digitList.add(find);
}
return digitList;
}
private OnClickListener click = new OnClickListener() {
@Override
public void onClick(View v) {
getClick(phone);
}
};
private OnClickListener clickListener = new OnClickListener() {
@Override
public void onClick(View v) {
getClick(numbers);
}
};
private void getClick(final String s) { //参数为当前点击的数字字符串
new AlertDialog.Builder(context)
.setTitle(s)
.setItems(new String[] { "拨打电话", "复制文本" },
new DialogInterface.OnClickListener() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressWarnings("deprecation")
@Override
public void onClick(DialogInterface dialog,
int which) {
switch (which) {
case 0://跳转拨号
Intent intent = new Intent(
Intent.ACTION_DIAL, Uri
.parse("tel:"
+ s.replaceAll("-",
"")));
startActivity(intent);
break;
case 1://复制文本到系统剪切板
ClipboardManager cmb = (ClipboardManager) context
.getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(s.trim());
break;
}
}
}).show();
}
class Clickable extends ClickableSpan {
private final View.OnClickListener mListener;
public Clickable(View.OnClickListener l) {
mListener = l;
}
/**
* 重写父类点击事件
*/
@Override
public void onClick(View v) {
mListener.onClick(v);
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);// 设置文字下划线不显示
ds.setColor(getResources().getColor(R.color.colorAccent));// 设置字体颜色
}
}
}
布局文件就不放了.
运行效果图:
没什么技术含量,初学者或者同样需求的可以看看.
另外求大神指导这样的需求是不是还有更好的解决办法,冥冥之中感觉应该有,但是目前是不得知,求指点.