InCallTouchUi继承FrameLayout,Phone是通过InCallScreen管理整个界面,通过电话不同状态来显示需要的界面。该类主要管理来电接听、挂断、静音控制、多通电话切换、录音、键盘显示等功能。

1、InCallTouchUi通过构造能加载布局同时初始化PhoneApp对象:

public InCallTouchUi(Context context, AttributeSet attrs) {
        super(context, attrs);

        if (DBG) log("InCallTouchUi constructor...");
        if (DBG) log("- this = " + this);
        if (DBG) log("- context " + context + ", attrs " + attrs);

        // Inflate our contents, and add it (to ourself) as a child.
        LayoutInflater inflater = LayoutInflater.from(context);
        inflater.inflate(
                R.layout.incall_touch_ui,  // resource
                this,                      // root
                true);

        mApp = PhoneApp.getInstance();
}

2、在onFinishInflate()获取子控件的引用,这里需要注意MultiWaveView,该控件是自定义控件,及我们见到的滑动接听和挂断,在framework层进行处理,我们看看它是如何显示和隐藏:

//ringingCall) 理所就是当Call状态为响铃状态时显示
private void showIncomingCallWidget(Call ringingCall) {

      //部分代码省略,其他为显示动画
      mIncomingCallWidget.setVisibility(View.VISIBLE);
            
}
//隐藏方法
 private void hideIncomingCallWidget() {
  //部分代码省略,其他为显示动画
      mIncomingCallWidget.setVisibility(View.GONE);
    
 }

//有啦显示和隐藏方法,看在哪通过状态控制
 void updateState(CallManager cm) {

 //通过CallManager获取当前状态
  Phone.State state = cm.getState(); 
 
 //showIncomingCallControls)是boolean状态标识
  if (showIncomingCallControls) {
            if (DBG) log("- updateState: showing incoming call widget...");
            showIncomingCallWidget(ringingCall);

            mApp.notificationMgr.statusBarHelper.enableSystemBarNavigation(false);
        } else {
            hideIncomingCallWidget();
            mApp.notificationMgr.statusBarHelper.enableSystemBarNavigation(true);
        }
 
 //判断电话状态
 if ((ringingCall.getState() != Call.State.IDLE)
                && !fgCallState.isDialing()) {
            if (ringingCall.getState().isAlive()) {
                if (DBG) log("- updateState: RINGING!  Showing incoming call controls...");
                showIncomingCallControls = true;
            }

            long now = SystemClock.uptimeMillis();
            if (now < mLastIncomingCallActionTime + 500) {
                log("updateState: Too soon after last action; not drawing!");
                showIncomingCallControls = false;
            }
        } else {
            // Ok, show the regular in-call touch UI (with some exceptions):
            if (mInCallScreen.okToShowInCallTouchUi()) {
                showInCallControls = true;
            } else {
                if (DBG) log("- updateState: NOT OK to show touch UI; disabling...");
            }
        }

}

//如果我们要修改接听和挂断样式,就可以在这里进行一些改动

3、InCallTouchUi基本不处理具体实现操作,它是如何传递点击事件,在onClick点击方法中,这是对mInCallControls事件处理:

//事件处理传递到InCallScreen 
mInCallScreen.handleOnscreenButtonClick(id);

//传递inCallScreen;对象到InCallTouchUi
 void setInCallScreenInstance(InCallScreen inCallScreen) {
        mInCallScreen = inCallScreen;
 }

4、看看如何使滑动接听和挂断:

//MultiWaveView实现啦OnTriggerListener

 public void onTrigger(View v, int whichHandle) {
        if (DBG) log("onDialTrigger(whichHandle = " + whichHandle + ")...");

        // On any action by the user, hide the widget:
        hideIncomingCallWidget();

        // ...and also prevent it from reappearing right away.
        // (This covers up a slow response from the radio for some
        // actions; see updateState().)
        mLastIncomingCallActionTime = SystemClock.uptimeMillis();

        // The InCallScreen actually implements all of these actions.
        // Each possible action from the incoming call widget corresponds
        // to an R.id value; we pass those to the InCallScreen's "button
        // click" handler (even though the UI elements aren't actually
        // buttons; see InCallScreen.handleOnscreenButtonClick().)

        if (mInCallScreen == null) {
            Log.wtf(LOG_TAG, "onTrigger(" + whichHandle
                    + ") from incoming-call widget, but null mInCallScreen!");
            return;
        }
        switch (whichHandle) {
            case ANSWER_CALL_ID: //接听
                if (DBG) log("ANSWER_CALL_ID: answer!");
                mInCallScreen.handleOnscreenButtonClick(R.id.incomingCallAnswer);
                break;

            case SEND_SMS_ID:      //短信
                if (DBG) log("SEND_SMS_ID!");
                mInCallScreen.handleOnscreenButtonClick(R.id.incomingCallRespondViaSms);
                break;

            case DECLINE_CALL_ID: //挂断
                if (DBG) log("DECLINE_CALL_ID: reject!");
                mInCallScreen.handleOnscreenButtonClick(R.id.incomingCallReject);
                break;

            default:
                Log.wtf(LOG_TAG, "onDialTrigger: unexpected whichHandle value: " + whichHandle);
                break;
        }

        // Regardless of what action the user did, be sure to clear out
        // the hint text we were displaying while the user was dragging.
        mInCallScreen.updateIncomingCallWidgetHint(0, 0);
    }

如果大家需要对来电接听、挂断,及通话界面修改及功能添加可围绕这几部分操作,其具体布局在incalltouchui.xml.中间联系人图片及通话时间号码显示则位于CallCard.

posted on 2013-09-09 14:10  羞涩的流氓  阅读(545)  评论(0编辑  收藏  举报