Contacts模块中的QuickContacts

来源:互联网 发布:php sort arsort 编辑:程序博客网 时间:2024/04/29 09:36

在ContactsLIstActiviry中的newView()和bindView()函数中都使用了ContactListItemCache类型的Cache:

    final staticclass ContactListItemCache {

       public View header;

       public TextView headerText;

       public View divider;

       public TextView nameView;

       public View callView;

       public ImageView callButton;

       public CharArrayBuffer nameBuffer = new CharArrayBuffer(128);

       public TextView labelView;

       public CharArrayBuffer labelBuffer = new CharArrayBuffer(128);

       public TextView dataView;

       public CharArrayBuffer dataBuffer = new CharArrayBuffer(128);

       public ImageView presenceView;

       public QuickContactBadge photoView;

       public ImageView nonQuickContactPhotoView;

}

 

其中QuickContactBadge类型的photoView,就是指的图片,点击图片之后会弹出QuickContacts框。

 

 

 

 

 

看一下QuickContactBadge的代码:

public void onClick(View v){

…………..……

} else if (mContactEmail != null) {

mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP_AND_TRIGGER,mContactEmail,

Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI,Uri.encode(mContactEmail)),

EMAIL_LOOKUP_PROJECTION, null, null,null);

…………..……

//在相应点击时触发一个startQuery()方法,这个方法执行完毕之后自动调用mQueryHandler的//onQueryComplete()方法

}

 

protected voidonQueryComplete(int token, Object cookie, Cursor cursor){

…………………………………….

 

if (trigger&& lookupUri != null) {

trigger(lookupUri);//在调用trigger()方法。

…………………………………..

}

 

 

}

    private voidtrigger(Uri lookupUri) {

       QuickContact.showQuickContact(getContext(), this, lookupUri, mMode,mExcludeMimes);

    }

 

对于showQuickContact方法来说,它是ContactsContract类中的一个函数。下面是代码:

 

 

public static voidshowQuickContact(Context context, Rect target, Uri lookupUri, intmode,

               String[] excludeMimes) {

           // Launch pivot dialog through intent for now

           final Intent intent = newIntent(ACTION_QUICK_CONTACT);//这个就是.UI.QuickContactsActivity的IntentFilter的Action

           intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_CLEAR_TOP

                   | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

 

           intent.setData(lookupUri);

           intent.putExtra(EXTRA_TARGET_RECT, target);

           intent.putExtra(EXTRA_MODE, mode);

           intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);

           context.startActivity(intent);//此时就会启动.UI.QuickContactsActivity

}

 

QuickContactsActivity类中的代码比较少。它继承了QuickContactWindow.OnDismissListener,使用onDismiss()函数来把QuickContact框dismiss掉。

QuickContactsActivity类在onNewIntent()函数中先将Intent解析出来,再调用show()方法将QuickContactWindow显示出来。

    public voidonNewIntent(Intent intent) {

       super.onNewIntent(intent);

                  ……………

       mQuickContact.show(lookupUri, target, mode,excludeMimes);//show()方法是QuickContactWindow类中的函数

    }

 

.UI.QuickContactsActivity界面的绘制就是在QuickContactWindow类中完成的。

 

 

 

首先,在Show()方法中调用mHandler.startQuery()方法

 

   

public synchronized void show(UrilookupUri, Rect anchor, int mode, String[] excludeMimes) {

                  ………………………………….

       if (mMode == QuickContact.MODE_LARGE) {

           // Select photos, but only super-primary

           mHandler.startQuery(TOKEN_DATA, lookupUri, dataUri,DataQuery.PROJECTION, Data.MIMETYPE

               + "!=? OR (" + Data.MIMETYPE + "=? AND " + Data._ID +"=" + Contacts.PHOTO_ID

               + ")", new String[] { Photo.CONTENT_ITEM_TYPE,Photo.CONTENT_ITEM_TYPE }, null);

       } else {

           // Exclude all photos from cursor

           mHandler.startQuery(TOKEN_DATA, lookupUri, dataUri,DataQuery.PROJECTION, Data.MIMETYPE

                   + "!=?", new String[] { Photo.CONTENT_ITEM_TYPE }, null);

       }

    }

 

然后在onQueryComplete()方法中调用handleData()

   

    publicsynchronized void onQueryComplete(int token, Object cookie,Cursor cursor) {

       if (cookie != mLookupUri) return;

 

       if (cursor == null) {

           // Problem while running query, so bail without showing

           Log.w(TAG, "Missing cursor for token=" + token);

           this.dismiss();

           return;

       }

                  //绘制QuickContact框的过程基本都在此函数中完成。

       handleData(cursor);

       mHasData = true;

 

       if (!cursor.isClosed()) {

           cursor.close();

       }

 

       considerShowing();

}

再来看handleData()的代码:

 

   

    private voidhandleData(Cursor cursor) {

       if (cursor == null) return;

…………………………………………………………

       // 使用一个while循环,将从onQueryComplete()方法中得到的cursor遍历。

       while (cursor.moveToNext()) {

           // 将cursor中的数据解出来。

           final long dataId = cursor.getLong(DataQuery._ID);

           final String accountType =cursor.getString(DataQuery.ACCOUNT_TYPE);

           final String resPackage =cursor.getString(DataQuery.RES_PACKAGE);

           final String mimeType = cursor.getString(DataQuery.MIMETYPE);

           

…………………………………………………………

//中间通过判断mimeType的类型,生成DataAction类的实例,然后使用函数considerAdd()将

//DataAction类型的action以mimeType为键存储在mActions中。

…………………………………………………………

}//end while

       // 将mActions的键取出。

       final Set<String> containedTypes =mActions.keySet();

       

       String[] temp = containedTypes.toArray(newString[containedTypes.size()]);

       int length = temp.length;

       

       //在此循环中调用inflateAction()函数,将QuickContact框中的图标生成。       

for (String mimeType :ORDERED_MIMETYPES) {

           if (containedTypes.contains(mimeType)) {

               final int index = mTrack.getChildCount() - 1;

               mTrack.addView(inflateAction(mimeType), index); //将快速联系人的小图标add到mTrack中,在showInternal()函数中会调用startAnimation()将其动画效果显示出来

               containedTypes.remove(mimeType);

           }

       }

…………………………………………………………

 

    }

 

 

   

    private voidconsiderAdd(Action action, String mimeType) {

       if (mResolveCache.hasResolve(action)) {

           mActions.collect(mimeType, action);

       }

}

 

 

 

   

    private ViewinflateAction(String mimeType) {

……………………………….

       ActionList children = mActions.get(mimeType);

       Action firstInfo = children.get(0);

       if (children.size() == 1) {

           view.setTag(firstInfo);

       } else {

           for (Action action : children) {

               if (action.isPrimary()) {

                   view.setTag(action);

                   isActionSet = true;

                   break;

               }

           }

           if (!isActionSet) {

               view.setTag(children);

           }

       }

 

       // Set icon and listen for clicks

       final CharSequence descrip =mResolveCache.getDescription(firstInfo);

       final Drawable icon = mResolveCache.getIcon(firstInfo);

       view.setChecked(false);

       view.setContentDescription(descrip);

       view.setImageDrawable(icon);

       view.setOnClickListener(this);

       return view;

    }

 

此时,handleData()函数已经完成,接着调用considerShowing(),由considerShowing()调用showInternal()函数来完成绘制工作。

 

 

   

    private voidconsiderShowing() {

       if (mHasData && !mShowing&& !mDismissed) {

           if (mMode == QuickContact.MODE_MEDIUM&& !mHasValidSocial) {

               // Missing valid social, swap medium for small header

               mHeader.setVisibility(View.GONE);

               mHeader = getHeaderView(QuickContact.MODE_SMALL);

           }

 

           // All queries have returned, pull curtain

           showInternal();

       }

    }

 

 

 

   

    private voidshowInternal() {

       mDecor = mWindow.getDecorView();

       mDecor.getViewTreeObserver().addOnGlobalLayoutListener(this);

       WindowManager.LayoutParams l = mWindow.getAttributes();

 

       l.width = mScreenWidth + mShadowHoriz + mShadowHoriz;

       l.height = WindowManager.LayoutParams.WRAP_CONTENT;

 

       // Force layout measuring pass so we have baseline numbers

       mDecor.measure(l.width, l.height);

       final int blockHeight = mDecor.getMeasuredHeight();

 

       l.gravity = Gravity.TOP | Gravity.LEFT;

       l.x = -mShadowHoriz;

 

       if (mAnchor.top > blockHeight) {

           // Show downwards callout when enough room, aligning bottomblock

           // edge with top of anchor area, and adjusting to inset arrow.

           showArrow(R.id.arrow_down, mAnchor.centerX());

           l.y = mAnchor.top - blockHeight + mShadowVert;

           l.windowAnimations = R.style.QuickContactAboveAnimation;

 

       } else {

           // Otherwise show upwards callout, aligning block top with bottomof

           // anchor area, and adjusting to inset arrow.

           showArrow(R.id.arrow_up, mAnchor.centerX());

           l.y = mAnchor.bottom - mShadowVert;

           l.windowAnimations = R.style.QuickContactBelowAnimation;

 

       }

 

       l.flags =WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN

               | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;

 

       mRequestedY = l.y;

       mWindowManager.addView(mDecor, l);

       mShowing = true;

       mQuerying = false;

       mDismissed = false;

 

       mTrack.startAnimation(mTrackAnim);// 调用动画效果

 

       if (TRACE_LAUNCH) {

           android.os.Debug.stopMethodTracing();

           Log.d(TAG, "Window recycled " + mWindowRecycled + "times, chiclets "

                   + mActionRecycled + " times");

       }

    }

 

到此,完了。

若有错,欢迎指正。