您的位置:首页 > 产品设计 > UI/UE

Android6.0的phone应用源码分析(3)——phone 拨号UI分析

2016-07-23 14:09 771 查看

1.1   原生界面

 

Phone应用的UI设计直接关系到后面的去来电流程,因此有必要对Phone的UI做一定的介绍。下面是Android6.0的原生拨号界面:



1.2   应用界面

Phone的UI入口可以认为是DialtactsActivity.java的onCreate()。

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        Trace.beginSection(TAG + " onCreate");

        super.onCreate(savedInstanceState);

 

        mFirstLaunch = true;//首次launch标志

 

        final Resources resources = getResources();

        mActionBarHeight = resources.getDimensionPixelSize(R.dimen.action_bar_height_large);//获取高度

 

        Trace.beginSection(TAG + " setContentView");

        setContentView(R.layout.dialtacts_activity);//获得布局文件

        Trace.endSection();

        getWindow().setBackgroundDrawable(null);

        //设置视图,actionBar即手机顶部的常驻空间,供页面的切换或标识

        Trace.beginSection(TAG + " setup Views");

        final ActionBar actionBar = getActionBar();

        actionBar.setCustomView(R.layout.search_edittext);//放入“搜索编辑框”

        actionBar.setDisplayShowCustomEnabled(true);

        actionBar.setBackgroundDrawable(null);

        //搜索编辑框设计,首先同构ViewID找到控件

        SearchEditTextLayout searchEditTextLayout =

                (SearchEditTextLayout) actionBar.getCustomView().findViewById(R.id.search_view_container);

        //猜测为输入时的智能提示

        searchEditTextLayout.setPreImeKeyListener(mSearchEditTextLayoutListener);

        //为这个搜索编辑框绑定控制器

        mActionBarController = new ActionBarController(this, searchEditTextLayout);

        //找到编辑控件

        mSearchView = (EditText) searchEditTextLayout.findViewById(R.id.search_view);

        //监听编辑框文字输入

        mSearchView.addTextChangedListener(mPhoneSearchQueryTextListener);

        //声控输入按钮

        mVoiceSearchButton = searchEditTextLayout.findViewById(R.id.voice_search_button);

        //放大镜,位于文本编辑控件的左侧,并绑定Listener

        searchEditTextLayout.findViewById(R.id.search_magnifying_glass)

                .setOnClickListener(mSearchViewOnClickListener);

       //绑定开始查找按钮

        searchEditTextLayout.findViewById(R.id.search_box_start_search)

                .setOnClickListener(mSearchViewOnClickListener);

        searchEditTextLayout.setOnClickListener(mSearchViewOnClickListener);

        //为searchEditTextLayout绑定callBack

        searchEditTextLayout.setCallback(new SearchEditTextLayout.Callback() {

           //返回上一次搜索

            @Override

            public void onBackButtonClicked() {

                onBackPressed();

            }

 

            @Override

            public void onSearchViewClicked() {

//Floating action button (FAB)是一个带有环状阴影的圆形按键,位于 UI之上,用//于显示常用的操作,比如添加新条目、编写邮件等。

              // 当键盘显示时隐藏FAB

                mFloatingActionButtonController.scaleOut();

            }

        });

 

        mIsLandscape = getResources().getConfiguration().orientation

                == Configuration.ORIENTATION_LANDSCAPE;

        //获取floatingActionButton的容器

        final View floatingActionButtonContainer = findViewById(

                R.id.floating_action_button_container);

        //获取floatingActionButton

        ImageButton floatingActionButton = (ImageButton) findViewById(R.id.floating_action_button);

        //监听floatingActionButton

        floatingActionButton.setOnClickListener(this);

        //floatingActionButton控制,由于FAB是浮动的因此需要限定范围,并加以控制

        mFloatingActionButtonController = new FloatingActionButtonController(this,

                floatingActionButtonContainer, floatingActionButton);

        //通过监听者都是this,猜测应该就是floatingActionButton

        ImageButton optionsMenuButton =

                (ImageButton) searchEditTextLayout.findViewById(R.id.dialtacts_options_menu_button);

        optionsMenuButton.setOnClickListener(this);

       //为搜索添加设置菜单

        mOverflowMenu = buildOptionsMenu(searchEditTextLayout);

        //绑定监听者

        optionsMenuButton.setOnTouchListener(mOverflowMenu.getDragToOpenListener());

 

        //此处猜测为常用联系人

        // Add the favorites fragment but only if savedInstanceState is null. Otherwise the

        // fragment manager is responsible for recreating it.

        if (savedInstanceState == null) {

            getFragmentManager().beginTransaction()

                    .add(R.id.dialtacts_frame, new ListsFragment(), TAG_FAVORITES_FRAGMENT)

                    .commit();

        } else {

            mSearchQuery = savedInstanceState.getString(KEY_SEARCH_QUERY);

            mInRegularSearch = savedInstanceState.getBoolean(KEY_IN_REGULAR_SEARCH_UI);

            mInDialpadSearch = savedInstanceState.getBoolean(KEY_IN_DIALPAD_SEARCH_UI);

            mFirstLaunch = savedInstanceState.getBoolean(KEY_FIRST_LAUNCH);

            mShowDialpadOnResume = savedInstanceState.getBoolean(KEY_IS_DIALPAD_SHOWN);

            mActionBarController.restoreInstanceState(savedInstanceState);

        }

 

        final boolean isLayoutRtl = DialerUtils.isRtl();

        //处理划屏动画加载,界面切换

        if (mIsLandscape) {//左右滑屏为切换

            mSlideIn = AnimationUtils.loadAnimation(this,

                    isLayoutRtl ? R.anim.dialpad_slide_in_left : R.anim.dialpad_slide_in_right);

            mSlideOut = AnimationUtils.loadAnimation(this,

                    isLayoutRtl ? R.anim.dialpad_slide_out_left : R.anim.dialpad_slide_out_right);

        } else {//上下滑屏为常驻返回等菜单显示与隐藏

            mSlideIn = AnimationUtils.loadAnimation(this, R.anim.dialpad_slide_in_bottom);

            mSlideOut = AnimationUtils.loadAnimation(this, R.anim.dialpad_slide_out_bottom);

        }

 

        mSlideIn.setInterpolator(AnimUtils.EASE_IN);

        mSlideOut.setInterpolator(AnimUtils.EASE_OUT);

        //绑定滑屏监听者,这样才能实现功能

        mSlideIn.setAnimationListener(mSlideInListener);

        mSlideOut.setAnimationListener(mSlideOutListener);

        //拖拽处理

        mParentLayout = (FrameLayout) findViewById(R.id.dialtacts_mainlayout);

        mParentLayout.setOnDragListener(new LayoutOnDragListener());

        floatingActionButtonContainer.getViewTreeObserver().addOnGlobalLayoutListener(

                new ViewTreeObserver.OnGlobalLayoutListener() {

                    @Override

                    public void onGlobalLayout() {

                        final ViewTreeObserver observer =

                                floatingActionButtonContainer.getViewTreeObserver();

                        if (!observer.isAlive()) {

                            return;

                        }

                        observer.removeOnGlobalLayoutListener(this);

                        int screenWidth = mParentLayout.getWidth();

                        mFloatingActionButtonController.setScreenWidth(screenWidth);

                        mFloatingActionButtonController.align(

                                getFabAlignment(), false /* animate */);

                    }

                });

 

        Trace.endSection();

 

        Trace.beginSection(TAG + " initialize smart dialing");

        mDialerDatabaseHelper = DatabaseHelperManager.getDatabaseHelper(this);

        SmartDialPrefix.initializeNanpSettings(this);

        Trace.endSection();

        Trace.endSection();

    }

以下为其布局XML

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/dialtacts_mainlayout"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical"

    android:focusable="true"

    android:focusableInTouchMode="true"

    android:clipChildren="false"

    android:background="@color/background_dialer_light">

 

    <FrameLayout

        android:id="@+id/dialtacts_container"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:clipChildren="false">

        <!-- The main contacts grid -->

        <FrameLayout

            android:layout_height="match_parent"

            android:layout_width="match_parent"

            android:id="@+id/dialtacts_frame"

            android:clipChildren="false" />

    </FrameLayout>

 

    <FrameLayout

        android:id="@+id/floating_action_button_container"

        android:background="@drawable/fab_blue"

        android:layout_width="@dimen/floating_action_button_width"

        android:layout_height="@dimen/floating_action_button_height"

        android:layout_marginBottom="@dimen/floating_action_button_margin_bottom"

        android:layout_gravity="center_horizontal|bottom">

 

        <ImageButton

            android:id="@+id/floating_action_button"

            android:background="@drawable/floating_action_button"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:contentDescription="@string/action_menu_dialpad_button"

            android:src="@drawable/fab_ic_dial"/>

 

    </FrameLayout>

 

    <!-- Host container for the contact tile drag shadow -->

    <FrameLayout

        android:id="@+id/activity_overlay"

        android:layout_height="match_parent"

        android:layout_width="match_parent">

        <ImageView

            android:id="@+id/contact_tile_drag_shadow_overlay"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:visibility="gone"

            android:importantForAccessibility="no" />

    </FrameLayout>

</FrameLayout>

1.3   拨号视图

拨号视图加载DialpadFragment .onCreateView():

    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {

        Trace.beginSection(TAG + " onCreateView");

        Trace.beginSection(TAG + " inflate view");

        //来自百度:在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于//findViewById()。不同点是LayoutInflater是用来找res/layout/下的xml布局文件,//并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、//TextView等)。具体作用:
1、对于一个没有被载入或者想要动态载入的界面,都需要使用//LayoutInflater.inflate()来载入;

        final View fragmentView = inflater.inflate(R.layout.dialpad_fragment, container,

                false);

        Trace.endSection();

        Trace.beginSection(TAG + " buildLayer");

        fragmentView.buildLayer();

        Trace.endSection();

 

        Trace.beginSection(TAG + " setup views");

 

        mDialpadView = (DialpadView) fragmentView.findViewById(R.id.dialpad_view);

        mDialpadView.setCanDigitsBeEdited(true);

        mDigits = mDialpadView.getDigits();

        mDigits.setKeyListener(UnicodeDialerKeyListener.INSTANCE);

        mDigits.setOnClickListener(this);//将自己设置为拨号按钮的监听者

        mDigits.setOnKeyListener(this);//设置按键事件监听者

        mDigits.setOnLongClickListener(this);

        mDigits.addTextChangedListener(this);

        mDigits.setElegantTextHeight(false);

        PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(getActivity(), mDigits);

        // 检查键盘的存在

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

        if (oneButton != null) {//如果存在设定监听者

            configureKeypadListeners(fragmentView);

        }

       //del键设置

        mDelete = mDialpadView.getDeleteButton();

 

        if (mDelete != null) {

            mDelete.setOnClickListener(this);

            mDelete.setOnLongClickListener(this);

        }

        //空格键设置

        mSpacer = fragmentView.findViewById(R.id.spacer);

        mSpacer.setOnTouchListener(new View.OnTouchListener() {

            @Override

            public boolean onTouch(View v, MotionEvent event) {

                if (isDigitsEmpty()) {

                    if (getActivity() != null) {

                        return ((HostInterface) getActivity()).onDialpadSpacerTouchWithEmptyQuery();

                    }

                    return true;

                }

                return false;

            }

        });

 

        mDigits.setCursorVisible(false);

 

        // Set up the "dialpad chooser" UI; see showDialpadChooser().

        mDialpadChooser = (ListView) fragmentView.findViewById(R.id.dialpadChooser);

        mDialpadChooser.setOnItemClickListener(this);

        //FAB设计

        final View floatingActionButtonContainer =

                fragmentView.findViewById(R.id.dialpad_floating_action_button_container);

        final ImageButton floatingActionButton =

                (ImageButton) fragmentView.findViewById(R.id.dialpad_floating_action_button);

        floatingActionButton.setOnClickListener(this);

        mFloatingActionButtonController = new FloatingActionButtonController(getActivity(),

                floatingActionButtonContainer, floatingActionButton);

        Trace.endSection();

        Trace.endSection();

        return fragmentView;

    }

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