我怎样才能改变背景色的特定行适当在ListView? (安卓)
我花了几天试图解决一个问题,我与在Android列表视图。我想实现用一个ListView单一选择列表框。所以,我想只有一个用predefined浅背景颜色,其余的与另一preselected色行。我的问题是,当我点击了一个特定的行是另一行被突出显示,没有一个我pressed。我加了一些消息日志发生了什么,但一切似乎很好地工作。这是我的code:
I have spent some days trying to solve a problem I have with ListViews on Android. I would like to implement a single selection list box using a ListView. So, I would like to have only one row with a predefined light background color and the rest with another preselected color. The problem I have is that when I click over a specific row is another row which is highlighted and not the one I pressed. I added several messages to Log what is happening but all seems to work fine. Here is my code:
public class TryListViewActivity extends Activity {
protected static final int NO_SELECTED_COLOR = 0xFF191919;
protected static final int SELECTED_COLOR = 0xFF3366CC;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView listView = new ListView(this);
ArrayList<String> list = new ArrayList<String>();
list.add("Option 1");
list.add("Option 2");
list.add("Option 3");
list.add("Option 4");
list.add("Option 5");
list.add("Option 6");
list.add("Option 7");
list.add("Option 8");
list.add("Option 9");
list.add("Option 10");
list.add("Option 11");
list.add("Option 12");
list.add("Option 13");
list.add("Option 14");
list.add("Option 15");
ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(
this,
R.layout.list_box_entry,
list
);
listView.setAdapter(listAdapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Set the listener
listView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.i(
"Log",
"[SingleSelectionListBox] Item clicked: position="
+ position + ";id=" + id
);
// First, set all rows to be unselected
int counter = parent.getCount();
Log.i(
"Log",
"[SingleSelectionListBox] "
+ counter + " items found inside the parent"
);
int children = parent.getChildCount();
Log.i(
"Log",
"[SingleSelectionListBox] "
+ children + " views found inside the parent"
);
for(int i=0;i<children;i++) {
Log.i(
"Log",
"[SingleSelectionListBox] Child "
+ i + " has message "
+ ((TextView)parent.getChildAt(i)).getText()
);
}
// Too inefficient but for now is OK
for(int i=0;i<children;i++)
parent.getChildAt(i)
.setBackgroundColor(NO_SELECTED_COLOR);
Log.i("Log",
"[SingleSelectionListBox] First visible position: "
+ parent.getFirstVisiblePosition()
);
// Set the background color
TextView textView = (TextView)(parent.getChildAt(
position-parent.getFirstVisiblePosition()));
textView.setBackgroundColor(SELECTED_COLOR);
Log.i(
"Log",
"[SingleSelectionListBox] Text inside the "
+ " View changing the color " + textView.getText()
);
}
}
);
setContentView(listView);
}
}
里面的资源(RES /布局)我插入了一个名为list_text_entry.xml包含以下内容的文件
Inside the resources (res/layout) I inserted a file called list_text_entry.xml with the following content
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:gravity="center"
android:textColor="#FFFFFF" android:padding="10dp" android:textSize="16sp">
</TextView>
例如,如果我点击在选项11项时,在ListView已经previously向下滚动,直到我看到的第一行是选项4,作为选定作为的选项7出现一行只有一个背着一个蓝色的背景。有人能解释发生了什么我这里来?我后下我扔日志的消息。
For example, If I click over the "Option 11" entry when the listView has been previously scrolled down until the first row I see is "Option 4", the "Option 7" row appears as selected being the only one carrying a blue color in the background. Can someone explain what happens here to me? I post below the messages I got throw the Log.
[SingleSelectionListBox] Item clicked: position=10;id=10
[SingleSelectionListBox] 15 items found inside the parent
[SingleSelectionListBox] 11 views found inside the parent
[SingleSelectionListBox] Child 0 has message Option 4
[SingleSelectionListBox] Child 1 has message Option 5
[SingleSelectionListBox] Child 2 has message Option 6
[SingleSelectionListBox] Child 3 has message Option 7
[SingleSelectionListBox] Child 4 has message Option 8
[SingleSelectionListBox] Child 5 has message Option 9
[SingleSelectionListBox] Child 6 has message Option 10
[SingleSelectionListBox] Child 7 has message Option 11
[SingleSelectionListBox] Child 8 has message Option 12
[SingleSelectionListBox] Child 9 has message Option 13
[SingleSelectionListBox] Child 10 has message Option 14
[SingleSelectionListBox] First visible position: 3
[SingleSelectionListBox] Text inside the View changing the color Option 11
据我可以猜对的ViewGroup内的所有儿童责令从上到下,甚至当我做到这一点,在code:
As I can guess all children inside the ViewGroup as ordered from top to bottom and even when I do this in the code:
TextView textView = (TextView)(parent.getChildAt(
position-parent.getFirstVisiblePosition()
));
textView.setBackgroundColor(SELECTED_COLOR);
会出现信息选项11
,但真的是选项7
选择。这是Android的一个bug?
Appears the message Option 11
but is really the option 7
selected. Is this a bug from Android?
感谢戴夫和ChristianB你的答案。我仍然不知道为什么Android的做吧,这样的问题仍然没有得到解决。然而,我发现了一个方式来获得我所需要创建一个自定义的适配器。我会给你code,以防有人可能会需要它。
Thanks Dave and ChristianB for your answers. I still do not know why Android does it, so the question is still unresolved. However, I found a way to get what I needed creating a custom Adapter. I will give you the code in case someone could need it.
public class CustomAdapter extends ArrayAdapter<String> {
protected static final int NO_SELECTED_COLOR = 0xFF191919;
protected static final int SELECTED_COLOR = 0xFF3366CC;
private ArrayList<String> items;
private LayoutInflater mInflater;
private int viewResourceId;
private int selectedPosition;
public CustomAdapter(Activity activity,int resourceId,
ArrayList<String> list) {
super(activity,resourceId,list);
// Sets the layout inflater
mInflater = (LayoutInflater)activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Set a copy of the layout to inflate
viewResourceId = resourceId;
// Set a copy of the list
items = list;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = (TextView)convertView;
if (tv == null) {
tv = (TextView)mInflater.inflate(viewResourceId, null);
}
tv.setText(items.get(position));
// Change the background color
if (position==selectedPosition) tv.setBackgroundColor(SELECTED_COLOR);
else tv.setBackgroundColor(NO_SELECTED_COLOR);
return tv;
}
public void setSelected(int position) {
selectedPosition = position;
}
}
所以,在ListView初始化我只是需要把这个监听器:
So, in the ListView initialization I just need to put this listener:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
((CustomAdapter)listAdapter).setSelected(position);
listView.invalidate();
}
});
这是不是因为我是从ArrayAdapter这是假设已经提供了所有数据的副本扩展的高效解决方案。因此,我现在用的比需要更多的内存和案例列表变得非常大,我可以有记忆的麻烦。所以,如果有人知道一个更好的解决方案,请邮寄!
This is not an efficient solution due to I am extending from ArrayAdapter which is suppose to have a copy of all data provided. Thus, I am using much more memory than needed and in case the list becomes very large I could have memory trouble. So, if someone knows a better solution, please post!