android - 在显示所有已安装应用程序的ListView和实现OnItemClickListener时出现问题

原文 标签 android

Issues Displaying a ListView of All Installed Apps and Implementing an OnItemClickListener

I am trying to write a very simple app that displays the name of every installed app on the device in a listview. I am using Google's ListView tutorial as a base.

Here is my code:

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

        final PackageManager pm = this.getPackageManager();

        Intent intent = new Intent(Intent.ACTION_MAIN, null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);

        final ArrayList<ResolveInfo> list =
                (ArrayList<ResolveInfo>) pm.queryIntentActivities(intent, 
                        PackageManager.PERMISSION_GRANTED);
        for (ResolveInfo rInfo : list)
        {
            Log.i(TAG, ": Installed Applications " + rInfo.activityInfo.
                    applicationInfo.loadLabel(pm).toString());
        }

        final ArrayAdapter<ResolveInfo> adapter = 
            new ArrayAdapter<ResolveInfo>(this, R.layout.list_item, list)
            {
            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                    convertView = LayoutInflater.from(parent.getContext()).
                        inflate(R.layout.list_item, parent, false);

                final String text = list.get(position).activityInfo.
                    applicationInfo.loadLabel(pm).toString();
                ((TextView)convertView.findViewById(R.id.text)).setText(text);

                final Drawable drawable = list.get(position).activityInfo.applicationInfo.loadIcon(pm);
                ((ImageView)convertView.findViewById(R.id.image)).setImageDrawable(drawable);

                return convertView;
            }

            };
        setListAdapter(adapter);

        ListView lv = getListView();
        lv.setTextFilterEnabled(true);
        lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

                // On Item Click Activity
                // This is where I want to send the Package Name of the app selected to be passed to a method.


            }
          });
    }




 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ImageView android:id="@+id/image" 
        android:layout_width="50dp" android:layout_height="50dp" />
    <TextView android:id="@+id/text"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:padding="10dp" android:textSize="16sp" />
</LinearLayout>   

UPDATE: I now need to use an OnItemClickListener to pass the Package Name of the App selected to a method.

Answer

To display your activities' names correctly in the list, you should override the getView method of your ListAdapter, and set some of your local variables as final (to work with inner class):

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

    final PackageManager pm = this.getPackageManager();

    Intent intent = new Intent(Intent.ACTION_MAIN, null);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);

    final ArrayList<ResolveInfo> list =
            (ArrayList<ResolveInfo>) pm.queryIntentActivities(intent, 
                    PackageManager.PERMISSION_GRANTED);
    for (ResolveInfo rInfo : list)
    {
        Log.i(TAG, ": Installed Applications " + rInfo.activityInfo.
                applicationInfo.loadLabel(pm).toString());
    }

    final ArrayAdapter<ResolveInfo> adapter = 
        new ArrayAdapter<ResolveInfo>(this, R.layout.list_item, list)
        {
            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                convertView = super.getView(position, convertView, parent);
                final String text = list.get(position).activityInfo.
                    applicationInfo.loadLabel(pm).toString();
                ((TextView)convertView).setText(text);
                return convertView;
            }
        };
    setListAdapter(adapter);

    ListView lv = getListView();
    lv.setTextFilterEnabled(true);
}

This way you have your custom ArrayAdapter implementation, which displays the proper label of applicationinfo in the TextView.

You can also achieve this, if you create a new ArrayList<String>, and populate it inside the for cycle where you log the applications:

final ArrayList<String> labelList = new ArrayList<String>();
for (ResolveInfo rInfo : list)
{
    Log.i(TAG, ": Installed Applications " + rInfo.activityInfo.
            applicationInfo.loadLabel(pm).toString());
    labelList.add(rInfo.activityInfo.
            applicationInfo.loadLabel(pm).toString());
}

final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
        R.layout.list_item, labelList);
setListAdapter(adapter);

Then you use this new labelList as the source of your adapter.

Update
To include the icon into the item renderers, the overridden getView method would look like:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    if (convertView == null)
        convertView = LayoutInflater.from(parent.getContext()).
            inflate(R.layout.list_item, parent, false);

    final String text = list.get(position).activityInfo.
        applicationInfo.loadLabel(pm).toString();
    ((TextView)convertView.findViewById(R.id.text)).setText(text);

    final Drawable drawable = list.get(position).activityInfo.applicationInfo.loadIcon(pm);
    ((ImageView)convertView.findViewById(R.id.image)).setImageDrawable(drawable);

    return convertView;
}

and your res/layout/list_item.xml layout file has to contain the text TextView and the image ImageView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ImageView android:id="@+id/image" 
        android:layout_width="50dp" android:layout_height="50dp" />
    <TextView android:id="@+id/text"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:padding="10dp" android:textSize="16sp" />
</LinearLayout>   

翻译

我正在尝试编写一个非常简单的应用程序,以列表视图显示设备上每个已安装应用程序的名称。我使用Google的ListView教程作为基础。

这是我的代码:

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

        final PackageManager pm = this.getPackageManager();

        Intent intent = new Intent(Intent.ACTION_MAIN, null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);

        final ArrayList<ResolveInfo> list =
                (ArrayList<ResolveInfo>) pm.queryIntentActivities(intent, 
                        PackageManager.PERMISSION_GRANTED);
        for (ResolveInfo rInfo : list)
        {
            Log.i(TAG, ": Installed Applications " + rInfo.activityInfo.
                    applicationInfo.loadLabel(pm).toString());
        }

        final ArrayAdapter<ResolveInfo> adapter = 
            new ArrayAdapter<ResolveInfo>(this, R.layout.list_item, list)
            {
            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                    convertView = LayoutInflater.from(parent.getContext()).
                        inflate(R.layout.list_item, parent, false);

                final String text = list.get(position).activityInfo.
                    applicationInfo.loadLabel(pm).toString();
                ((TextView)convertView.findViewById(R.id.text)).setText(text);

                final Drawable drawable = list.get(position).activityInfo.applicationInfo.loadIcon(pm);
                ((ImageView)convertView.findViewById(R.id.image)).setImageDrawable(drawable);

                return convertView;
            }

            };
        setListAdapter(adapter);

        ListView lv = getListView();
        lv.setTextFilterEnabled(true);
        lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

                // On Item Click Activity
                // This is where I want to send the Package Name of the app selected to be passed to a method.


            }
          });
    }




 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ImageView android:id="@+id/image" 
        android:layout_width="50dp" android:layout_height="50dp" />
    <TextView android:id="@+id/text"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:padding="10dp" android:textSize="16sp" />
</LinearLayout>   


更新:现在,我需要使用OnItemClickListener来将所选应用程序的包名称传递给方法。
最佳答案
为了在列表中正确显示活动的名称,您应该覆盖getViewListAdapter方法,并将一些局部变量设置为final(以使用内部类):

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

    final PackageManager pm = this.getPackageManager();

    Intent intent = new Intent(Intent.ACTION_MAIN, null);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);

    final ArrayList<ResolveInfo> list =
            (ArrayList<ResolveInfo>) pm.queryIntentActivities(intent, 
                    PackageManager.PERMISSION_GRANTED);
    for (ResolveInfo rInfo : list)
    {
        Log.i(TAG, ": Installed Applications " + rInfo.activityInfo.
                applicationInfo.loadLabel(pm).toString());
    }

    final ArrayAdapter<ResolveInfo> adapter = 
        new ArrayAdapter<ResolveInfo>(this, R.layout.list_item, list)
        {
            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                convertView = super.getView(position, convertView, parent);
                final String text = list.get(position).activityInfo.
                    applicationInfo.loadLabel(pm).toString();
                ((TextView)convertView).setText(text);
                return convertView;
            }
        };
    setListAdapter(adapter);

    ListView lv = getListView();
    lv.setTextFilterEnabled(true);
}


这样,您将拥有自定义的ArrayAdapter实现,该实现在TextView中显示applicationinfo的正确标签。

如果创建一个新的ArrayList<String>并将其填充到用于记录应用程序的for循环内,则也可以实现此目的:

final ArrayList<String> labelList = new ArrayList<String>();
for (ResolveInfo rInfo : list)
{
    Log.i(TAG, ": Installed Applications " + rInfo.activityInfo.
            applicationInfo.loadLabel(pm).toString());
    labelList.add(rInfo.activityInfo.
            applicationInfo.loadLabel(pm).toString());
}

final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
        R.layout.list_item, labelList);
setListAdapter(adapter);


然后,您可以使用这个新的labelList作为adapter的来源。

更新资料
要将图标包括在项目渲染器中,被覆盖的getView方法应类似于:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    if (convertView == null)
        convertView = LayoutInflater.from(parent.getContext()).
            inflate(R.layout.list_item, parent, false);

    final String text = list.get(position).activityInfo.
        applicationInfo.loadLabel(pm).toString();
    ((TextView)convertView.findViewById(R.id.text)).setText(text);

    final Drawable drawable = list.get(position).activityInfo.applicationInfo.loadIcon(pm);
    ((ImageView)convertView.findViewById(R.id.image)).setImageDrawable(drawable);

    return convertView;
}


并且您的res/layout/list_item.xml布局文件必须包含text TextViewimage ImageView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ImageView android:id="@+id/image" 
        android:layout_width="50dp" android:layout_height="50dp" />
    <TextView android:id="@+id/text"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:padding="10dp" android:textSize="16sp" />
</LinearLayout>   
相关推荐

android - 将png文件从一个文件夹复制到另一个

android - 如何在Android的画布上绘制路径?

android - HTML5音频+ Phonegap + Android?

android - android试图使用首选项保存数据,但是不起作用

android - 在设备上进行Android调试-LogCat不起作用!

android - Android Adb错误

java - 如何通过使用SQL WHERE子句搜索包含单引号的字符串

android - 如何在TabHost中更改颜色

android - Android:将额外的内容从一项活动传递到另一项活动

android - 如何在drawable文件夹内创建一个新文件夹并引用其中的图像?