在 ListView 中显示 ContactContracts 名称、电子邮件、照片,使用 Fragment - Android

Posted

技术标签:

【中文标题】在 ListView 中显示 ContactContracts 名称、电子邮件、照片,使用 Fragment - Android【英文标题】:Display ContactContracts Name, Email, Photo in ListView, using Fragment - Android 【发布时间】:2015-02-22 05:30:18 【问题描述】:

我有一个活动需要将 android 手机联系人显示到 ListView 中,这是我的 AddressBook.java 活动中的一个片段。我能够让我的列表显示名称,但没有别的。我觉得我很接近,但很难让这些观点发挥作用。在我的 XML 文件(我有 4 个)中,我有活动 XML(只有片段)、ListView XML (contact_list_view.xml),然后是 ListView 的典型行,我称之为我的 Item XML (contacts_list_item.xml) .但是如何将所有这些视图连接到我的活动视图中呢?我认为我在活动中的片段可以,因为名称列表有效,但不确定如何获取照片和电子邮件以显示。我知道我的主代码中也遗漏了一些东西,ContactFragments.java

一个问题是我必须按姓名过滤我的联系人,否则我手机上每个应用程序中的每封电子邮件都会发布,这不是我想要的。我只希望我的 Android 联系人应用程序中的联系人显示,所以我希望这不会阻止显示联系人的其他详细信息。

下面是我的代码,我没有显示我的AddressBook.java 活动,因为我只使用 XML 视图在其中显示我的片段,使用片段标签(效果很好,因为我至少得到了联系人名字)。

我已经在网上广泛搜索了这个问题的答案,但是有很多部分,我找不到如何解决我的具体情况。我希望使用我已经拥有的代码并对其进行最少的编辑(而不是实现一种全新的方法来实现其他类等)。如果您有任何想法,我将非常感谢。

ContactsFragment.java

package org.azurespot.practiceapp.addressbook;

import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentUris;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import com.example.practiceapp.R;

/*
 * Taken from http://***.com/questions/18199359/how-to-display-contacts-in-a-listview-in-android-for-android-api-11
 */

public class ContactsFragment extends ListFragment implements 
                                LoaderCallbacks<Cursor>

    private CursorAdapter mAdapter;
    public ListView listView;
    public Cursor cursor;
    // Name should be displayed in the text1 TextView in item layout
    public static final String[] FROM =  ContactsContract.Contacts
                                                .DISPLAY_NAME_PRIMARY ;
    private static final int[] TO =  android.R.id.text1 ;
    private android.content.Context context;
    public View view;
    public static Uri uri;


    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        // delete list if already there (old version)
        if (!(listView == null))
            listView.setAdapter(null);
        

        // create adapter once
        context = getActivity();
        int layout = android.R.layout.simple_list_item_1;
        Cursor c = null; // there is no cursor yet
        int flags = 0; // no auto-requery! Loader requeries.

        // put List in adapter
        mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);


     // end onCreate


    // columns requested from the database
    private static final String[] PROJECTION = 
            Contacts._ID,
            ContactsContract.Contacts.PHOTO_THUMBNAIL_URI,
            ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
            ContactsContract.Contacts.HAS_PHONE_NUMBER,
            ContactsContract.Contacts.IN_VISIBLE_GROUP
    ;

    // this goes in the CursorLoader parameter list, it filters
    // out only those contacts who have a phone number
    private static final String SELECTION = 
            ContactsContract.Contacts.HAS_PHONE_NUMBER + "='1'";

    // Empty public constructor, required by the system
    public ContactsFragment() 

    // A UI Fragment must inflate its View (all fragments must override onCreateView)
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) 
        // Inflate the fragment layout
        View view =  inflater.inflate(R.layout.contact_list_view,
            container, false);
        listView = (ListView) view.findViewById(R.id.list); 

        // set Contact photo to ImageView
        ContactsFragment frag = new ContactsFragment();
        ImageView thumb = (ImageView)view.findViewById(R.id.contact_thumbnail);
        frag.getPhotoUriFromID(Contacts._ID);
        thumb.setImageURI(uri);
        return view;
    

    public void onActivityCreated(Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);

        // and tell loader manager to start loading
        getLoaderManager().initLoader(0, null, this);

        listView.setAdapter(mAdapter);
        listView.setFastScrollEnabled(true);

    

    // a CursorLoader does a query in the background
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) 
        // load from the "Contacts table"
        Uri contentUri = Contacts.CONTENT_URI;

        // no sub-selection, no sort order, simply every row
        // projection says we want just the _id and the name column
        return new CursorLoader(getActivity(),
                contentUri,
                PROJECTION,
                SELECTION,
                null,
                ContactsContract.Contacts.DISPLAY_NAME
        );
    

    private Uri getPhotoUriFromID(String id) 
        try 
            Cursor cur = context.getContentResolver()
                    .query(ContactsContract.Data.CONTENT_URI,
                            null,
                            ContactsContract.Data.CONTACT_ID
                                    + "="
                                    + id
                                    + " AND "
                                    + ContactsContract.Data.MIMETYPE
                                    + "='"
                                    + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
                                    + "'", null, null);
            if (cur != null) 
                if (!cur.moveToFirst()) 
                    return null; // no photo
                
             else 
                return null; // error in cursor process
            
         catch (Exception e) 
            e.printStackTrace();
            return null;
        
        Uri person = ContentUris.withAppendedId(
                ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
         uri = Uri.withAppendedPath(person,
                ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
         return uri;
    

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) 
         // Once cursor is loaded, give it to adapter
        mAdapter.swapCursor(data);
    

    @Override
    public void onLoaderReset(Loader<Cursor> loader) 
        // Delete the reference to the existing Cursor,
        // so it can recycle it
        mAdapter.swapCursor(null);
    

contact_list_view.xml

<?xml version="1.0" encoding="utf-8"?>

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list"
    android:layout_
    android:layout_ >
</ListView>

contacts_list_item

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical" >

        <ImageView
        android:id="@+id/contact_thumbnail"
        android:layout_
        android:layout_
        android:contentDescription="@string/thumbnail" />

        <TextView 
          android:id='@+id/text_name'
          android:layout_
          android:layout_
          android:clickable="true"/>
</LinearLayout>

【问题讨论】:

【参考方案1】:

您应该重写适配器的 getView() 方法并创建一个自定义列表视图来显示图像、名称和电子邮件。

更多详情请参考此链接http://www.androidhive.info/2014/07/android-custom-listview-with-image-and-text-using-volley/

【讨论】:

感谢 Arjun,但我正试图从我的 Contacts 中撤出,这是一个完全不同的野兽,而不仅仅是一个 ListView。有的教程说CursorLoader有自己的观点,我就不用提供了。然后其他人说使用我的Cursor 从查询中获取照片/电子邮件,访问ContactContracts.Data 类表。仍在研究,但如果我发现更多,我会在这里注明。不过感谢您的想法。【参考方案2】:

假设您的光标正在返回所有适当的数据,看起来您只需要在初始化适配器时调整一些起始值。尝试更新以下内容:

public static final String[] FROM =  ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Contacts.PHOTO_THUMBNAIL_URI ;
private static final int[] TO =  R.id.text_name, R.id.contact_thumbnail ;

int layout = R.layout.contact_list_item;

这应该让您的适配器同时显示图像和显示名称。不需要按照 Arjun Sna 的建议覆盖 getView() 方法,因为 SimpleCursorAdapter 支持同时显示 TextViewImageView。如果要添加电子邮件,则需要更新 XML 以包含另一个 TextView,然后将其关联信息添加到 FROM 和 TO 数组。

【讨论】:

以上是关于在 ListView 中显示 ContactContracts 名称、电子邮件、照片,使用 Fragment - Android的主要内容,如果未能解决你的问题,请参考以下文章

解决在ScrollView中套用ListView显示不正常

ScrollView中嵌套ListView时,listview高度显示的问题

使用动画在 ListView 中显示/隐藏小部件

如何在Android中的ListView中突出显示行?

Django:在 DataTables、ListView 中显示图像

delphi中listview显示居中