QuickContact分析及其弹出窗口实现
2013-08-06 10:21
405 查看
一、简介
QuickContact是为了应用程序能够快速方便的访问联系人,并且快速的运用联系人的信息执行相应操作而设计的。最常见的在Contacts应用程序中如下图所示:
![](http://img1.51cto.com/attachment/201103/210311708.png)
在Activity中存在一个图标,点击该图标后弹出一个窗口,窗口中会有几个图标,不同的图标表示针对该联系人进行的不同操作,比如打电话,发短信,发送邮件,进入主页等等。图标的显示和不显示取决于该联系人是否存在该种操作相关的信息。比如,如果该联系人中如果存在邮箱的话,就可以出现发送邮件的图标,否则就不会出现。
二、在自己的应用程序中应用QuickContact
在自己的程序中加入QuickContact十分方便,可以用Framework中的组件QuickContactBadge。
比如,我们创建一个Activity,设置它的layout如下:
Activity的onCreate代码如下:
主要还有一点,要在AndroidManifest中设置android.permission.READ_CONTACTS的权限,否则,不会弹出窗口,而是直接进入Contacts中的联系人详情界面。
运行效果如图:
![](http://img1.51cto.com/attachment/201103/210616275.jpg)
由于本文不是针对QuickContactBadge的详细讲解,而是讲解它的实现方法,从而能够见贤思齐,设计出类似的功能。要了解QuickContactBadge的详细用法可以看Android文档,和google。
三、结构
系统在实现QuickContact包含三部分:
1、弹出界面。
2、ContactContract中的调用接口
3、组件QuickContactBadge。
弹出界面在应用程序Contacts中编写,这也是QuickContact的主要部分。
ContactContract为方便使用QuickContact定义了几个函数,可以在不同的情形下显示出QuickContact。
QuickContactBadge是为了方便开发者使用QuickContact,设计的一个组件,开发者只需要在自己的Layout中加入该组件,便可以方便的使用。而且该组件还支持根据邮箱、电话号码等指定某个联系人。实际上,QuickContactBadge在单击的时候调用了ContactContract中的函数来显示QuickContact。因此,实际上,ContactContract中的QuickContact可以完成更多情况下QuickContact的显示。
框图待补充
四、QuickContactActivity和QuickContactWindow
为了使弹出窗口可以跨进程共享,弹出界面的实现实际上是采用了透明Activity贴上一层View的方式。透明的Activity无疑就是QuickContactActivity了,在该Activity中含有一个QuickContactWindow的成员,通过QuickContactWindow将一个View贴到该Activity上。
那么,QuickContactWindow是如何将View贴到Activity上的呢?大家需要了解Activity,View,Window和WindowManager之间的关系,不明白的赶紧查下资料。
QuickContactWindow在创建时就会创建一个PhoneWindow,然后设置它的布局,进行一系列的初始化,在显示的时候,会查询该联系人的信息,查询完毕后生成该联系人的视图,之后获得PhoneWindow的根节点,将该根节点加到WindowManager中,该View就会被贴到Activity中去了。
五、ContactContract中的QuickContact
ContactContract中的QuickContact的显示函数,实际上就是用Intent开启了QuickContactActivity。
六、QuickContactBadge
QuickContactBadge继承自ImageView,所以所有ImageView的函数都可以用来设置QuickContactBadge。当点击QuickContactBadge时,它调用了ContactContract中的QuickContact显示函数。
为了为开发者提供方便,QuickContactBadge可以根据开发者提供的邮箱或电话号码等信息找到该联系人。
七、见贤思齐
1、PopupWindow弹出窗口实现
其实,单纯实现弹出窗口是很简单的,Android为我们提供了PopupWindow这个组件。通过这个组件我们可以将我们的窗口显示在顶层,并且可以通过坐标来决定它的位置。如下面的代码:
显示效果如下:
![](http://img1.51cto.com/attachment/201103/210919463.png)
需要注意的一点就是,PopupWindow在Activity的onCreate函数中显示是会出现错误的,用户可以自行验证。解决方法不是本文暂不研究。
2、Dialog的弹出窗口实现
我们常见的Dialog都是居中显示的,而且背景会变暗,因此要Dialog实现弹出窗口的效果,就要解决任意位置显示和背景不变暗的问题。
在Activity中写如下代码:
在onPrepareDialog函数中,我们获得了Dialog的Window,然后对位置和宽度进行了设置,并且通过Flag取消了背景变暗的效果,最后我们得到的结果如下图:
![](http://img1.51cto.com/attachment/201103/211058252.png)
其实,带有Dialog主题的Activity也可以实现该效果,不过本人没有实现背景不变暗,故不将代码贴上了。
3、跨进程共享弹出窗口设计
我们能不能实现类似于QuickContact那样的弹出窗口跨进程共享呢?当然是可以的。
可能我们会想到用一个透明的Activity,然后显示一个PopupWindow来实现,但是PopupWindow我们之前说过,在Activity的onCreate函数中显示时会有问题。
我们也可能还会想到一个透明的Activity加一个Dialog来显示,但是我们也知道,Dialog并不是像PopupWindow那样是轻量级的,仅仅一个Activity的显示就够耗费了,再显示一个Dialog,那么耗费就更大了。
我们可能还会想到用QuickContact的方式,创建一个Window,然后将该Window的根View贴到透明Activity上,然而,不幸的是,创建Window的函数是非公开的。
其实,我们不需要创建一个Window,也能将View贴到Activity之中。见如下代码:
该Activity要设置成透明,可以在AndroidManifest中加入android:theme = "@android:style/Theme.Translucent"。
调用的代码如下:
最终效果如下:
![](http://img1.51cto.com/attachment/201103/211256835.png)
4、跨进程共享弹出窗口的优化
由于跨进程共享的弹出窗口是重启的一个新的Activity,因此花销是比较大的,为了提高效率,我们需要做一些工作。
首先,设置Activity的launchMode为singleTop,通过该设置,当该Activity已经在栈顶时,可以直接调用onNewIntent函数而不是重新创建。
其次,设置Activity的taskAffinity为其他值,如:android:taskAffinity = "com.winuxxan.dialogactivity",并且开启Activity时,设置flag:
这样,该Activity在一个单独的Task中,并且只要该Task堆栈中存在该Activity,那么就不会重新创建,而是调用onNewIntent。
再次,当隐藏该窗口时,不是销毁掉,而是moveTaskToBack,这样再次显示时就不是重新创建,而是将后台Task放到前台。
通过这些手段就可以显著的提高该弹出窗口的效率。
QuickContact是为了应用程序能够快速方便的访问联系人,并且快速的运用联系人的信息执行相应操作而设计的。最常见的在Contacts应用程序中如下图所示:
![](http://img1.51cto.com/attachment/201103/210311708.png)
在Activity中存在一个图标,点击该图标后弹出一个窗口,窗口中会有几个图标,不同的图标表示针对该联系人进行的不同操作,比如打电话,发短信,发送邮件,进入主页等等。图标的显示和不显示取决于该联系人是否存在该种操作相关的信息。比如,如果该联系人中如果存在邮箱的话,就可以出现发送邮件的图标,否则就不会出现。
二、在自己的应用程序中应用QuickContact
在自己的程序中加入QuickContact十分方便,可以用Framework中的组件QuickContactBadge。
比如,我们创建一个Activity,设置它的layout如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <QuickContactBadge android:id="@+id/badge_small" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon"> </QuickContactBadge> </LinearLayout>
Activity的onCreate代码如下:
QuickContactBadge smallBadge = (QuickContactBadge) findViewById(R.id.badge_small); smallBadge.assignContactFromEmail("winuxxan@gmail.com", true); smallBadge.setMode(ContactsContract.QuickContact.MODE_LARGE);
主要还有一点,要在AndroidManifest中设置android.permission.READ_CONTACTS的权限,否则,不会弹出窗口,而是直接进入Contacts中的联系人详情界面。
运行效果如图:
![](http://img1.51cto.com/attachment/201103/210616275.jpg)
由于本文不是针对QuickContactBadge的详细讲解,而是讲解它的实现方法,从而能够见贤思齐,设计出类似的功能。要了解QuickContactBadge的详细用法可以看Android文档,和google。
三、结构
系统在实现QuickContact包含三部分:
1、弹出界面。
2、ContactContract中的调用接口
3、组件QuickContactBadge。
弹出界面在应用程序Contacts中编写,这也是QuickContact的主要部分。
ContactContract为方便使用QuickContact定义了几个函数,可以在不同的情形下显示出QuickContact。
QuickContactBadge是为了方便开发者使用QuickContact,设计的一个组件,开发者只需要在自己的Layout中加入该组件,便可以方便的使用。而且该组件还支持根据邮箱、电话号码等指定某个联系人。实际上,QuickContactBadge在单击的时候调用了ContactContract中的函数来显示QuickContact。因此,实际上,ContactContract中的QuickContact可以完成更多情况下QuickContact的显示。
框图待补充
四、QuickContactActivity和QuickContactWindow
为了使弹出窗口可以跨进程共享,弹出界面的实现实际上是采用了透明Activity贴上一层View的方式。透明的Activity无疑就是QuickContactActivity了,在该Activity中含有一个QuickContactWindow的成员,通过QuickContactWindow将一个View贴到该Activity上。
那么,QuickContactWindow是如何将View贴到Activity上的呢?大家需要了解Activity,View,Window和WindowManager之间的关系,不明白的赶紧查下资料。
QuickContactWindow在创建时就会创建一个PhoneWindow,然后设置它的布局,进行一系列的初始化,在显示的时候,会查询该联系人的信息,查询完毕后生成该联系人的视图,之后获得PhoneWindow的根节点,将该根节点加到WindowManager中,该View就会被贴到Activity中去了。
五、ContactContract中的QuickContact
ContactContract中的QuickContact的显示函数,实际上就是用Intent开启了QuickContactActivity。
六、QuickContactBadge
QuickContactBadge继承自ImageView,所以所有ImageView的函数都可以用来设置QuickContactBadge。当点击QuickContactBadge时,它调用了ContactContract中的QuickContact显示函数。
为了为开发者提供方便,QuickContactBadge可以根据开发者提供的邮箱或电话号码等信息找到该联系人。
七、见贤思齐
1、PopupWindow弹出窗口实现
其实,单纯实现弹出窗口是很简单的,Android为我们提供了PopupWindow这个组件。通过这个组件我们可以将我们的窗口显示在顶层,并且可以通过坐标来决定它的位置。如下面的代码:
private void showPopupWindow(int x, int y, int width, int height) { TextView textView = new TextView(this); textView.setText("Hello popupWindow"); textView.setBackgroundColor(Color.CYAN); PopupWindow popupWindow = new PopupWindow(textView, width, height); popupWindow.showAtLocation(getWindow().getDecorView(), Gravity.NO_GRAVITY, x, y); }
显示效果如下:
![](http://img1.51cto.com/attachment/201103/210919463.png)
需要注意的一点就是,PopupWindow在Activity的onCreate函数中显示是会出现错误的,用户可以自行验证。解决方法不是本文暂不研究。
2、Dialog的弹出窗口实现
我们常见的Dialog都是居中显示的,而且背景会变暗,因此要Dialog实现弹出窗口的效果,就要解决任意位置显示和背景不变暗的问题。
在Activity中写如下代码:
public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //在指定位置显示对话框 showDialog(100, 100, 200, 200); } @Override protected Dialog onCreateDialog(int id, Bundle args) { return new AlertDialog.Builder(this) .setTitle("Hello Dialog!") .setMessage("Hello Dialog") .create(); } @Override protected void onPrepareDialog(int id, Dialog dialog, Bundle args) { switch (id) { case 1: { //设置对话框的属性 Window window = dialog.getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); lp.x = args.getInt("x"); lp.y = args.getInt("y"); lp.width = args.getInt("width"); lp.height = args.getInt("height"); lp.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND; dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.argb(0, 0, 0, 0))); } break; default: break; } super.onPrepareDialog(id, dialog, args); } private void showDialog(int x, int y, int width, int height) { Bundle bundle = new Bundle(); bundle.putInt("x", x); bundle.putInt("y", y); bundle.putInt("width", width); bundle.putInt("height", height); showDialog(1, bundle); } }
在onPrepareDialog函数中,我们获得了Dialog的Window,然后对位置和宽度进行了设置,并且通过Flag取消了背景变暗的效果,最后我们得到的结果如下图:
![](http://img1.51cto.com/attachment/201103/211058252.png)
其实,带有Dialog主题的Activity也可以实现该效果,不过本人没有实现背景不变暗,故不将代码贴上了。
3、跨进程共享弹出窗口设计
我们能不能实现类似于QuickContact那样的弹出窗口跨进程共享呢?当然是可以的。
可能我们会想到用一个透明的Activity,然后显示一个PopupWindow来实现,但是PopupWindow我们之前说过,在Activity的onCreate函数中显示时会有问题。
我们也可能还会想到一个透明的Activity加一个Dialog来显示,但是我们也知道,Dialog并不是像PopupWindow那样是轻量级的,仅仅一个Activity的显示就够耗费了,再显示一个Dialog,那么耗费就更大了。
我们可能还会想到用QuickContact的方式,创建一个Window,然后将该Window的根View贴到透明Activity上,然而,不幸的是,创建Window的函数是非公开的。
其实,我们不需要创建一个Window,也能将View贴到Activity之中。见如下代码:
public class PopupActivity extends Activity { private WindowManager mWindowManager; private View mAddedView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); int x = getIntent().getIntExtra("x", 0); int y = getIntent().getIntExtra("y", 0); int width = getIntent().getIntExtra("width", 200); int height = getIntent().getIntExtra("height", 200); //该TextView要贴到透明的Activity上 TextView textView = new TextView(this); textView.setBackgroundColor(Color.CYAN); textView.setWidth(width); textView.setHeight(height); mAddedView = textView; textView.setOnKeyListener(new OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { mWindowManager.removeView(mAddedView); finish(); return false; } }); WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.x = x; params.y = y; params.width = width; params.height = height; params.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND; params.packageName = this.getPackageName(); //贴到透明Activity上 mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE); mWindowManager.addView(textView, params); } }
该Activity要设置成透明,可以在AndroidManifest中加入android:theme = "@android:style/Theme.Translucent"。
调用的代码如下:
private void showPopupActivity(int x, int y, int width, int height) { Intent intent = new Intent(); intent.setClass(this, DialogActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); intent.putExtra("x", x); intent.putExtra("y", y); intent.putExtra("width", width); intent.putExtra("height", height); startActivity(intent); }
最终效果如下:
![](http://img1.51cto.com/attachment/201103/211256835.png)
4、跨进程共享弹出窗口的优化
由于跨进程共享的弹出窗口是重启的一个新的Activity,因此花销是比较大的,为了提高效率,我们需要做一些工作。
首先,设置Activity的launchMode为singleTop,通过该设置,当该Activity已经在栈顶时,可以直接调用onNewIntent函数而不是重新创建。
其次,设置Activity的taskAffinity为其他值,如:android:taskAffinity = "com.winuxxan.dialogactivity",并且开启Activity时,设置flag:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
这样,该Activity在一个单独的Task中,并且只要该Task堆栈中存在该Activity,那么就不会重新创建,而是调用onNewIntent。
再次,当隐藏该窗口时,不是销毁掉,而是moveTaskToBack,这样再次显示时就不是重新创建,而是将后台Task放到前台。
通过这些手段就可以显著的提高该弹出窗口的效率。
相关文章推荐
- QuickContact分析及其弹出窗口实现
- QuickContact分析及其弹出窗口实现
- QuickContact分析及其弹出窗口实现
- QuickContact分析及其弹出窗口实现 推荐
- 使用JDBC连接MySQL数据库--典型案例分析(九)----财务帐号的DAO设计及其实现
- ASP.NET实现自适应图片大小的弹出窗口(窗口可任意编辑)
- C#.NET 实现右下角弹出窗口
- Android popupwindow 和 Activity弹出窗口实现方式
- 【改进】BP算法及其C语言实现分析
- 千千静听 窗口自动粘合,java 代码实现 源码分析
- 【转】android源码分析之windowmanager (android悬浮窗口的实现)
- js实现弹出窗口代码收集集萃
- 在ASP.NET中,如何实现点击按钮弹出新窗口.刷新父窗口
- ASP.NET弹出窗口Div实现
- showmodaldialog弹出的窗口里,不能实现文件的下载解决方案
- 仿自下向上动画弹出菜单(同时背景窗口变暗/缩小)的实现原理,例小米,苹果等菜单
- Visual C++中窗口子类化技术的实现及其应用
- jQuery实现弹出窗口中切换登录与注册表单
- Strassen矩阵算法分析及其C++实现 递归分治法(转)
- C#+JS简单实现 定时轮询数据表 以及时弹出消息提示窗口