在提出问题并花了15天时间来解决这个问题后,我再次寻求帮助和解决方案。 在MainActivity中,我创建了Json下载任务,它从http下载数据,并使用CustomListAdapter.class填充listview。 一切正常。 现在,在列表视图中,我有2个textview,我希望它是可点击的,其中一个是"接受",textview只是在xml中,它没有填充适配器或Json 。 "接受"应该像这样工作"将文本更改为已接受并更改颜色"它的工作就像其他一切一样。但是当我点击第一个"在列表视图中接受"(位置0)时 它会更改其他列表视图项目(位置4,9)。就像我点击位置4,9上的文本视图一样。 在第一张图片上点击"接受"第二个是点击。
///
public class MainActivity extends Activity {
protected static final String TAG = null;
public ArrayList<FeedItem> feedList;
public ListView feedListView;
private ProgressBar progressbar;
private CustomListAdapter adap;
private LayoutInflater mInflater;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
feedListView= (ListView) findViewById(R.id.custom_list);
mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
String url = "...";
new DownloadFilesTask().execute(url);
getActionBar().setIcon(R.drawable.angel);
progressbar = (ProgressBar)findViewById(R.id.progressBar);
public void updateList() {
adap = new CustomListAdapter(this, feedList);
feedListView.setAdapter(adap);
}
public class DownloadFilesTask extends AsyncTask<String, Integer, Void> {
///....
CustomListAdapter.class
public class CustomListAdapter extends BaseAdapter
{
private ArrayList<FeedItem> listData;
private LayoutInflater layoutInflater;
private Context mContext;
private ArrayList<String> data;
protected ListView feedListView;
ArrayList<HashMap<String,String>> list;
public CustomListAdapter(Context context, ArrayList<FeedItem> listData)
{
this.listData = listData;
layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mContext = context;
data = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
data.add("Sample Text " + String.valueOf(i));
}
}
@Override
public int getCount()
{
return listData.size();
}
@Override
public Object getItem(int position)
{
return listData.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
public View getView( int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
View row=convertView;
if ((row == null) || (row.getTag()==null)) {
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder = new ViewHolder();
holder.headlineView = (TextView)convertView.findViewById(R.id.name);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.accept= (TextView) convertView.findViewById(R.id.acceptTV);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
final FeedItem newsItem = (FeedItem) listData.get(position);
holder.accept.setFocusable(true);
holder.accept.setClickable(true);
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
holder.accept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
holder.accept.setText(Html.fromHtml(newsItem.getContent()));
}
});
return convertView;
}
static class ViewHolder
{
TextView accept;
TextView headlineView;
TextView reportedDateView;
ImageView imageView;
FeedItem newsItem;
}
答案 0 :(得分:6)
您需要了解listview回收机制的工作原理
How ListView's recycling mechanism works
使用模型类。假设您已经拥有以下
public class FeedItem {
String title,content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
在getView
holder.accept.setText(listData.get(position).getContent());
holder.accept.setTag(position);
holder.accept.setOnClickListener(mClickListener);
然后
private OnClickListener mClickListener = new OnClickListener() {
public void onClick(View v) {
int pos = (Integer) v.getTag();
FeedItem newsItem = (FeedItem) listData.get(pos);
newsItem.setContent("Accepted");
CustomListadapter.this.notifyDataSetChanged();
}
};
Exaplanation:
您使用具有getter和setter的模型类。
您setTag
到有位置的按钮。在onClick中,您获得标记即位置并相应地更改内容。您可以通过调用适配器上的notifyDataSetChanged
来刷新列表视图。
为了别人的利益,这是一个例子
public class MainActivity extends Activity {
ArrayList<Holder> list = new ArrayList<Holder>();
ListView lv;
CustomListAdapter cus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.listView1);
for(int i=0;i<10;i++)
{
Holder h = new Holder();
h.setTitle("Title"+i);
h.setContent("Content"+i);
h.setColor(Color.BLACK);
list.add(h);
}
cus = new CustomListAdapter(this,list);
lv.setAdapter(cus);
}
}
模型类持有人
public class Holder {
String title,content;
int color;
public int getColor() {
return color;
public void setColor(int color) {
this.color = color;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
CustomListAdapter
public class CustomListAdapter extends BaseAdapter{
LayoutInflater inflater;
ArrayList<Holder> list;
public CustomListAdapter(MainActivity mainActivity, ArrayList<Holder> list) {
inflater = LayoutInflater.from(mainActivity);
this.list =list;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item,
parent, false);
holder = new ViewHolder();
holder.tv = (TextView) convertView.findViewById(R.id.textView1);
holder.b = (Button) convertView.findViewById(R.id.button1);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Holder h = list.get(position);
holder.tv.setText(h.getTitle());
holder.b.setText(h.getContent());
holder.b.setTextColor(h.getColor());
holder.b.setOnClickListener(mClickListener);
holder.b.setTag(position);
return convertView;
}
private OnClickListener mClickListener = new OnClickListener() {
public void onClick(View v) {
int pos = (Integer) v.getTag();
Holder h = (Holder) list.get(pos);
h.setContent("Accepted");
h.setColor(Color.BLUE);
CustomListAdapter.this.notifyDataSetChanged();
}
};
static class ViewHolder
{
TextView tv;
Button b;
}
}
list_item.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="match_parent" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="40dp"
android:text="Button" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/button1"
android:layout_alignParentLeft="true"
android:layout_marginLeft="22dp"
android:text="TextView" />
</RelativeLayout>
activity_main.xml中
<RelativeLayout 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=".MainActivity" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</ListView>
</RelativeLayout>
对齐
单击第1行和第5行的按钮,使其更改为“已接受”并为蓝色。
答案 1 :(得分:1)
getView(...){
if ((row == null) || (row.getTag()==null)) {
// some code
}else{
// some code
}
holder.accept.setTag(position);
// some more code
if(newsItem.isSelected()){
holder.accept.setText("accepted");
}else{
holder.accept.setText("accept");
}
//handling click
holder.accept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
int position = (Integer)arg0.getTag();
// change backing dataset here instead.
FeedItem m = listData.get(position);
// declare a boolean 'selected' in FeedItem
// toggle the previous selection
m.setSelected(! m.isSelected());
// call notifydatasetChanged
CustomListAdapter.this.notifyDataSetChanged();
}
});
// some more code
}
class FeedItem{
// some data member
boolean selected = false;
public boolean isSelected(){
return selected;
}
public void setSelected(boolean status){
selected = status;
}
}
答案 2 :(得分:0)
您的问题肯定来自于重复使用时不重置视图状态的事实。 ListView重用视图以实现更好的内存管理。因此,根据项目的选定状态调整您的getView()
以调整文本和颜色。我没有看到你将它保存在代码中的哪个位置,所以我不能给你一个有效的例子。
像
这样的东西 if (newsItem.selected)
holder.accept.setText("accepted");
else
holder.accept.setText("accept");