ContactDetail 和 ContactEditor 界面头像响应点击过程

1,联系人详情界面

 ContactDetailFragment中处理,ViewAdapter装载数据显示头像

 1 private final class ViewAdapter extends BaseAdapter {
 2         ......
 3  
 4         public View getView(int position, View convertView, ViewGroup parent) {
 5             switch (getItemViewType(position)) {
 6                 case VIEW_TYPE_HEADER_ENTRY://获取头像,name等
 7                     return getHeaderEntryView(convertView, parent);
 8                 case VIEW_TYPE_SEPARATOR_ENTRY://同类data,多个item之间分割线
 9                     return getSeparatorEntryView(position, convertView, parent);
10                 case VIEW_TYPE_KIND_TITLE_ENTRY://data类别标题以及下划线
11                     return getKindTitleEntryView(position, convertView, parent);
12                 case VIEW_TYPE_DETAIL_ENTRY://data详情
13                     return getDetailEntryView(position, convertView, parent);
14                 case VIEW_TYPE_NETWORK_TITLE_ENTRY:
15                     return getNetworkTitleEntryView(position, convertView, parent);
16                 case VIEW_TYPE_ADD_CONNECTION_ENTRY:
17                     return getAddConnectionEntryView(position, convertView, parent);
18                 default:
19                     throw new IllegalStateException("Invalid view type ID " +
20                             getItemViewType(position));
21             }
22         }
View Code

构建OnClickListener,并注册启用

 1 private View getHeaderEntryView(View convertView, ViewGroup parent) {
 2             final int desiredLayoutResourceId = R.layout.detail_header_contact_without_updates;
 3             ......
 4 
 5             // Set the photo if it should be displayed
 6             if (viewCache.photoView != null) {
 7                 final boolean expandOnClick = mContactData.getPhotoUri() != null;
 8                 //构造OnClickListener 
 9                 final OnClickListener listener = mPhotoSetter.setupContactPhotoForClick(
10                         mContext, mContactData, viewCache.photoView, expandOnClick);
11 
12                 RawContact rawContact = mContactData.getRawContacts().get(0);
13                 final String accountType = rawContact.getAccountTypeString();
14 
15                 if ((expandOnClick || mContactData.isWritableContact(mContext))
16                         && !(SimAccountType.ACCOUNT_TYPE.equals(accountType))) {
17                     ///启用OnClickListener 
18                     viewCache.enablePhotoOverlay(listener);
19                 }
20             }
View Code 
public class ContactDetailPhotoSetter extends ImageViewDrawableSetter {
    public OnClickListener setupContactPhotoForClick(Context context, Contact contactData,
            ImageView photoView, boolean expandPhotoOnClick) {
        Bitmap bitmap = setupContactPhoto(contactData, photoView);
        return setupClickListener(context, contactData, bitmap, expandPhotoOnClick);
    }
     ......

private OnClickListener setupClickListener(Context context, Contact contactData, Bitmap bitmap,
            boolean expandPhotoOnClick) {
        final ImageView target = getTarget();
        if (target == null) return null;

        return new PhotoClickListener(
                context, contactData, bitmap, getCompressedImage(), expandPhotoOnClick);
    }
    ......

private static final class PhotoClickListener implements OnClickListener {
        ......
        
        public PhotoClickListener(Context context, Contact contactData, Bitmap photoBitmap,
                byte[] photoBytes, boolean expandPhotoOnClick) {
          ......
        }

        @Override
        public void onClick(View v) {
           ......

            Intent photoSelectionIntent = PhotoSelectionActivity.buildIntent(mContext,
                    photoUri, mPhotoBitmap, mPhotoBytes, rect, delta, mContactData.isUserProfile(),
                    mContactData.isDirectoryEntry(), mExpandPhotoOnClick);
            ......
            mContext.startActivity(photoSelectionIntent);
        }
    }
}
View Code

onClick会启动PhotoSelectionActivity

public class PhotoSelectionActivity extends Activity {
        ......

        @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.photoselection_activity);    
        ......
        / Wait until the layout pass to show the photo, so that the source bounds will match up.
        SchedulingUtils.doAfterLayout(mBackdrop, new Runnable() {
            @Override
            public void run() {
                displayPhoto();
            }
        });
        ......
        private void displayPhoto() {
        ......
        attachPhotoHandler();
    }
private void attachPhotoHandler() {
         ......
        mPhotoHandler = new PhotoHandler(this, mPhotoView, mode, mState);

        if (mPendingPhotoResult != null) {
        ......
        } else {           
            SchedulingUtils.doAfterLayout(mBackdrop, new Runnable() {
                @Override
                public void run() {
                    animatePhotoOpen();
                }
            });
        }
    }

private void animatePhotoOpen() {
        mAnimationListener = new AnimatorListenerAdapter() {
            private void capturePhotoPos() {
               ......
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                capturePhotoPos();
                if (mPhotoHandler != null) {
                    //又一个onClick被调用
                    mPhotoHandler.onClick(mPhotoView);
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                capturePhotoPos();
            }
        };
        animatePhoto(getPhotoEndParams());
    }                
mPhotoHandler.onClick(mPhotoView)处理
public abstract class PhotoSelectionHandler implements OnClickListener {
        ......
 @Override
    public void onClick(View v) {
        final PhotoActionListener listener = getListener();
        if (listener != null) {
            if (getWritableEntityIndex() != -1) {
                mPopup = PhotoActionPopup.createPopupMenu(
                        mContext, mPhotoView, listener, mPhotoMode);
                mPopup.setOnDismissListener(new OnDismissListener() {
                    @Override
                    public void onDismiss() {
                        listener.onPhotoSelectionDismissed();
                    }
                });
                mPopup.show();//显示弹出框ListPopupWindow
            }
        }
    }
}

PhotoActionPopup创建ListPopupWindow

 1 public static ListPopupWindow createPopupMenu(Context context, View anchorView,
 2             final Listener listener, int mode) {
 3         // Build choices, depending on the current mode. We assume this Dialog is never called
 4         // if there are NO choices (e.g. a read-only picture is already super-primary)
 5         final ArrayList<ChoiceListItem> choices = new ArrayList<ChoiceListItem>(4);
 6         // Use as Primary
 7         if ((mode & Flags.ALLOW_PRIMARY) > 0) {
 8             choices.add(new ChoiceListItem(ChoiceListItem.ID_USE_AS_PRIMARY,
 9                     context.getString(R.string.use_photo_as_primary)));
10         }
11         // Remove
12         if ((mode & Flags.REMOVE_PHOTO) > 0) {
13             choices.add(new ChoiceListItem(ChoiceListItem.ID_REMOVE,
14                     context.getString(R.string.removePhoto)));
15         }
16         // Take photo or pick one from the gallery.  Wording differs if there is already a photo.
17         if ((mode & Flags.TAKE_OR_PICK_PHOTO) > 0) {
18             boolean replace = (mode & Flags.TAKE_OR_PICK_PHOTO_REPLACE_WORDING) > 0;
19             final int takePhotoResId = replace ? R.string.take_new_photo : R.string.take_photo;
20             final String takePhotoString = context.getString(takePhotoResId);
21             final int pickPhotoResId = replace ? R.string.pick_new_photo : R.string.pick_photo;
22             final String pickPhotoString = context.getString(pickPhotoResId);
23             if (PhoneCapabilityTester.isCameraIntentRegistered(context)) {
24                 choices.add(new ChoiceListItem(ChoiceListItem.ID_TAKE_PHOTO, takePhotoString));
25             }
26             choices.add(new ChoiceListItem(ChoiceListItem.ID_PICK_PHOTO, pickPhotoString));
27         }
28 
29         final ListAdapter adapter = new ArrayAdapter<ChoiceListItem>(context,
30                 R.layout.select_dialog_item, choices);
31 
32         final ListPopupWindow listPopupWindow = new ListPopupWindow(context);
33         final OnItemClickListener clickListener = new OnItemClickListener() {
34             @Override
35             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
36                 final ChoiceListItem choice = choices.get(position);
37                 switch (choice.getId()) {
38                     case ChoiceListItem.ID_USE_AS_PRIMARY:
39                         listener.onUseAsPrimaryChosen();
40                         break;
41                     case ChoiceListItem.ID_REMOVE:
42                         listener.onRemovePictureChosen();
43                         break;
44                     case ChoiceListItem.ID_TAKE_PHOTO:
45                         listener.onTakePhotoChosen();
46                         break;
47                     case ChoiceListItem.ID_PICK_PHOTO:
48                         listener.onPickFromGalleryChosen();
49                         break;
50                 }
51 
52                 UiClosables.closeQuietly(listPopupWindow);
53             }
54         };
55 
56         listPopupWindow.setAnchorView(anchorView);
57         listPopupWindow.setAdapter(adapter);
58         listPopupWindow.setOnItemClickListener(clickListener);
59         listPopupWindow.setModal(true);
60         listPopupWindow.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
61         final int minWidth = context.getResources().getDimensionPixelSize(
62                 R.dimen.photo_action_popup_min_width);
63         if (anchorView.getWidth() < minWidth) {
64             listPopupWindow.setWidth(minWidth);
65         }
66         return listPopupWindow;
67     }
View Code

----------------------------------------------------

2,联系人编辑界面

ContactEditorFragment处理, bindEditors()加载编辑界面

private void bindEditors() {
     ......
    editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view,
                        mContent, false);
    editor.setState(rawContactDelta, type, mViewIdGenerator, isEditingUserProfile());

      // Set up the photo handler.
      bindPhotoHandler(editor, type, mState);
    ......
}

bindPhotoHandler(...) 构建Listener

  1 private void bindPhotoHandler(BaseRawContactEditorView editor, AccountType type,
  2             RawContactDeltaList state) {
  3         ......
  4         final PhotoHandler photoHandler = new PhotoHandler(mContext, editor, mode, state);
  5         editor.getPhotoEditor().setEditorListener(
  6                 (PhotoHandler.PhotoEditorListener) photoHandler.getListener());
  7         ......
  8 }
  9 private final class PhotoHandler extends PhotoSelectionHandler {
 10 
 11         final long mRawContactId;
 12         private final BaseRawContactEditorView mEditor;
 13         private final PhotoActionListener mPhotoEditorListener;
 14 
 15         public PhotoHandler(Context context, BaseRawContactEditorView editor, int photoMode,
 16                 RawContactDeltaList state) {
 17             super(context, editor.getPhotoEditor(), photoMode, false, state);
 18             mEditor = editor;
 19             mRawContactId = editor.getRawContactId();
 20             mPhotoEditorListener = new PhotoEditorListener();
 21         }
 22 
 23         @Override
 24         public PhotoActionListener getListener() {
 25             return mPhotoEditorListener;
 26         }
 27 
 28         @Override
 29         public void startPhotoActivity(Intent intent, int requestCode, Uri photoUri) {
 30             mRawContactIdRequestingPhoto = mEditor.getRawContactId();
 31             mCurrentPhotoHandler = this;
 32             mStatus = Status.SUB_ACTIVITY;
 33             mCurrentPhotoUri = photoUri;
 34             ContactEditorFragment.this.startActivityForResult(intent, requestCode);
 35         }
 36 
 37         private final class PhotoEditorListener extends PhotoSelectionHandler.PhotoActionListener
 38                 implements EditorListener {
 39 
 40             @Override
 41             public void onRequest(int request) {
 42                 if (!hasValidState()) return;
 43 
 44                 if (request == EditorListener.REQUEST_PICK_PHOTO) {
 45                     onClick(mEditor.getPhotoEditor());
 46                 }
 47             }
 48 
 49             @Override
 50             public void onDeleteRequested(Editor removedEditor) {
 51                 // The picture cannot be deleted, it can only be removed, which is handled by
 52                 // onRemovePictureChosen()
 53             }
 54 
 55             /**
 56              * User has chosen to set the selected photo as the (super) primary photo
 57              */
 58             @Override
 59             public void onUseAsPrimaryChosen() {
 60                 // Set the IsSuperPrimary for each editor
 61                 int count = mContent.getChildCount();
 62                 for (int i = 0; i < count; i++) {
 63                     final View childView = mContent.getChildAt(i);
 64                     if (childView instanceof BaseRawContactEditorView) {
 65                         final BaseRawContactEditorView editor =
 66                                 (BaseRawContactEditorView) childView;
 67                         final PhotoEditorView photoEditor = editor.getPhotoEditor();
 68                         photoEditor.setSuperPrimary(editor == mEditor);
 69                     }
 70                 }
 71                 bindEditors();
 72             }
 73 
 74             /**
 75              * User has chosen to remove a picture
 76              */
 77             @Override
 78             public void onRemovePictureChosen() {
 79                 mEditor.setPhotoBitmap(null);
 80 
 81                 // Prevent bitmap from being restored if rotate the device.
 82                 // (only if we first chose a new photo before removing it)
 83                 mUpdatedPhotos.remove(String.valueOf(mRawContactId));
 84                 bindEditors();
 85             }
 86 
 87             @Override
 88             public void onPhotoSelected(Uri uri) throws FileNotFoundException {
 89                 final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(mContext, uri);
 90                 setPhoto(mRawContactId, bitmap, uri);
 91                 mCurrentPhotoHandler = null;
 92                 bindEditors();
 93             }
 94 
 95             @Override
 96             public Uri getCurrentPhotoUri() {
 97                 return mCurrentPhotoUri;
 98             }
 99 
100             @Override
101             public void onPhotoSelectionDismissed() {
102                 // Nothing to do.
103             }
104         }
105     }
View Code

RawContactEditorView加载PhotoEditorView,PhotoEditorView注册Listener

public class RawContactEditorView extends BaseRawContactEditorView {
        ......
        @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        ......
    }
       ......  
}

public abstract class BaseRawContactEditorView extends LinearLayout {
        ......
        Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        mBody = findViewById(R.id.body);
        mDivider = findViewById(R.id.divider);

        mPhoto = (PhotoEditorView)findViewById(R.id.edit_photo);
        mPhoto.setEnabled(isEnabled());
    }
    ......
}

public class PhotoEditorView extends LinearLayout implements Editor {
        ......
@Override
    protected void onFinishInflate() {
        super.onFinishInflate();            
        mPhotoImageView = (ImageView) findViewById(R.id.photo);
        mFrameView = findViewById(R.id.frame);
        mFrameView.setOnClickListener(new OnClickListener() {
            @Override//响应点击onClick   
            public void onClick(View v) {
                if (mListener != null) { 
            mListener.onRequest(EditorListener.REQUEST_PICK_PHOTO); } } }); } ...... }

 mListener.onRequest就是ContactEditorFragment中bindPhotoHandler中定义的

private final class PhotoHandler extends PhotoSelectionHandler {    ......
        public PhotoHandler(Context context, BaseRawContactEditorView editor, int photoMode,
                RawContactDeltaList state) {
            super(context, editor.getPhotoEditor(), photoMode, false, state);
            mEditor = editor;
            mRawContactId = editor.getRawContactId();
            mPhotoEditorListener = new PhotoEditorListener();
        }
        ......
        private final class PhotoEditorListener extends PhotoSelectionHandler.PhotoActionListener
                implements EditorListener {

            @Override
            public void onRequest(int request) {
                if (!hasValidState()) return;

                if (request == EditorListener.REQUEST_PICK_PHOTO) {
                    onClick(mEditor.getPhotoEditor());//调用PhotoSelectionHandler 中定义的onClick方法。
} } ...... } ...... }

PhotoSelectionHandler中的onClick

public abstract class PhotoSelectionHandler implements OnClickListener {
......
    @Override
    public void onClick(View v) {
        final PhotoActionListener listener = getListener();
        if (listener != null) {
            if (getWritableEntityIndex() != -1) {
                mPopup = PhotoActionPopup.createPopupMenu(
                        mContext, mPhotoView, listener, mPhotoMode);
                mPopup.setOnDismissListener(new OnDismissListener() {
                    @Override
                    public void onDismiss() {
                        listener.onPhotoSelectionDismissed();
                    }
                });
                mPopup.show();
            }
        }
    }
......
}

然后又是PhotoActionPopup.createPopupMenu处理。

---------------------------------------------------------

综上:联系人详情 and 联系人编辑界面响应头像点击过程都是:

先构建并注册OnClickListener,——>Listener处理——>调用PhotoSelectionHandler中的onClick——>PhotoActionPopup.createPopupMenux 显示弹出框PopupWindow

区别在于Listener的构建,和传递的参数。

原文地址:https://www.cnblogs.com/antoon/p/4383052.html