Android - 单击后保持 ListView 的项目突出显示

Posted

技术标签:

【中文标题】Android - 单击后保持 ListView 的项目突出显示【英文标题】:Android - Keep ListView's item highlighted once one has been clicked 【发布时间】:2012-03-06 01:31:48 【问题描述】:

所以我有一个包含 2 个 ListView 小部件的活动,当您在第一个小部件中选择一个值时,第二个将填充与第一个 ListView 中的选择相关的值。这个机制没有问题,但现在我希望用户选择保持突出显示。我已经阅读了大量与该主题相关的问题,似乎有无数种方法可以实现这一点,但在尝试了大约 4-5 次之后,我仍然无法让它发挥作用。

我已经使用android:listSelector="#CCCCCC" XML 属性在第二个ListView 上工作了,但是一旦将OnItemClickListener 引入到组合中(就像我在第一个@ 987654328@).

到目前为止,这是我所拥有的:

自定义OnItemClickListener 我发现浏览了有关此主题的各种答案(稍作修改以使其在第二个 ListView 中加载我的信息):

private class ItemHighlighterListener implements OnItemClickListener 

    private View oldSelection = null;

    public void clearSelection() 
        if(oldSelection != null) 
            oldSelection.setBackgroundColor(android.R.color.transparent);
        
    

    public void onItemClick(AdapterView<?> parent, View view, int pos, long id) 
        clearSelection();
        oldSelection = view;
        view.setBackgroundDrawable(view.getContext().getResources().getDrawable(R.drawable.list_selector));
        loadClubs(mXMLPortalOptions.getRegion(pos).getId());
        mClubList.setAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.list_item_white, mClubs));
    

这是我的list_selector.xml 文件:

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

    <item android:state_selected="true"><shape>
            <solid android:color="#CCCCCC" />
        </shape></item>

    <item android:state_selected="false"><shape>
            <solid android:color="#FFFFFF" />
        </shape></item>

</selector>

调用并执行方法(OnItemClick),但我的ListItem的背景颜色保持不变:/

我不敢相信这个简单的任务竟然如此复杂。

如果我省略了可能有用的代码,或者我的问题缺乏细节,请随时指出,我会尽力解释自己。

【问题讨论】:

我认为这与您使用的SDK版本有关。 API 级别 7 是我正在使用的。 i.masm 的帖子有一个链接到我的想法。 android-developers.blogspot.com/2008/12/touch-mode.html 也许这会有所帮助:***.com/questions/15344320/… 【参考方案1】:

为所选项目放置一个位置变量。更改onItemClicked() 方法中的位置。查看getView()内List Adapter中选中的位置,并设置选中项的背景。

public class TestAdapter extends BaseAdapter

    private Context context;
    private ArrayList<TestList> testList;
    private int selectedIndex;
    private int selectedColor = Color.parseColor("#1b1b1b");

    public TestAdapter(Context ctx, ArrayList<TestList> testList)
    
        this.context = ctx;
        this.testList = testList;
        selectedIndex = -1;
    

    public void setSelectedIndex(int ind)
    
        selectedIndex = ind;
        notifyDataSetChanged();
    

    @Override
    public int getCount()
    
        return testList.size();
    

    @Override
    public Object getItem(int position)
    
        return testList.get(position);
    

    @Override
    public long getItemId(int position)
    
        return position;
    

    private class ViewHolder
    
        TextView tv;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    
        View vi = convertView;
        ViewHolder holder;
        if(convertView == null)
        
            vi = LayoutInflater.from(context).inflate(R.layout.test_list_item, null);
            holder = new ViewHolder();

            holder.tv = (TextView) vi;

            vi.setTag(holder);
        
        else
        
            holder = (ViewHolder) vi.getTag();
        

        if(selectedIndex!= -1 && position == selectedIndex)
        
            holder.tv.setBackgroundColor(Color.BLACK);
        
        else
        
            holder.tv.setBackgroundColor(selectedColor);
        
        holder.tv.setText("" + (position + 1) + " " + testList.get(position).getTestText());

        return vi;
    


现在在单击列表项时设置 selectedIndex 变量。

public class TestActivity extends Activity implements OnItemClickListener

    // Implemented onItemClickListener

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    
        adapter.setSelectedIndex(position);
    

【讨论】:

你能详细解释一下吗.. 我得到了一些东西,但不是 100%。所以请详细说明步骤..请 很好的解释 - 几个新概念都一口气解释了,谢谢! 伟大而简单,这就是我喜欢我的代码的地方!直到我将一些东西设为静态并移动了一些东西(见下面我的回答),我才让它工作。 +1 您好,我正在尝试将这种方法与可扩展的列表视图一起使用,但无法使其正常工作,每当我打开一个组时,我发现其中选择了一个项目 @R4j 它不应该让你的 UI 变慢。也许还有其他原因。每次notifyDataSetChanged() 调用时,只会更新可见的行数。【参考方案2】:

要扩展 Shaiful 的出色解决方案,您可能无法让他在您的情况下发挥作用。

如果您正在使用将代码全部放在public void onListItemClick(ListView l, View v, int index, long id) 中,如果您正在使用片段并且必须声明一个接口而不是实现 OnListItemClickListener,或者导致您的 IDE 生成错误的任何原因,您可能必须访问变量和静态方法。

public static int selectedPosition = 0;
ArrayAdapter<Your_obj> adapter = null;

@Override
public void onListItemClick(ListView l, View v, int index, long id) 
    super.onListItemClick(l, v, index, id);

        selectedPosition = index;
        Your_adapter.setSelectedIndex(selectedPosition);
        adapter.notifyDataSetChanged();

在 Your_adapter 中:

private static int selectedIndex;

//public Your_adapter...

public static void setSelectedIndex(int ind) 
    selectedIndex = ind;


@Override
public View getView(int position, View convertView, ViewGroup parent) 
    WellHolder holder = null;

    if (null == convertView) 

                //set up your "holder"
    

    if (position == selectedIndex) 
        convertView.setBackgroundColor(convertView.getResources().getColor(R.color.cyan));
    
    else 
        convertView.setBackgroundColor(convertView.getResources().getColor(R.color.silver));
    

    return convertView;

其他一些区别是您不必将任何变量初始化为“0”或“-1”,并且在您的活动中调用 notifyDataSetChanged()。

再次感谢@Shaiful 的解决方案。它确实帮助我节省了尝试让 ios 中的默认设置适用于 Android 的时间,同时避免选择器/项目/聚焦/按下/等。

【讨论】:

这是因为你没有使用状态列表,这是一个低效且不太合适的解决方案,最好依靠这种东西的平台【参考方案3】:

我遇到了类似的问题。这就是我的解决方案:

首先将自定义列表选择器添加到您的列表视图中:

<ListView
    android:id="@+id/list"
    android:layout_
    android:layout_
    android:listSelector="@drawable/listselector" />

在listselector.xml里面:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_accelerated="false"
        android:drawable="@drawable/bg" />
</selector>

最后是带有高亮颜色的可绘制 bg.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#33b5e6"/>
</shape>

【讨论】:

【参考方案4】:

我认为最好和最简单的解决方案就是这个。您不需要在 ListView 本身上设置任何 android:listSelector 或对适配器进行任何更改。您不需要甚至需要调用OnItemClickListener 中的任何setSelection(position),因为它会自动处理。

    设置为您的 ListView:

    android:choiceMode="singleChoice"
    

    设置列表项本身的背景:

    android:background="?android:attr/activatedBackgroundIndicator"
    

    就是这样。

这样您将获得默认的系统行为。这就是在默认的android.R.layout.simple_list_item_activated_1 布局中完成的方式。

【讨论】:

【参考方案5】:

lv.setSelector(R.drawable.highlighter);

highlighter.png 图像放入可绘制文件夹 在列表视图中突出显示所选项目的最简单方法。

【讨论】:

【参考方案6】:

两周前我正在寻找它,结果是可绘制选择器无法实现。 欲了解更多信息,请阅读 Android 开发者博客中的这篇文章:Touch Mode

在简历中:只有当您的手指在屏幕上时,才会选择项目。

另一种可能性是保存在 var 中选择的项目,并使用您的自定义适配器绘制不同的颜色,就像 Shaiful 说的那样。

【讨论】:

【参考方案7】:
//create a list_itemselectorin drawable folder
//you will get the list item selected background color change once you select //the item

    <selector xmlns:android="http://schemas.android.com/apk/res/android">

        <!-- Focused State -->
        <item android:state_focused="true"><shape>
                <solid android:color="#66FFFFFF" />
            </shape></item>
        <!-- Pressed State -->

        <item android:state_pressed="true"><shape>
                <solid android:color="@color/Black" />
            </shape></item>

        <!-- Default State -->
        <item><shape>
                <solid android:color="@color/Black" />
            </shape></item>

    </selector>


    //create a list in layout folder
      <ListView
            android:id="@+id/mySlidingList"
            android:layout_
            android:layout_
            android:choiceMode="singleChoice"
            android:divider="@color/GrayHot"
            android:dividerHeight="1dip"
            android:listSelector="@drawable/list_itemselector"
            android:scrollbars="none" />

// 并查看输出。

【讨论】:

【参考方案8】:

如果你可以使用drawable来显示listItem Highlighted,那么你应该使用以下代码:-

listView.setSelector(R.drawable.bg_image);

有效。

【讨论】:

【参考方案9】:

有一个简单的完全 XML 解决方案,它对我有用。 首先,使用选择器代码定义 XML-drawable,其中“正常”状态将对应于列表项的“选定未按下”视觉状态,而 state_pressed=true 对应于“按下”视觉状态。 文件“custom_item_selector.xml”示例,类似于 Holo 蓝色选择:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid
                android:color="#643292ff">
            </solid>
            <stroke
                android:
                android:color="#c83292ff">
            </stroke>
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid
                android:color="#323292ff">
            </solid>
            <stroke
                android:
                android:color="#783292ff">
            </stroke>
        </shape>
    </item>
</selector>

(也可以在那里设置焦点状态)。 其次,将此 xml-drawable 应用为 ListView 的 listSelector 并设置它所需的选择模式:

<ListView
            android:layout_
            android:layout_
            android:id="@+id/listView"
            android:choiceMode="singleChoice"
            android:listSelector="@drawable/custom_item_selector"/>

就是这样。它允许为“简单选定”和“按下选定”项目定义不同的视觉状态,例如使项目在按下时更亮。

【讨论】:

【参考方案10】:

要保持列表项(多选)突出显示,单击(激活)时,请按照以下步骤操作。

1.将背景设置为可绘制的列表项布局。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_
        android:layout_
        android:background="@drawable/list_item_selector">

        <ImageView
            android:id="@+id/icon"
            android:layout_
            android:layout_
            android:layout_marginLeft="4px"
            android:layout_marginRight="10px"
            android:layout_marginTop="4px"
            android:src="@mipmap/ic_launcher" >
        </ImageView>

        <TextView
            android:id="@+id/label"
            android:layout_
            android:layout_
            android:text="@+id/label"
            android:textSize="20px" >
        </TextView>
    </LinearLayout>

2。可绘制选择器

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

<item android:state_pressed="true"     android:drawable="@android:color/holo_red_light" />

<item android:state_activated="true" android:drawable="@android:color/holo_orange_dark" />

</selector>

3. Listview设置多选模式

getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

按下时

下图显示,当用户选择多个列表项时。

激活时

【讨论】:

【参考方案11】:

为了总结这篇文章并可能在将来帮助其他人,我建议答案:)

首先,我们需要创建res/drawable/list_item_background.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_activated="true"
        android:drawable="@color/list_item_activated" />
    <item
        android:drawable="@color/list_item_default" />
</selector>

当然,请指定您的可绘制资源。您还可以添加其他具有不同状态的&lt;item&gt; 元素,例如state_pressedstate_focused 等。

然后,我们应该将background 参数设置为我们的自定义列表项ViewGroup 元素(f.i. res/layout/list_item_layout.xml),如下所示:

android:background="@drawable/list_item_background"

下一步是修改我们的自定义Adapter 类。以下是以下代码片段:

public class CustomAdapter extends BaseAdapter 
    private List<Item> items;
    private LayoutInflater itemInflater;        
    private int selectedIndex; // add this

    public CustomAdapter(Context c, List<Item> items) 
        this.items = items;
        this.itemInflater = LayoutInflater.from(c);
        selectedIndex = -1; // add this
    

    /* add this */
    public void setSelectedIndex(int index) 
        selectedIndex = index;
        notifyDataSetChanged();
    

    /* other adapter's stuff */

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        if(convertView == null) 
            convertView = itemInflater.inflate(R.layout.list_item_layout, parent, false);
        

        // add this
        convertView.setActivated(selectedIndex != -1 && position == selectedIndex);

        /* do some stuff */

        return convertView;
    

最后,我们应该在AdapterView.OnItemClickListeneronItemClick(...)方法中调用setSelectedIndex(position)适配器的方法。

public class YourActivity extends Activity
        implements AdapterView.OnItemClickListener 

    private CustomAdapter mCustomAdapter;

    /* activity implementation */

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
        mCustomAdapter.setSelectedIndex(position);
    

现在,我们可以对适当的列表项突出显示感到满意了 :)

附:如果我们想在我们的列表中启用多项选择模式,我们只需将以下字符串放入保存listView 实例的活动类:

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

因此,我们将获得正确的多个项突出显示。

-- 希望这对任何人都有帮助:)

【讨论】:

以上是关于Android - 单击后保持 ListView 的项目突出显示的主要内容,如果未能解决你的问题,请参考以下文章

android listview数据刷新后保持原来的位置

在Android中通过ArrayAdapter在ListView中单击单个ImageView背景后如何更改它?

ListView OnClickItems 在 Android 中更改项目颜色

回到之前的片段(如 ListView)后,我可以保持 ScrollView 的位置吗?

android中给一个ListView添加长按事件后无法响应单击事件?

Android ListView 突出显示会导致奇怪的行为