在Android4.0中Contacts拨号盘点击事件详析(源码)

前文有朋友回复说想深入了解一下拨号盘源码的实现,也许是上文中,我对此说的不够细致,现将拨号盘点击事件及处理,拨号键的点击等。

对于拨号盘的界面显示,在此就不在浪费大家的时间,不清楚的朋友可以点击下面的连接(拨号盘界面的显示)。下面主要描述一下点击拨号盘中某个按钮后,是怎么将对应的数字显示在输入框中和点击控制键(拨号,删除,搜索)所触发的事件。

1.拨号盘中数字键

DialpadFragment.java中,通过onCreateView方法,加载出了拨号界面,在该方法中有一句这样的令人费解的代码

  View oneButton = fragmentView.findViewById(R.id.one);

if (oneButton != null) {

  setupKeypad(fragmentView);

}

 首先通过View类的findViewById方法获得oneButton对象,当oneButton不为null的时候才绑定键盘。然后调用setupKeypad(fragmentView)方法,进行键盘监听事件的绑定,现截取代码片段与大家分享。

private void setupKeypad(View fragmentView) {

        // Setup the listeners for the buttons

View view = fragmentView.findViewById(R.id.one);

view.setOnClickListener(this);

view.setOnLongClickListener(this);

….

}

废话不多说,看代码!

 View view = fragmentView.findViewById(R.id.one); 

   通过View类的findViewById方法获得oneButton按钮,下面将分设置点击事件和长按事件两部分来进行描述。

1.1数字键盘的点击事件

view.setOnClickListener(this);

为其设置点击事件监听器。此时该监听器为当前对象this,看样子该Fragment实现了viewonClickListener接口,是不是呢?我们看代码

DialpadFragment extends Fragment implements View.OnClickListener

好,既然如此,肯定要覆盖onClick(View view) 方法,我们继续跟进

onClick方法的片段如下

@Override

public void onClick(View view) {

     switch (view.getId()) {

    case R.id.one: {

           playTone(ToneGenerator.TONE_DTMF_1);

           keyPressed(KeyEvent.KEYCODE_1);

            return;

     }//case结束       。。。

//switch结束

//onClick结束

 当点击按钮1 时出会触发onClick事件,然后进入R.id.one分支

 好,如果该分支后,会看到两个方法的调用,继续跟进playTone(ToneGenerator.TONE_DTMF_1);

这个方法主要是根据不同的按键发出不同的声音,最总调到本地方法,和显示关系不大,就不做详细描述,有需要的朋友自己看一下,java代码比较简单。

keyPressed(KeyEvent.KEYCODE_1);

我们来看这句的代码

 private void keyPressed(int keyCode) {

  mHaptic.vibrate();

  KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);

  mDigits.onKeyDown(keyCode, event);

  final int length = mDigits.length();

 if (length == mDigits.getSelectionStart() && length == mDigits.getSelectionEnd()) {

            mDigits.setCursorVisible(false);

   }

}

第一句mHaptic.vibrate();

我们先来看看mHaptic 到底是个什么东西吧

// Vibration (haptic feedback) for dialer key presses.

private HapticFeedback mHaptic = new HapticFeedback();

HapticFeedback是一个Android定义的类,该类的vibrate()方法的大体上就是是手机震动一下。

继续跟进

KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);

mDigits.onKeyDown(keyCode, event);

通过传递过来的键盘码,构造键盘点击事件,然后将该事件交给EditText的子类对象mDigits进行处理。处理后就会将keyCode所代表的字符显示在输入框内。

final int length = mDigits.length();

 if (length == mDigits.getSelectionStart() && length == mDigits.getSelectionEnd()) {

   mDigits.setCursorVisible(false);

}

后面几句,就是设置光标的可见与否。onCilck事件我们已经分析完毕,所有按键的点击均会触发该事件,回过头来,我们继续跟进setupKeypad方法。

1.2数字键盘的长按事件

view.setOnLongClickListener(this);

  view对象设置长按事件,长按事件的监听器还是this,当前的对象,不用多说,该类肯定也是实现了ViewOnLongClickListener接口。我们直接看onLongClick方法。

相关代码片段如下:

public boolean onLongClick(View view) {

    final Editable digits = mDigits.getText();

    int id = view.getId();

    switch (id) {

           。。。

     case R.id.one: {

         if (isDigitsEmpty()) {

            if (isVoicemailAvailable()) {

               callVoicemail();

             } else if (getActivity() != null) {

            DialogFragment dialogFragment = ErrorDialogFragment.newInstance(

                    R.string.dialog_voicemail_not_ready_title,

                    R.string.dialog_voicemail_not_ready_message);

dialogFragment.show(getFragmentManager(), "voicemail_not_ready");

             }

             return true;

          }

           return false;

        }//one 处理结束

            。。。

}//switch 语句结束

return false;

}//onLongClick方法结束

公共代码分析

final Editable digits = mDigits.getText();

    int id = view.getId();

获得输入框EditText的输入数据,获得viewid号码,用于switch语句的分支确认。

通过上面的基本操作,我们找到了长按1事件的主体,R.id.one分支

映入眼帘的第一句

  if (isDigitsEmpty())

看代码

private boolean isDigitsEmpty() {

        return mDigits.length() == 0;

}

简单的说就是判断该输入框内是否有输入

当没有输入时首先执行isVoicemailAvailable()方法,我们看源码

private boolean isVoicemailAvailable() {

        try {

            return (TelephonyManager.getDefault().getVoiceMailNumber() != null);

        } catch (SecurityException se) {

            // Possibly no READ_PHONE_STATE privilege.

            Log.w(TAG, "SecurityException is thrown. Maybe privilege isn't sufficient.");

        }

        return false;

    }

通过源码可以看出,该方法实际上是判断了VoiceMailNumber是否为null,按照源码中的意思,这个条件永远成立,有兴趣的朋友可以去看一下源码。

当没有输入且可以拨打voicemail时执行如下

             callVoicemail();

我们查看源码

public void callVoicemail() {

        startActivity(newVoicemailIntent());

        mDigits.getText().clear(); // TODO: Fix bug 1745781

        getActivity().finish();

}

继续跟进

private Intent newVoicemailIntent() {

        final Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,

                      Uri.fromParts("voicemail", EMPTY_NUMBER, null));

        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        return intent;

}

不用多说,是跳转到另一个动作,其实voicemail类似于快捷拨号,在settings中可以设置成自己需要拨打的特殊号码,这样当长按1时,就可以自动拨打出去。

在不符合上面条件的前提下

当没有输入而Activity不等于null时执行dialogFragment 的弹出操作,在此不做过多的说明。

通过对1按键的描述,我想大家已经可以按该过程有所了解。

2.拨号盘中删除键

我们从onCreateView方法中,找到

mDelete = mAdditionalButtonsRow.findViewById(R.id.deleteButton);

mDelete.setOnClickListener(this);

mDelete.setOnLongClickListener(this);

接下来我们分删除键的点击事件和长按事件两部分描述。

 2.1 删除键的点击描述

通过上文mDelete.setOnClickListener(this),我们知道,单击事件需要找onClick方法,直接定位到指定位置。

  public void onClick(View view) {

        switch (view.getId()) {

             。。。。。。。。

        case R.id.deleteButton: {

                keyPressed(KeyEvent.KEYCODE_DEL);

                return;

         }

。。。。。。

        

   同上,最终调用

KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL);

   mDigits.onKeyDown(keyCode, KeyEvent.KEYCODE_DEL);

   mDigits就会将光标的前一个位置的字符删除。

2.2 删除键长按描述

废话不说,直接看定位代码

   public boolean onLongClick(View view) {

               ………………..

                switch (id) {

            case R.id.deleteButton: {

                digits.clear();

                mDelete.setPressed(false);

                return true;

            }

………..

}

}

Digits.clear()方法,直接清空输入框内的数字

mDelete.setPressed(false); 设置删除键的按下状态

3.拨号盘中拨号键

同理,在onClick方法中找到拨号键

           …………..

  case R.id.dialButton: {

              mHaptic.vibrate();

              dialButtonPressed();

              return;

            }

  ……………….

mHaptic.vibrate(); 震动一下

继续查看dialButtonPressed()方法

在该方法中,通过输入域内是否为null建立了两个分支结构,在两个分支中均做了比较多的分支,最终页面实现跳转或对话框的弹出等,比较简单,需要的朋友请自己查看dialButtonPressed()方法的源码。

 

4.拨号盘中搜索键

搜索按键的处理与其它按键的处理类似,但是又有些不同,在后文将详细的分析一下,感兴趣的朋友自己走一下onClick流程。

 

希望我的分析,对朋友你有所帮助。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值