java 更改 ListView 背景 - 奇怪的行为
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4583349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Change ListView background - strange behaviour
提问by Beasly
I have a problem with changing the background of a view in a ListView.
我在更改 ListView 中的视图背景时遇到问题。
What I need:
Change the background image of a row onClick()
我需要什么:
更改一行 onClick() 的背景图像
What actually happens:
The background gets changed (selected) after pressing e.g. the first entry. But after scrolling down the 8th entry is selected too.
Scroll back to the top the first isn't selected anymore. The second entry is selected now.
Continue scrolling and it continues jumping...
实际发生的情况:
例如按下第一个条目后,背景会改变(选择)。但是向下滚动后,第 8 个条目也被选中。滚动回顶部,第一个不再被选中。现在选择了第二个条目。继续滚动,它继续跳跃......
What i'm dong in the Code:
I have channels, and onClick() I toggle an attribute of channel boolean selectedand then I change the background.
I'm doing this onlyonClick() thats why I don't get why it's actuelly happening on other entries too.
One thing I notices is: It seems to be only the "drawing"-part because the item which get selected "by it self" has still the selectedvalue on false
我在代码中的内容:
我有频道,并且 onClick() 我切换了 channel boolean selected的属性,
然后我更改了背景。我只在onClick() 上这样做,这就是为什么我不明白为什么它也发生在其他条目上。我注意到的一件事是:它似乎只是“绘图”部分,因为“自己”选择的项目仍然具有false的选定值
I think it seems to have something to do with the reuse of the views in the custom ListAdapters getView(...)
我认为这似乎与自定义 ListAdapters getView(...) 中视图的重用有关
Code of onClick() in ListActivity:
ListActivity中onClick()的代码:
@Override
protected ViewHolder createHolder(View v) {
// createHolder will be called only as long, as the ListView is not
// filled
TextView title = (TextView) v
.findViewById(R.id.tv_title_channel_list_adapter);
TextView content = (TextView) v
.findViewById(R.id.tv_content_channel_list_adapter);
ImageView icon = (ImageView) v
.findViewById(R.id.icon_channel_list_adapter);
if (title == null || content == null || icon == null) {
Log.e("ERROR on findViewById",
"Couldn't find Title, Content or Icon");
}
ViewHolder mvh = new MyViewHolder(title, content, icon);
// We make the views become clickable
// so, it is not necessary to use the android:clickable attribute in
// XML
v.setOnClickListener(new ChannelListAdapter.OnClickListener(mvh) {
public void onClick(View v, ViewHolder viewHolder) {
// we toggle the enabled state and also switch the the
// background
MyViewHolder mvh = (MyViewHolder) viewHolder;
Channel ch = (Channel) mvh.data;
ch.setSelected(!ch.getSelected()); // toggle
if (ch.getSelected()) {
v.setBackgroundResource(R.drawable.row_blue_selected);
} else {
v.setBackgroundResource(R.drawable.row_blue);
}
// TESTING
Log.d("onClick() Channel", "onClick() Channel: "
+ ch.getTitle() + " selected: " + ch.getSelected());
}
});
return mvh;
}
Code of getView(...):
getView(...) 的代码:
@Override
public View getView(int position, View view, ViewGroup parent) {
ViewHolder holder;
// When view is not null, we can reuse it directly, there is no need
// to reinflate it.
// We only inflate a new View when the view supplied by ListView is
// null.
if (view == null) {
view = mInflater.inflate(mViewId, null);
// call own implementation
holder = createHolder(view);
// TEST
// we set the holder as tag
view.setTag(holder);
} else {
// get holder back...much faster than inflate
holder = (ViewHolder) view.getTag();
}
// we must update the object's reference
holder.data = getItem(position);
// <EDIT SOLUTION>
if(getItem(position).get_id() == channelList.get(position).get_id()){
if(getItem(position).getSelected())
{
view.setBackgroundResource(R.drawable.row_blue_selected);
}
else{
view.setBackgroundResource(R.drawable.row_blue);
}
}
// </EDIT SOLUTION>
// call the own implementation
bindHolder(holder);
return view;
}
I really would appreciate any idea how to solve this! :)
我真的很感激任何想法如何解决这个问题!:)
If more information is needed please tell me.
如果需要更多信息,请告诉我。
Thanks in advance!
提前致谢!
回答by Javanator
Let me show you the code that I use for every ListView
and properly controlling the click event for changing the background and doing anything further
让我向您展示我用于每个ListView
和正确控制单击事件以更改背景和执行任何进一步操作的代码
public class Offices extends Activity {
private ListView listView;
/* selectedListItem will contain the number of items to be selected.
* Your list item OnOlickListener will simply change this variable
* to the position of the clicked item. The Adapter will do the rest
* because you need to refresh the ListView.
*/
private int selectedListItem = -1;
private Handler mHandler = new Handler();
private Vector<String> data;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.officeslayout);
data = new Vector<String>();
// Add data as per your requirement
data.add("one");
data.add("two");
data.add("three");
data.add("four");
data.add("Five");
data.add("Six");
data.add("Seven");
data.add("Eight");
data.add("Nine");
data.add("Ten");
listView = (ListView)findViewById(R.id.ListView01);
listView.setDivider(null);
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
selectedListItem = position;
((EfficientAdapter)listView.getAdapter()).notifyDataSetChanged();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// call any new activity here or do any thing you want here
}
}, 200L);
}
});
listView.setAdapter(new EfficientAdapter(getApplicationContext()));
}
private class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null || convertView.getTag() == null) {
convertView = mInflater.inflate(R.layout.officeslistitemlayout, null);
holder = new ViewHolder();
holder.backgroundView = (ImageView) convertView
.findViewById(R.id.OfficesBackground);
holder.officesTitle = (TextView) convertView
.findViewById(R.id.OfficesName);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if(position == selectedListItem) {
holder.backgroundView.setBackgroundResource(R.drawable.and_gray_bg_listing_selected);
} else {
holder.backgroundView.setBackgroundResource(R.drawable.and_gray_bg_listing);
}
holder.officesTitle.setText(data.get(position));
return convertView;
}
}
static class ViewHolder {
TextView officesTitle;
ImageView backgroundView;
}
}
officeslistitemlayout.xml file will be like following add drawable and design it according to you put the following code in RelativeLayout
officelistitemlayout.xml 文件会像下面一样添加drawable并根据你设计它把下面的代码放在RelativeLayout中
<ImageView android:id="@+id/OfficesBackground" android:layout_width="fill_parent"
android:layout_height="45dip"
android:layout_alignParentTop="true"
android:background="@drawable/and_gray_bg_listing"
android:scaleType="fitXY"
></ImageView>
<TextView android:id="@+id/OfficesName" android:layout_width="wrap_content"
android:text="Offices Name"
android:textColor="#000000" android:textStyle="bold"
android:layout_height="wrap_content"
android:layout_centerVertical="true" android:layout_marginLeft="5dip"
></TextView>
Hope it will help :)
希望它会有所帮助:)