在Android中编程选择ListView中的项目

57

我有两个片段。第一个片段内有按钮,第二个片段内有ListView(列表片段)。

我希望第一个片段(借助其按钮)允许用户浏览第二个片段中的ListView。

因此,我想让第一个片段通过按钮来控制ListView。

我没有问题在片段之间进行通信(从第一个片段发送命令到第二个片段),但我不知道如何告诉我的ListView选择(以编程方式)一个特定的列表项。

我应该使用什么类型的ListView,并如何告诉它选择/突出显示/聚焦其中的一项?

当用户按下第一个片段的按钮时,我处于触摸模式。

我应该使用setFocusableInTouchMode(true)还是setChoiceMode(ListView.CHOICE_MODE_SINGLE)或其他什么操作?


我正在制作一个聊天应用程序并创建FCM推送通知。当FCM通知到来时,我希望它能进入聊天室,但是当我设置一个链接到聊天室时,应用程序会崩溃,请帮助我如何解决这个问题。 - Ashish Shahi
另外,您已经给了我一个想法,即在不点击列表视图项的情况下自动选择列表视图,其人员值通过字符串值传递。这非常紧急,请帮助我。先行致谢。 - Ashish Shahi
9个回答

144

以下是想要编程选择ListView项目并使其保持高亮的所有人:

-编程选择ListView中的一个项目

-使该项目保持高亮

我正在使用Android ICS,不知道是否适用于所有级别的API。

首先创建一个ListView(或者如果您已经在ListActivity/ListFragment中,则获取它)

然后通过以下方式将listview的选择模式设置为单个Mylistview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

然后使用以下代码编程选择您的项目Mylistview.setItemChecked(position, true); (其中position是指要选择的项的排名整数)

现在您的项目实际上已被选择,但您可能什么也看不到,因为没有选择的视觉反馈。现在您有两个选择:您可以使用预构建的listview或自定义的listview。

1) 如果您想要预构建的listview,请尝试使用simple_list_item_activated_1simple_list_item_checkedsimple_list_item_single_choice等...

例如,您可以像这样设置列表视图:setListAdapter(new ArrayAdapter<String>(this, R.layout.simple_list_item_activated_1, data))

根据您选择的预构建listview,您现在会看到在选择时复选框被选中或背景颜色更改等...

2) 如果您使用自定义listview,则需要定义一个将在每个项目中使用的自定义布局。在此XML布局中,您将为需要在选择时更改的每个部分视图分配一个选择器。

假设在选择时,您希望行更改文本颜色和背景颜色。您的XML布局可以编写如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/menu_item_background_selector"
    android:orientation="horizontal" >

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:textColor="@drawable/menu_item_text_selector" />

现在,在drawable文件夹中创建menu_item_background_selector.xml和menu_item_text_selector.xml。

menu_item_text_selector.xml:

 <?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_activated="true"
     android:color="#FFF">
</item>

<item android:state_pressed="true"
     android:color="#FFF">
</item>

<item android:state_pressed="false"
     android:color="#000">
</item>

</selector>

当被选中时,文本将变为白色。

接下来对背景做类似的操作:(记住你不必使用颜色,也可以使用drawable)

menu_item_background_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">


        <item android:state_activated="true"
        android:color="#0094CE">
        </item>

        <item android:state_pressed="true"
        android:color="#0094CE">
        </item>

        <item android:state_pressed="false"
        android:color="#ACD52B">
        </item>


      </selector>

当被选中时,背景是蓝色的;未被选中时,背景是绿色的。

我缺少的主要元素是android:state_activated。确实有(太)多种状态:activated、pressed、focused、checked、selected......

我不确定我提供的android:state_activatedandroid:state_pressed示例是否是最佳且最清晰的,但它似乎对我有效。

但是我不需要创建自己的类来获得一个自定义的CheckableRelativeLayout(这很不清真),也没有使用CheckableTextViews。我不知道其他人为什么要使用这样的方法,可能取决于API级别。


4
好的回答!但是我可以确认在Gingerbread及更早版本中不起作用。(state_activated是在Honeycomb中添加的,API级别为11。) - benkc
2
你忘了提到应该使用 Mylistview.getCheckedItemPosition(); 方法来检索你选择的项目的位置。 - Alex Semeniuk
6
为了安全起见,您不应将Mylistview.setChoiceMode设置为1。您应该将其设置为AbsListView.CHOICE_MODE_SINGLE。虽然目前它等于1,但在未来的API版本中,它们可能会更改。 - Jason Teplitz
8
对于其他人我不确定,但对我来说,我以前为背景选择器使用了RelativeLayout,但该应用程序一直崩溃(XML填充异常)。 通过在背景可绘制中更改android:colorandroid:drawable,我设法让它正常工作(无论如何你仍然可以使用颜色)。 无论如何,感谢您提供的解决方案,它非常有效! - Quentin Klein
3
谢谢。还要感谢@Quentin提供的提示,否则这会浪费我几个小时!在使用android:drawable时,必须使用在colors.xml中指定的@color/<customcolor>。 例如:android:drawable="@color/pressed_color",其中“pressed_color”在colors.xml中定义为<color name="pressed_color">#CACFD2</color>。 - madu
显示剩余5条评论

15

10
这是我的做法:

1)设置列表的选择行为。

 mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

2) 设置指定位置的选中状态。

mListView.setItemChecked(1,true); //Don't make the same mistake I did by calling this function before setting the listview adapter.

3) 在样式资源(res/values)中添加一个新的样式,如下所示:

<style name="activated" parent="android:Theme.Holo">
<item name="android:background">@android:color/holo_green_light</item>
</style>

请随意使用您喜欢的颜色。

4) 在您的ListView中使用先前定义的样式

<ListView
        android:id="@+id/listview"
        style="@style/activated"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"/>

在你使用的布局中,也可以作为行来使用。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content" 
  style="@style/activated"
>
  <!--widgets for your row here-->

</LinearLayout>

希望这能帮助到任何人!

4

Jecimi的回答对我有用,但有一小部分不行。我想与他人分享。在FragmentActivity的onCreate()中调用list.setItemChecked( 0, true )没有起作用。在适配器的getView()中,list.getCheckedItemPosition()返回-1。

我必须从protected void onPostCreate(Bundle savedInstanceState)中调用此方法。


所有生命周期技巧结束后,如果动态更改适配器有什么解决方案? - A. Petrov

4
尝试使用mListView.setSelection(position);

5
例如,如果我使用mListView.setSelection(20),它会将用户发送到列表的第20个项目。但是你有没有什么想法让这个项目保持选定状态(或高亮显示)? - Jecimi
3
实际上在我的情况下,最好使用 listview.setItemChecked(position, true);(如果您想了解更多详情,请查看我的答案)。无论如何,感谢您的回答:) - Jecimi
只有在非触摸模式下(文档明确说明),setSelection()才能正常工作。 - Alex Semeniuk
@AlexSemeniuk,我认为我们对“清楚”有不同的看法,文档在哪里说明了这一点?还有,为记录,我同意setSelection()在触摸模式下似乎无法工作。 - Constantin
1
@Constantin,这是链接:http://developer.android.com/reference/android/widget/ListView.html#setSelection(int)。短语“如果在触摸模式下,则不会选择该项,但仍将适当定位”比目前更加“清晰”。 - Alex Semeniuk

0
package com.example.samsung;

import com.example.samsung.*;
import com.example.samsung.R;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;

public class Firstscreen extends Activity implements OnItemSelectedListener {
    Button btn;
     Spinner sp;
     public String[] product = { "ML-1676P/XIP","SLM2021W/XIP","SL-M2826ND/XIP","SL-M2826ND/XIP","SL-M2826ND/XIP","SL-M3320ND/XIP","SL-M3820ND/XIP","SL-M4020ND/XIP"};  


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_firstscreen);
        btn = (Button) findViewById(R.id.bn);
        sp= (Spinner) findViewById(R.id.sp);
    }
        public void button (View v){
            {

        Intent i = new Intent(Firstscreen.this,ML1676P.class);
        startActivity(i);
        }

        Spinner s1 = (Spinner) findViewById(R.id.sp);
        ArrayAdapter<String> adapter 
        = new ArrayAdapter<String>(this, 
                android.R.layout.simple_spinner_item, product); // find other layout parameters
        s1.setAdapter(adapter);
        s1.setOnItemSelectedListener(new OnItemSelectedListener()
        {

            @Override
            public void onItemSelected(AdapterView<?> arg0, View arg1,
                    int arg2, long arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
                // TODO Auto-generated method stub

            }

    });
    }

    private Object product() {
            // TODO Auto-generated method stub
            return null;
        }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.firstscreen, menu);
        return true;
    }

    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
            long arg3) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
        // TODO Auto-generated method stub


    }



}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".Firstscreen"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FF35B5E5"
        android:layout_centerInParent="true"
        android:text="CHOOSE THE PRODUCT FROM THE LIST" />

    <Spinner
        android:id="@+id/sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:drawSelectorOnTop="true" />

    <Button
        android:id="@+id/bn"
        android:layout_width="285dp"
        android:layout_height="wrap_content"
        android:text="       GO             " 
        android:onClick="button"/>


</LinearLayout>

在ListView中选择一个项目,然后在单击按钮时,应该进入特定选定项页面,如何实现呢? 代码如上所示


0

我喜欢这样做:

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            try {
                int pos = 0;
                listview.performItemClick(null, pos, listview.getItemIdAtPosition(pos) );
            } catch (Exception e) {
                e.printStackTrace();
            }
        } 
    }

0

您可以使用 ListView#setSelection(int) 方法


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接