blob: a8803f5257e9a28c1d7efe638c4cd7f764db6f56 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.contacts.detail;
import com.android.contacts.ContactLoader;
import com.android.contacts.ContactSaveService;
import com.android.contacts.R;
import com.android.contacts.activities.ContactDetailActivity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.CheckBox;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.TextView;
/**
* This is a horizontally scrolling carousel with 2 tabs: one to see info about the contact and
* one to see updates from the contact.
* TODO: Create custom views for the tabs so their width can be programatically set as 2/3 of the
* screen width.
*/
public class ContactDetailTabCarousel extends HorizontalScrollView
implements View.OnClickListener, OnTouchListener {
private static final String TAG = "ContactDetailTabCarousel";
private CheckBox mStarredView;
private ImageView mPhotoView;
private TextView mStatusView;
private TextView mStatusDateView;
private Uri mContactUri;
private Listener mListener;
private View[] mTabs = new View[2];
private int mAllowedScrollLength;
/**
* Interface for callbacks invoked when the user interacts with the carousel.
*/
public interface Listener {
public void onTouchDown();
public void onTouchUp();
public void onScrollChanged(int l, int t, int oldl, int oldt);
public void onTabSelected(int position);
}
public ContactDetailTabCarousel(Context context) {
this(context, null);
}
public ContactDetailTabCarousel(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ContactDetailTabCarousel(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
final LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.contact_detail_tab_carousel, this);
setOnTouchListener(this);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
mListener.onScrollChanged(l, t, oldl, oldt);
}
/**
* Returns the number of pixels that this view can be scrolled.
*/
public int getAllowedScrollLength() {
if (mAllowedScrollLength == 0) {
// Find the total length of two tabs side-by-side
int totalLength = 0;
for (int i=0; i < mTabs.length; i++) {
totalLength += mTabs[i].getWidth();
}
// Find the allowed scrolling length by subtracting the current visible screen width
// from the total length of the tabs.
mAllowedScrollLength = totalLength - getWidth();
}
return mAllowedScrollLength;
}
/**
* Updates the tab selection.
*/
public void setCurrentTab(int position) {
if (position < 0 || position > mTabs.length) {
throw new IllegalStateException("Invalid position in array of tabs: " + position);
}
// TODO: Handle device rotation (saving and restoring state of the selected tab)
// This will take more work because there is no tab carousel in phone landscape
if (mTabs[position] == null) {
return;
}
mTabs[position].setSelected(true);
unselectAllOtherTabs(position);
}
private void unselectAllOtherTabs(int position) {
for (int i = 0; i < mTabs.length; i++) {
if (position != i) {
mTabs[i].setSelected(false);
}
}
}
/**
* Loads the data from the Loader-Result. This is the only function that has to be called
* from the outside to fully setup the View
*/
public void loadData(ContactLoader.Result contactData) {
mContactUri = contactData.getLookupUri();
View aboutView = findViewById(R.id.tab_about);
View updateView = findViewById(R.id.tab_update);
TextView aboutTab = (TextView) aboutView.findViewById(R.id.label);
aboutTab.setText(mContext.getString(R.string.contactDetailAbout));
aboutTab.setClickable(true);
aboutTab.setSelected(true);
TextView updatesTab = (TextView) updateView.findViewById(R.id.label);
updatesTab.setText(mContext.getString(R.string.contactDetailUpdates));
updatesTab.setClickable(true);
aboutTab.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.onTabSelected(0);
}
});
updatesTab.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.onTabSelected(1);
}
});
mTabs[0] = aboutTab;
mTabs[1] = updatesTab;
// Retrieve the photo and star views for the "about" tab
mPhotoView = (ImageView) aboutView.findViewById(R.id.photo);
mStarredView = (CheckBox) aboutView.findViewById(R.id.star);
mStarredView.setOnClickListener(this);
// Retrieve the social update views for the "updates" tab
mStatusView = (TextView) updateView.findViewById(R.id.status);
mStatusDateView = (TextView) updateView.findViewById(R.id.status_date);
ContactDetailDisplayUtils.setPhoto(mContext, contactData, mPhotoView);
ContactDetailDisplayUtils.setStarred(contactData, mStarredView);
ContactDetailDisplayUtils.setSocialSnippetAndDate(mContext, contactData, mStatusView,
mStatusDateView);
}
/**
* Set the given {@link Listener} to handle carousel events.
*/
public void setListener(Listener listener) {
mListener = listener;
}
// TODO: The starred icon needs to move to the action bar.
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.star: {
// Toggle "starred" state
// Make sure there is a contact
if (mContactUri != null) {
Intent intent = ContactSaveService.createSetStarredIntent(
getContext(), mContactUri, mStarredView.isChecked());
getContext().startService(intent);
}
break;
}
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mListener.onTouchDown();
return true;
case MotionEvent.ACTION_UP:
mListener.onTouchUp();
return true;
}
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean interceptTouch = super.onInterceptTouchEvent(ev);
if (interceptTouch) {
mListener.onTouchDown();
}
return interceptTouch;
}
}