1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.contacts.detail; 18 19 import android.app.ListFragment; 20 import android.content.ContentUris; 21 import android.content.Intent; 22 import android.net.Uri; 23 import android.os.Bundle; 24 import android.provider.ContactsContract.StreamItems; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.view.ViewGroup; 28 import android.widget.AbsListView.OnScrollListener; 29 import android.widget.ListView; 30 31 import com.android.contacts.R; 32 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener; 33 import com.android.contacts.detail.ContactDetailDisplayUtils.StreamPhotoTag; 34 import com.android.contacts.model.AccountTypeManager; 35 import com.android.contacts.model.Contact; 36 import com.android.contacts.model.account.AccountType; 37 import com.android.contacts.util.StreamItemEntry; 38 39 public class ContactDetailUpdatesFragment extends ListFragment implements FragmentKeyListener { 40 41 private static final String TAG = "ContactDetailUpdatesFragment"; 42 43 private Contact mContactData; 44 private Uri mLookupUri; 45 46 private LayoutInflater mInflater; 47 private StreamItemAdapter mStreamItemAdapter; 48 49 private OnScrollListener mVerticalScrollListener; 50 51 /** 52 * Listener on clicks on a stream item. 53 * <p> 54 * It assumes the view has a tag of type {@link StreamItemEntry} associated with it. 55 */ 56 private final View.OnClickListener mStreamItemClickListener = new View.OnClickListener() { 57 @Override 58 public void onClick(View view) { 59 StreamItemEntry streamItemEntry = (StreamItemEntry) view.getTag(); 60 if (streamItemEntry == null) { 61 // Ignore if this item does not have a stream item associated with it. 62 return; 63 } 64 final AccountType accountType = getAccountTypeForStreamItemEntry(streamItemEntry); 65 66 final Uri uri = ContentUris.withAppendedId(StreamItems.CONTENT_URI, 67 streamItemEntry.getId()); 68 final Intent intent = new Intent(Intent.ACTION_VIEW, uri); 69 intent.setClassName(accountType.syncAdapterPackageName, 70 accountType.getViewStreamItemActivity()); 71 startActivity(intent); 72 } 73 }; 74 75 private final View.OnClickListener mStreamItemPhotoItemClickListener 76 = new View.OnClickListener() { 77 @Override 78 public void onClick(View view) { 79 StreamPhotoTag tag = (StreamPhotoTag) view.getTag(); 80 if (tag == null) { 81 return; 82 } 83 final AccountType accountType = getAccountTypeForStreamItemEntry(tag.streamItem); 84 85 final Intent intent = new Intent(Intent.ACTION_VIEW, tag.getStreamItemPhotoUri()); 86 intent.setClassName(accountType.syncAdapterPackageName, 87 accountType.getViewStreamItemPhotoActivity()); 88 startActivity(intent); 89 } 90 }; 91 92 private AccountType getAccountTypeForStreamItemEntry(StreamItemEntry streamItemEntry) { 93 return AccountTypeManager.getInstance(getActivity()).getAccountType( 94 streamItemEntry.getAccountType(), streamItemEntry.getDataSet()); 95 } 96 97 public ContactDetailUpdatesFragment() { 98 // Explicit constructor for inflation 99 } 100 101 @Override 102 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { 103 mInflater = inflater; 104 return mInflater.inflate(R.layout.contact_detail_updates_fragment, container, false); 105 } 106 107 @Override 108 public void onViewCreated(View view, Bundle savedInstanceState) { 109 super.onViewCreated(view, savedInstanceState); 110 mStreamItemAdapter = new StreamItemAdapter(getActivity(), mStreamItemClickListener, 111 mStreamItemPhotoItemClickListener); 112 setListAdapter(mStreamItemAdapter); 113 getListView().setOnScrollListener(mVerticalScrollListener); 114 115 // It is possible that the contact data was set to the fragment when it was first attached 116 // to the activity, but before this method was called because the fragment was not 117 // visible on screen yet (i.e. using a {@link ViewPager}), so display the data if we already 118 // have it. 119 if (mContactData != null) { 120 mStreamItemAdapter.setStreamItems(mContactData.getStreamItems()); 121 } 122 } 123 124 public void setData(Uri lookupUri, Contact result) { 125 if (result == null) { 126 return; 127 } 128 mLookupUri = lookupUri; 129 mContactData = result; 130 131 // If the adapter has been created already, then try to set stream items. Otherwise, 132 // wait for the adapter to get initialized, after which we will try to set the stream items 133 // again. 134 if (mStreamItemAdapter != null) { 135 mStreamItemAdapter.setStreamItems(mContactData.getStreamItems()); 136 } 137 } 138 139 /** 140 * Reset the list adapter in this {@link Fragment} to get rid of any saved scroll position 141 * from a previous contact. 142 */ 143 public void resetAdapter() { 144 setListAdapter(mStreamItemAdapter); 145 } 146 147 @Override 148 public boolean handleKeyDown(int keyCode) { 149 return false; 150 } 151 152 public void setVerticalScrollListener(OnScrollListener listener) { 153 mVerticalScrollListener = listener; 154 } 155 156 /** 157 * Returns the top coordinate of the first item in the {@link ListView}. If the first item 158 * in the {@link ListView} is not visible or there are no children in the list, then return 159 * Integer.MIN_VALUE. Note that the returned value will be <= 0 because the first item in the 160 * list cannot have a positive offset. 161 */ 162 public int getFirstListItemOffset() { 163 return ContactDetailDisplayUtils.getFirstListItemOffset(getListView()); 164 } 165 166 /** 167 * Tries to scroll the first item to the given offset (this can be a no-op if the list is 168 * already in the correct position). 169 * @param offset which should be <= 0 170 */ 171 public void requestToMoveToOffset(int offset) { 172 ContactDetailDisplayUtils.requestToMoveToOffset(getListView(), offset); 173 } 174 } 175