8

我想在用户单击它时更改列表视图项的背景。有点像Honeycomb 设置页面(虽然我不只处理设置,所以我没有使用 PreferenceActivity)我有这个功能通过资源状态选择器状态选择器工作,除了单击列表视图菜单更改线性的情况列表视图右侧的布局(一种分屏视图)。我猜 listview 失去焦点所以 state_pressed 不再是真的。

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

在选择另一个列表视图项目之前保持该列表视图项目颜色的任何提示?谢谢!

编辑:

我能够在 setOnItemClickListener 中更改背景

view.setBackgroundResource(R.color.red); 

我一次只需要选择一个,因此当单击其他列表项时,我尝试lv.invalidate()lv.getChildAt(0).invalidate()但均未成功,第二个导致空指针异常。有什么想法可以恢复颜色吗?

4

10 回答 10

9

当您从单元格中松开手指时,它不再记录为按下状态。您要做的实际上是在用户选择 is 时更改单个行的背景。这意味着实现onItemClick或 onItemTouch 并标记适配器以使用新背景重绘行。如果您已经在使用自定义列表适配器,您可以在 getView() 方法中实现对布尔值的检查。您还需要跟踪哪些行被“选中”,哪些未被选中。

伪代码:

   public View getView(int pos, View convertView, ViewGroup parent) {
      if(isChecked[pos]) //set background to checked color
   }
于 2011-04-15T20:40:32.053 回答
4

希望这有帮助,

1.- 为焦点项目创建一个形状文件:\drawable\list_selector_focused.xml

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

    <gradient android:angle="90" android:startColor="#f5c98c" android:endColor="#f7ddb8"/> 

</shape>

2.- 为按下的项目创建一个形状文件:\drawable\list_selector_pressed.xml

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

    <gradient android:angle="90" android:startColor="#fb9d23" android:endColor="#ffc579" />

</shape>

3.- 创建列表选择器文件:\drawable\list_selector.xml

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

    <item android:state_pressed="true" android:drawable="@drawable/list_selector_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/list_selector_focused" />
    <item android:drawable="@drawable/list_selector_focused" />

</selector>

4.- 将此属性添加到布局文件中的 ListView 中:

 android:choiceMode="singleChoice"
 android:listSelector="@drawable/list_selector"

您可以使用颜色而不是渐变形状,

于 2013-03-17T22:02:20.307 回答
3

这是sgarman想法的实现:

    package com.mypackage;

import java.util.Vector;

import com.myapp.R;
import com.myapp.data.Address;

import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class AddressesListAdapter extends BaseAdapter{
    protected Context context;
    protected LayoutInflater mInflater;
    protected int itemResourceId;
    protected Vector<Address> contentItems = new Vector<Address>();
    protected Vector<Boolean> selectedStates;
    private static final String TAG = "myapp";

    public AddressesListAdapter(Context context, Vector<Address> contentItems) {
        this.context = context;
        this.contentItems = contentItems;
        mInflater = LayoutInflater.from(context);
        itemResourceId = R.layout.address_list_item;
        selectedStates = new Vector<Boolean>();
        //initial fill
        clearSelectedState();
    }

    @Override
    public int getCount() {
        return contentItems.size();
    }

    @Override
    public Object getItem(int position) {
        return contentItems.get(position);
    }

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(itemResourceId, null);

            holder = new ViewHolder();
            holder.addressName = (TextView) convertView.findViewById(R.id.addressName);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Address address = (Address) contentItems.get(position);
        holder.addressName.setText(address.getAddressName());
        holder.addressName.setOnClickListener(new SetFocusListener(position));

        //restore saved position from saving vector
        if (selectedStates.get(position)) holder.addressName.setBackgroundColor(Color.BLUE);
        else holder.addressName.setBackgroundColor(Color.TRANSPARENT);

        return convertView;
    }

    private void clearSelectedState () {
        selectedStates.clear();  
        for (int i = 0 ; i <= contentItems.size(); i++) {
            selectedStates.add(new Boolean(false));
        } 
    }

    private class SetFocusListener implements View.OnClickListener {
        private int position;

        public SetFocusListener(int position) {
            this.position = position;
        }

        @Override
        public void onClick(View v) {
            //clear selected state vector
            clearSelectedState();
            //set selected position
            selectedStates.set(position, new Boolean(true));
            //refresh adapter to redraw focus
            notifyDataSetChanged();
        }
    }

    static class ViewHolder {
          TextView addressName;
    }
}

唯一担心的是为每次 getView() 迭代设置新的侦听器可能会很昂贵

于 2011-09-23T09:17:05.813 回答
3

最好使用检查的 android 状态来解决此问题。

有人提到使用 android:background="?android:attr/activatedBackgroundIndicator"。

这只是指向android源代码的frameworks/base/core/res/res/drawable中的activated_background_*资源之一。例如activated_background_holo_dark.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
  <item android:state_activated="true" android:drawable="@android:drawable/list_activated_holo" />
  <item android:drawable="@color/transparent" /> 
</selector>

所以本质上你想使用 state_activated 来表示用户何时按下按钮以及当它处于选中状态(即处于持久选择状态)状态时。请注意,仅在 Honeycomb 之后才引入了 activate ,如果您针对的是较旧的设备,则需要依赖 state_checked (更多详细信息请点击此处)。

现在如果你想将一个项目设置为选中,你需要调用listView.setItemChecked(position, true). 您可能希望将android:choiceModeListView 上的属性设置为适当的值(例如,如果您希望一次只选择一件事singleChoice)。您不需要无效,对 setItemChecked 的调用将触发重新布局,该重新布局将更新视图。

如果您允许对 ListView 中的项目重新排序,也要小心,因为当前选中的项目需要更新。如果您使用稳定的 ID,这将自动处理。

要查看实际操作示例,请查看培训系列中的 NavigationDrawer 示例代码:http: //developer.android.com/training/implementing-navigation/nav-drawer.html

于 2013-08-31T14:07:22.713 回答
2

默认情况下,当您使用触摸界面时,“已选择”与“已单击”不同——当我开始 Android 开发时,这让我非常头疼。

要支持通过触摸导航的用户和使用滚轮/轨迹球的用户,您可能需要使用setSelection,并在AdapterView.OnItemSelectedListener实现中进行操作(使用setOnItemSelectedListener设置)。

另一个问题是如果最后一个事件是触摸事件,setSelection不会突出显示项目。

我建议您为列表项创建一个自定义视图,并在其中处理突出显示。

希望这可以帮助,

菲尔·莱洛

于 2011-04-15T21:33:46.940 回答
0

好的,所以我尝试了上面的解决方案,上面写着“这是 sgarman 想法的实现:”这仅在 SetFocusListener 是 OnTouchListner 时才有效。否则 onClick 方法会消耗点击。我必须将此解决方案与列表项上的 OnItemClick 侦听器配对,以使列表实际显示突出显示的项。

于 2014-10-18T17:26:34.907 回答
0

我用 android:state_activated="true"而不是state_selected. 它就像一个魅力!

于 2015-01-20T12:53:28.387 回答
0

如果你在整个活动中保持你的 listView ,你可以mListView.isItemChecked(position)getView()方法中做一个。他们根据结果设置背景颜色。

于 2015-02-27T20:21:41.710 回答
-2

你试过android:state_selected="true"吗?

于 2011-04-15T20:39:26.170 回答
-2

尝试

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

;)

于 2013-03-30T19:09:31.740 回答