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;

}

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

  1. [导入]SunriseUpload.0.9.1的源码分析(七)

    接着分析了几个小时的SunriseUpload.0.9.1的源码. 终于明白了作者的整体思路.在此就做一个总结. 首先,要想能上传很大的文件,我们就必须编写一个HttpModule来自己处理用户上传的 ...

  2. 分析开源项目源码,我们该如何入手分析?(授人以渔)

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:牛人 20000 字的 Spring Cloud 总结,太硬核了~ 1 前言 本文接上篇文章跟大家聊聊我们为什么 ...

  3. Anaconda Python3.6 OpenCV4.1.0 Ubuntu 16.04源码编译

    Anaconda Python3.6 OpenCV4.1.0 Ubuntu 16.04源码编译 转载于:https://blog.csdn.net/phdsky/article/details/782 ...

  4. android 5.0播放swf flash源码Demo

    android 5.0播放swf flash源码Demo 安卓5.0flash播放源码 android flash 播放器 swf 由于之前webview方法播放flash在新的系统中不可用.所以so ...

  5. 点云配准2:icp算法在PCL1.10.0上的实现+源码解析

    目录 本文最后实现的配准实例 点云配准系列 准备 程序结构 主程序 1.为什么要降采样 2.体素降采样原理 3.点云更新 icp 配准前的参数设置 icp配准算法内部 对应点对确定(determine ...

  6. 2022全新Ripro日主题V9.0升级修正版源码+美化包和插件

    正文: 2022全新Ripro日主题V9.0升级修正版源码+美化包和插件,我现在分享的是RiPro9.0的二开版本,这个模板是本人花了Q找人弄到的,我给各位弄了2个美化包和全屏水印以及防复制插件. 模 ...

  7. (已更新)最新版本梦想贩卖机2.0.4小程序源码

    环境要求 PHP+MYSQL+微擎+小程序 修复 小程序卡密资源库存为0时继续任务获取的bug 新增  后台资源列表页一键置顶.一键取消置顶功能 优化  后台资源列表页置顶排序优先 优化  去除小程序 ...

  8. 洗衣店v2.5.0微信小程序源码下载

    新增功能 1.订单状态 通知 2.管理员手机端增加会员充值功能 3.优化下单页面功能 4.增加管理员端 跑腿人员结账功能 5.增加管理员收银功能 6.增加套餐卡(月/季/年卡)包月功能 7.增加会员功 ...

  9. 云开发喝酒神器2.0微信小程序源码 附搭建教程【源码好优多】

    简介 云开发喝酒神器2.0微信小程序源码 附搭建教程 微信小程序云开发喝酒神器2.0微信小程序源码(带流量主),云开发小程序无法服务器即可搭建,配置有安装文档教程. 下方资源地址 云开发喝酒神器2.0 ...

最新文章

  1. 《深入理解Java虚拟机》读书笔记五
  2. boost::serial_executor相关的测试程序
  3. angular 动画_如何在Angular 6中使用动画
  4. 负数比较大小_人教版六下【第一单元】负数比较负数的大小
  5. 织梦cms第四版仿七猫技术导航源码 附安装教程
  6. 【AI视野·今日Robot 机器人论文速览 第二十期】Thu, 8 Jul 2021
  7. TreeView的基本使用 1205
  8. Ubuntu安装过程中的问题
  9. python 点击按钮 click_用selenium和Python单击“onclick”按钮
  10. python 速成学堂_Python 与数据科学入门
  11. LINUX SHELL中while循环和遍历参数
  12. HTML资源嗅探,scrapy-2 嗅探网站,解析HTML
  13. PMP考试扫盲:超详细的PMP考试小白攻略,必看篇
  14. 【批处理】快速批量修改特定文件夹的文件名
  15. mysql sniffer 安装_ubunt 安装mysql-sniffer
  16. 三星为Ativ S发布WP8更新
  17. 打印自身源代码的程序
  18. 机器学习老中医:利用学习曲线诊断模型的偏差和方差
  19. 纸箱制作机器人邮箱_纸箱机器人衣服制作方法
  20. 苹果x计算机怎么恢复,苹果手机怎样找回备忘录,电脑小白数据恢复全攻略

热门文章

  1. WebService:全网最全WebService技术简介
  2. WM SCM630 笔记 Unit 4 Putaway Control (1)
  3. linux:关于服务器终端自动掉线的问题总结
  4. 推荐美国简单的选项卡功能实现
  5. vim 从嫌弃到依赖(0)——概述
  6. java 导出txt,java生成txt,并写入内容,java读取txt文本内容
  7. MCS51霓虹灯_Proteus仿真
  8. [附源码]计算机毕业设计大学生心理测评系统Springboot程序
  9. dw php 网站上传,Dreamweaver怎么上传站点到服务器
  10. NodeJS 响应式故宫文化宣传网站计算机毕设源码61557