1. 程式人生 > >Android同一個TextView裡響應多個區域點選事件

Android同一個TextView裡響應多個區域點選事件

    專案中遇到這樣的一個需求:物流資訊中會返回一個配送人員的手機號碼,一個投訴電話,根據快遞公司不同,有時候還會返回一個快遞單號,這三個標籤的字型顯示為藍色並且可點選。第一反應是放不同的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));// 設定字型顏色
        }
    }
}

佈局檔案就不放了.
執行效果圖:


沒什麼技術含量,初學者或者同樣需求的可以看看.

另外求大神指導這樣的需求是不是還有更好的解決辦法,冥冥之中感覺應該有,但是目前是不得知,求指點.