Отображение эмблемы контакта

Этот урок покажет вам, как добавить QuickContactBadge в пользовательский интерфейс, и как связать данные. QuickContactBadge это виджет, который изначально выглядит как эскиз изображения. Хотя вы можете использовать любой Bitmap как эскиз изображения, вы обычно используете Bitmap , декодированный из уменьшенного фото контакта .

Небольшое изображение используется для управления; когда пользователи нажимают на изображение, QuickContactBadge расширяется в диалог, содержащий следующее:

Большое изображение
Большое изображение, связанное с контактом, или графический заполнитель, если изображение доступно.
Иконки приложений
Значок приложения для каждой части подробных данных, которые могут быть обработаны с помощью встроенных приложений. Например, если контакт включает один или несколько адресов электронной почты, появляется значок приложения электронной почты. Когда пользователь нажимает на иконку, появляются все адреса электронной почты контакта. Когда пользователь нажимает на один из адресов, приложение электронной почты отображает экран для составления сообщения для выбранного адреса электронной почты.

QuickContactBadge представление обеспечивает мгновенный доступ к информации о контакте, а также быстрый способ связи с контактом. Пользователям не нужно искать контакт, находить и копировать информацию, а затем вставлять её в соответствующее приложение. Вместо этого, они могут нажать на QuickContactBadge, выбрать желаемый способ связи, и отправить информацию непосредственно в соответствующее приложение.

Добавление QuickContactBadge представления

Для добавления QuickContactBadge, вставьте <QuickContactBadge> элемент в макет. Например:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
...
    <QuickContactBadge
               android:id=@+id/quickbadge
               android:layout_height="wrap_content"
               android:layout_width="wrap_content"
               android:scaleType="centerCrop"/>
    ...
</RelativeLayout>

Получение данных поставщика

Для отображения контакта в QuickContactBadge, вам нужен URI контента для контакта и Bitmap для эскиза изображения. Вы генерируете как URI контента так и Bitmap на основе столбцов, полученных от поставщика контакта. Укажите эти столбцы как часть проекции, которую вы используете для загрузки данных в ваш Cursor.

Для Android 3.0 (API уровень 11) и новее, включают следующие столбцы в вашу проекцию:

Для Android 2.3.3 (API уровень 10) и ранее, используйте следующие столбцы:

В оставшейся части этого урока предполагается, что вы уже загрузили Cursor , который содержит эти столбцы, а также другие, которые вам нужны. Чтобы узнать, как получить эти столбцы через Cursor, читайте урок Получение списка контактов.

Установка URI контакта и эскиза

Как только у вас есть необходимые столбцы, вы можете связать данные с QuickContactBadge.

Установка URI контакта

Чтобы установить URI контента для контакта, вызовите getLookupUri(id,lookupKey) для получения CONTENT_LOOKUP_URI, затем вызовите assignContactUri() для установки контакта. Например:

    // The Cursor that contains contact rows
    Cursor mCursor;
    // The index of the _ID column in the Cursor
    int mIdColumn;
    // The index of the LOOKUP_KEY column in the Cursor
    int mLookupKeyColumn;
    // A content URI for the desired contact
    Uri mContactUri;
    // A handle to the QuickContactBadge view
    QuickContactBadge mBadge;
    ...
    mBadge = (QuickContactBadge) findViewById(R.id.quickbadge);
    /*
     * Insert code here to move to the desired cursor row
     */
    // Gets the _ID column index
    mIdColumn = mCursor.getColumnIndex(Contacts._ID);
    // Gets the LOOKUP_KEY index
    mLookupKeyColumn = mCursor.getColumnIndex(Contacts.LOOKUP_KEY);
    // Gets a content URI for the contact
    mContactUri =
            Contacts.getLookupUri(
                mCursor.getLong(mIdColumn),
                mCursor.getString(mLookupKeyColumn)
            );
    mBadge.assignContactUri(mContactUri);

Когда пользователь нажимает QuickContactBadge значок, автоматически появляется диалог со сведениями о контакте.

Установка эскиза фотографии

Установка URI контакта для QuickContactBadge не загружает автоматически эскиз фото для контакта. Чтобы загрузить фотографию, получите URI для фото контакта из Cursor , используйте его для открытия файла, содержащий сжатый эскиз фотографии, и загрузите файл в Bitmap.

Примечание: PHOTO_THUMBNAIL_URI столбец не доступен в версиях платформы до 3.0. Для тех версиях, вы должны получить URI из Contacts.Photo подтаблицы.

Сначала установите переменные для доступа к Cursor содержащий Contacts._ID и Contacts.LOOKUP_KEY столбцы, как было описано ранее:

    // The column in which to find the thumbnail ID
    int mThumbnailColumn;
    /*
     * The thumbnail URI, expressed as a String.
     * Contacts Provider stores URIs as String values.
     */
    String mThumbnailUri;
    ...
    /*
     * Gets the photo thumbnail column index if
     * platform version >= Honeycomb
     */
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        mThumbnailColumn =
                mCursor.getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI);
    // Otherwise, sets the thumbnail column to the _ID column
    } else {
        mThumbnailColumn = mIdColumn;
    }
    /*
     * Assuming the current Cursor position is the contact you want,
     * gets the thumbnail ID
     */
    mThumbnailUri = mCursor.getString(mThumbnailColumn);
    ...

Определите метод, который принимает данные связанные с фото для контакта и размером представления, и возвращает эскиз соответствующего размера в виде Bitmap. Начните с построения URI, который указывает на эскиз:

    /**
     * Load a contact photo thumbnail and return it as a Bitmap,
     * resizing the image to the provided image dimensions as needed.
     * @param photoData photo ID Prior to Honeycomb, the contact's _ID value.
     * For Honeycomb and later, the value of PHOTO_THUMBNAIL_URI.
     * @return A thumbnail Bitmap, sized to the provided width and height.
     * Returns null if the thumbnail is not found.
     */
    private Bitmap loadContactPhotoThumbnail(String photoData) {
        // Creates an asset file descriptor for the thumbnail file.
        AssetFileDescriptor afd = null;
        // try-catch block for file not found
        try {
            // Creates a holder for the URI.
            Uri thumbUri;
            // If Android 3.0 or later
            if (Build.VERSION.SDK_INT
                    >=
                Build.VERSION_CODES.HONEYCOMB) {
                // Sets the URI from the incoming PHOTO_THUMBNAIL_URI
                thumbUri = Uri.parse(photoData);
            } else {
            // Prior to Android 3.0, constructs a photo Uri using _ID
                /*
                 * Creates a contact URI from the Contacts content URI
                 * incoming photoData (_ID)
                 */
                final Uri contactUri = Uri.withAppendedPath(
                        Contacts.CONTENT_URI, photoData);
                /*
                 * Creates a photo URI by appending the content URI of
                 * Contacts.Photo.
                 */
                thumbUri =
                        Uri.withAppendedPath(
                                contactUri, Photo.CONTENT_DIRECTORY);
            }
    
        /*
         * Retrieves an AssetFileDescriptor object for the thumbnail
         * URI
         * using ContentResolver.openAssetFileDescriptor
         */
        afd = getActivity().getContentResolver().
                openAssetFileDescriptor(thumbUri, "r");
        /*
         * Gets a file descriptor from the asset file descriptor.
         * This object can be used across processes.
         */
        FileDescriptor fileDescriptor = afd.getFileDescriptor();
        // Decode the photo file and return the result as a Bitmap
        // If the file descriptor is valid
        if (fileDescriptor != null) {
            // Decodes the bitmap
            return BitmapFactory.decodeFileDescriptor(
                    fileDescriptor, null, null);
            }
        // If the file isn't found
        } catch (FileNotFoundException e) {
            /*
             * Handle file not found errors
             */
        }
        // In all cases, close the asset file descriptor
        } finally {
            if (afd != null) {
                try {
                    afd.close();
                } catch (IOException e) {}
            }
        }
        return null;
    }

Вызовите loadContactPhotoThumbnail() метод в вашем коде для получения эскиза в виде Bitmap, и используйте результат для установки эскиза фотографии в QuickContactBadge:

    ...
    /*
     * Decodes the thumbnail file to a Bitmap.
     */
    Bitmap mThumbnail =
            loadContactPhotoThumbnail(mThumbnailUri);
    /*
     * Sets the image in the QuickContactBadge
     * QuickContactBadge inherits from ImageView, so
     */
    mBadge.setImageBitmap(mThumbnail);

Добавление QuickContactBadge в ListView

QuickContactBadge является полезным дополнением к ListView , который отображает список контактов. Используйте QuickContactBadge для отображения эскизов фотографий для каждого контакта; когда пользователи нажимают на эскиз, QuickContactBadge диалог появится.

Добавьте QuickContactBadge элемент

Для начала, добавьте QuickContactBadge элемент для представления в макет. Например, если вы хотите отобразить QuickContactBadge и имя для каждого контакта, который вы получили, поместите следующий XML в файл макета:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
    <QuickContactBadge
        android:id="@+id/quickcontact"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:scaleType="centerCrop"/>
    <TextView android:id="@+id/displayname"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_toRightOf="@+id/quickcontact"
              android:gravity="center_vertical"
              android:layout_alignParentRight="true"
              android:layout_alignParentTop="true"/>
</RelativeLayout>

В следующих разделах, этот файл называется contact_item_layout.xml.

Настройка пользовательского CursorAdapter

Для привязки CursorAdapter к ListView содержащий QuickContactBadge, определите пользовательский адаптер, который расширяет CursorAdapter. Такой подход позволяет обрабатывать данные в Cursor прежде чем привязать их к QuickContactBadge. Этот подход также позволяет привязывать несколько Cursor столбцов к QuickContactBadge. Ни одна из этих операций не возможна с обычным CursorAdapter.

Подкласс CursorAdapter , который вы определяете должен переопределить следующие методы:

CursorAdapter.newView()
Заполняет новый View объект, содержащий элемент макета. В переопределенном методе, сохраните данные связанные с дочерними View объектами макета, включая дочерние QuickContactBadge. Использую такой подход, можно избежать получения данных дочерних View объектов каждый раз, когда вы заполняете новый макет.

Вы должны переопределить этот метод, чтобы вы могли работать индивидуально с дочерними View объектами. Этот метод позволяет контролировать их связывание в CursorAdapter.bindView().

CursorAdapter.bindView()
Копирует данные из текущей Cursor строки в дочерние View объекты макета. Вы должны переопределить этот метод, чтобы иметь возможность связать как URI контакта так и эскиз для QuickContactBadge. Реализация по умолчанию позволяет задать только связь 1-к-1 между столбцом и View

Следующий фрагмент кода содержит пример пользовательского подкласса CursorAdapter:

Определение пользовательского адаптера списка

Определите подкласс CursorAdapter , включая его конструктор, и переопределите newView() и bindView():

    /**
     *
     *
     */
    private class ContactsAdapter extends CursorAdapter {
        private LayoutInflater mInflater;
        ...
        public ContactsAdapter(Context context) {
            super(context, null, 0);

            /*
             * Gets an inflater that can instantiate
             * the ListView layout from the file.
             */
            mInflater = LayoutInflater.from(context);
            ...
        }
        ...
        /**
         * Defines a class that hold resource IDs of each item layout
         * row to prevent having to look them up each time data is
         * bound to a row.
         */
        private class ViewHolder {
            TextView displayname;
            QuickContactBadge quickcontact;
        }
        ..
        @Override
        public View newView(
                Context context,
                Cursor cursor,
                ViewGroup viewGroup) {
            /* Inflates the item layout. Stores resource IDs in a
             * in a ViewHolder class to prevent having to look
             * them up each time bindView() is called.
             */
            final View itemView =
                    mInflater.inflate(
                            R.layout.contact_list_layout,
                            viewGroup,
                            false
                    );
            final ViewHolder holder = new ViewHolder();
            holder.displayname =
                    (TextView) view.findViewById(R.id.displayname);
            holder.quickcontact =
                    (QuickContactBadge)
                            view.findViewById(R.id.quickcontact);
            view.setTag(holder);
            return view;
        }
        ...
        @Override
        public void bindView(
                View view,
                Context context,
                Cursor cursor) {
            final ViewHolder holder = (ViewHolder) view.getTag();
            final String photoData =
                    cursor.getString(mPhotoDataIndex);
            final String displayName =
                    cursor.getString(mDisplayNameIndex);
            ...
            // Sets the display name in the layout
            holder.displayname = cursor.getString(mDisplayNameIndex);
            ...
            /*
             * Generates a contact URI for the QuickContactBadge.
             */
            final Uri contactUri = Contacts.getLookupUri(
                    cursor.getLong(mIdIndex),
                    cursor.getString(mLookupKeyIndex));
            holder.quickcontact.assignContactUri(contactUri);
            String photoData = cursor.getString(mPhotoDataIndex);
            /*
             * Decodes the thumbnail file to a Bitmap.
             * The method loadContactPhotoThumbnail() is defined
             * in the section "Set the Contact URI and Thumbnail"
             */
            Bitmap thumbnailBitmap =
                    loadContactPhotoThumbnail(photoData);
            /*
             * Sets the image in the QuickContactBadge
             * QuickContactBadge inherits from ImageView
             */
            holder.quickcontact.setImageBitmap(thumbnailBitmap);
    }

Инициализация переменных

В коде установите переменные, включая Cursor проекцию, которая включает в себя необходимые столбцы.

Примечание: Следующие фрагменты кода используют метод loadContactPhotoThumbnail(), который определен в разделе Установка URI контакта и эскиза

Например:

public class ContactsFragment extends Fragment implements
        LoaderManager.LoaderCallbacks<Cursor> {
...
    // Defines a ListView
    private ListView mListView;
    // Defines a ContactsAdapter
    private ContactsAdapter mAdapter;
    ...
    // Defines a Cursor to contain the retrieved data
    private Cursor mCursor;
    /*
     * Defines a projection based on platform version. This ensures
     * that you retrieve the correct columns.
     */
    private static final String[] PROJECTION =
            {
                Contacts._ID,
                Contacts.LOOKUP_KEY,
                (Build.VERSION.SDK_INT >=
                 Build.VERSION_CODES.HONEYCOMB) ?
                        Contacts.DISPLAY_NAME_PRIMARY :
                        Contacts.DISPLAY_NAME
                (Build.VERSION.SDK_INT >=
                 Build.VERSION_CODES.HONEYCOMB) ?
                        Contacts.PHOTO_THUMBNAIL_ID :
                        /*
                         * Although it's not necessary to include the
                         * column twice, this keeps the number of
                         * columns the same regardless of version
                         */
                        Contacts_ID
                ...
            };
    /*
     * As a shortcut, defines constants for the
     * column indexes in the Cursor. The index is
     * 0-based and always matches the column order
     * in the projection.
     */
    // Column index of the _ID column
    private int mIdIndex = 0;
    // Column index of the LOOKUP_KEY column
    private int mLookupKeyIndex = 1;
    // Column index of the display name column
    private int mDisplayNameIndex = 3;
    /*
     * Column index of the photo data column.
     * It's PHOTO_THUMBNAIL_URI for Honeycomb and later,
     * and _ID for previous versions.
     */
    private int mPhotoDataIndex =
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
            3 :
            0;
    ...

Настройка ListView

В Fragment.onCreate(), создайте экземпляр адаптера пользовательского курсора и получите указатель на ListView:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        /*
         * Instantiates the subclass of
         * CursorAdapter
         */
        ContactsAdapter mContactsAdapter =
                new ContactsAdapter(getActivity());
        /*
         * Gets a handle to the ListView in the file
         * contact_list_layout.xml
         */
        mListView = (ListView) findViewById(R.layout.contact_list_layout);
        ...
    }
    ...

В onActivityCreated(), привяжите ContactsAdapter к ListView:

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        ...
        // Sets up the adapter for the ListView
        mListView.setAdapter(mAdapter);
        ...
    }
    ...

Когда вы получите Cursor , содержащий данные контактов, как правило, в onLoadFinished(), вызовите swapCursor() для перемещения Cursor данных в ListView. Это отображает QuickContactBadge для каждой записи списка контактов:

    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        // When the loader has completed, swap the cursor into the adapter.
        mContactsAdapter.swapCursor(cursor);
    }

Когда вы привязываете Cursor к ListView с CursorAdapter (или подкласс), и вы используете CursorLoader для загрузки Cursor, всегда очищайте ссылки на Cursor в вашей реализации onLoaderReset(). Например:

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // Removes remaining reference to the previous Cursor
        mContactsAdapter.swapCursor(null);
    }