生活随笔
收集整理的這篇文章主要介紹了
QuickContact分析及其弹出窗口实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、簡介
?? ?QuickContact是為了應用程序能夠快速方便的訪問聯系人,并且快速的運用聯系人的信息執行相應操作而設計的。最常見的在Contacts應用程序中如下圖所示:
?? ?在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中的聯系人詳情界面。
?? ?運行效果如圖:
?? ?由于本文不是針對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);?}?
?? ?顯示效果如下:
?? ?需要注意的一點就是,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取消了背景變暗的效果,最后我們得到的結果如下圖:
?? ?其實,帶有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?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();???????????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);?????}?
?? ?最終效果如下:
?
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分析及其弹出窗口实现的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。