ContactDetailUpdatesFragment.java revision ab5387bb8728c34bafcb554830961341f1f9daea
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
17package com.android.contacts.detail;
18
19import com.android.contacts.ContactLoader;
20import com.android.contacts.R;
21import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
22import com.android.contacts.detail.ContactDetailDisplayUtils.StreamPhotoTag;
23import com.android.contacts.model.AccountType;
24import com.android.contacts.model.AccountTypeManager;
25import com.android.contacts.util.StreamItemEntry;
26
27import android.app.ListFragment;
28import android.content.ContentUris;
29import android.content.Intent;
30import android.net.Uri;
31import android.os.Bundle;
32import android.provider.ContactsContract.StreamItems;
33import android.view.LayoutInflater;
34import android.view.View;
35import android.view.View.OnClickListener;
36import android.view.ViewGroup;
37import android.widget.AbsListView.OnScrollListener;
38import android.widget.ListView;
39
40public class ContactDetailUpdatesFragment extends ListFragment
41        implements FragmentKeyListener, ViewOverlay {
42
43    private static final String TAG = "ContactDetailUpdatesFragment";
44
45    private ContactLoader.Result mContactData;
46    private Uri mLookupUri;
47
48    private LayoutInflater mInflater;
49    private StreamItemAdapter mStreamItemAdapter;
50
51    private float mInitialAlphaValue;
52
53    /**
54     * This optional view adds an alpha layer over the entire fragment.
55     */
56    private View mAlphaLayer;
57
58    /**
59     * This optional view adds a layer over the entire fragment so that when visible, it intercepts
60     * all touch events on the fragment.
61     */
62    private View mTouchInterceptLayer;
63
64    private OnScrollListener mVerticalScrollListener;
65
66    /**
67     * Listener on clicks on a stream item.
68     * <p>
69     * It assumes the view has a tag of type {@link StreamItemEntry} associated with it.
70     */
71    private final View.OnClickListener mStreamItemClickListener = new View.OnClickListener() {
72        @Override
73        public void onClick(View view) {
74            StreamItemEntry streamItemEntry = (StreamItemEntry) view.getTag();
75            if (streamItemEntry == null) {
76                // Ignore if this item does not have a stream item associated with it.
77                return;
78            }
79            final AccountType accountType = getAccountTypeForStreamItemEntry(streamItemEntry);
80
81            final Uri uri = ContentUris.withAppendedId(StreamItems.CONTENT_URI,
82                    streamItemEntry.getId());
83            final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
84            intent.setClassName(accountType.resPackageName,
85                    accountType.getViewStreamItemActivity());
86            startActivity(intent);
87        }
88    };
89
90    private final View.OnClickListener mStreamItemPhotoItemClickListener
91            = new View.OnClickListener() {
92        @Override
93        public void onClick(View view) {
94            StreamPhotoTag tag = (StreamPhotoTag) view.getTag();
95            if (tag == null) {
96                return;
97            }
98            final AccountType accountType = getAccountTypeForStreamItemEntry(tag.streamItem);
99
100            final Intent intent = new Intent(Intent.ACTION_VIEW, tag.getStreamItemPhotoUri());
101            intent.setClassName(accountType.resPackageName,
102                    accountType.getViewStreamItemPhotoActivity());
103            startActivity(intent);
104        }
105    };
106
107    private AccountType getAccountTypeForStreamItemEntry(StreamItemEntry streamItemEntry) {
108        return AccountTypeManager.getInstance(getActivity()).getAccountType(
109                streamItemEntry.getAccountType(), streamItemEntry.getDataSet());
110    }
111
112    public ContactDetailUpdatesFragment() {
113        // Explicit constructor for inflation
114    }
115
116    @Override
117    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
118        mInflater = inflater;
119        View rootView = mInflater.inflate(R.layout.contact_detail_updates_fragment, container,
120                false);
121
122        mTouchInterceptLayer = rootView.findViewById(R.id.touch_intercept_overlay);
123        mAlphaLayer = rootView.findViewById(R.id.alpha_overlay);
124        ContactDetailDisplayUtils.setAlphaOnViewBackground(mAlphaLayer, mInitialAlphaValue);
125
126        return rootView;
127    }
128
129    @Override
130    public void onViewCreated(View view, Bundle savedInstanceState) {
131        super.onViewCreated(view, savedInstanceState);
132        mStreamItemAdapter = new StreamItemAdapter(getActivity(), mStreamItemClickListener,
133                mStreamItemPhotoItemClickListener);
134        setListAdapter(mStreamItemAdapter);
135        getListView().setOnScrollListener(mVerticalScrollListener);
136
137        // It is possible that the contact data was set to the fragment when it was first attached
138        // to the activity, but before this method was called because the fragment was not
139        // visible on screen yet (i.e. using a {@link ViewPager}), so display the data if we already
140        // have it.
141        if (mContactData != null) {
142            mStreamItemAdapter.setStreamItems(mContactData.getStreamItems());
143        }
144    }
145
146    public void setData(Uri lookupUri, ContactLoader.Result result) {
147        if (result == null) {
148            return;
149        }
150        mLookupUri = lookupUri;
151        mContactData = result;
152
153        // If the adapter has been created already, then try to set stream items. Otherwise,
154        // wait for the adapter to get initialized, after which we will try to set the stream items
155        // again.
156        if (mStreamItemAdapter != null) {
157            mStreamItemAdapter.setStreamItems(mContactData.getStreamItems());
158        }
159    }
160
161    /**
162     * Reset the list adapter in this {@link Fragment} to get rid of any saved scroll position
163     * from a previous contact.
164     */
165    public void resetAdapter() {
166        setListAdapter(mStreamItemAdapter);
167    }
168
169    @Override
170    public void setAlphaLayerValue(float alpha) {
171        // If the alpha layer is not ready yet, store it for later when the view is initialized
172        if (mAlphaLayer == null) {
173            mInitialAlphaValue = alpha;
174        } else {
175            // Otherwise set the value immediately
176            ContactDetailDisplayUtils.setAlphaOnViewBackground(mAlphaLayer, alpha);
177        }
178    }
179
180    @Override
181    public void enableTouchInterceptor(OnClickListener clickListener) {
182        if (mTouchInterceptLayer != null) {
183            mTouchInterceptLayer.setVisibility(View.VISIBLE);
184            mTouchInterceptLayer.setOnClickListener(clickListener);
185        }
186    }
187
188    @Override
189    public void disableTouchInterceptor() {
190        if (mTouchInterceptLayer != null) {
191            mTouchInterceptLayer.setVisibility(View.GONE);
192        }
193    }
194
195    @Override
196    public boolean handleKeyDown(int keyCode) {
197        return false;
198    }
199
200    public void setVerticalScrollListener(OnScrollListener listener) {
201        mVerticalScrollListener = listener;
202    }
203
204    /**
205     * Returns the top coordinate of the first item in the {@link ListView}. If the first item
206     * in the {@link ListView} is not visible or there are no children in the list, then return
207     * Integer.MIN_VALUE. Note that the returned value will be <= 0 because the first item in the
208     * list cannot have a positive offset.
209     */
210    public int getFirstListItemOffset() {
211        return ContactDetailDisplayUtils.getFirstListItemOffset(getListView());
212    }
213
214    /**
215     * Tries to scroll the first item to the given offset (this can be a no-op if the list is
216     * already in the correct position).
217     * @param offset which should be <= 0
218     */
219    public void requestToMoveToOffset(int offset) {
220        ContactDetailDisplayUtils.requestToMoveToOffset(getListView(), offset);
221    }
222}
223