ListView的子对象可点击confilct对象、ListView、confilct

2023-09-11 12:31:16 作者:我家的输入法知道我爱你

问一个问题,并花费15天的时间解决这个问题之后,我寻求帮助和解决方案在这里了。 在MainActivity我创建的Json下载任务,从HTTP下载数据,并与CustomListAdapter.class我填充ListView。 一切正常。 现在,在列表视图我有2个的TextView的,我想可以点击,其中之一是接受,即TextView的仅仅是在XML中它不是填充适配器或JSON。 接受应该是这样的文字更改为接受和变色,其工作和其他事物一样。但是当我点击第一个接受,在列表视图(位置0) 它改变了其他的ListView项目(位置4,9)。这就像我点击textviews上的位置4,9。 在第一个图像是点击接受,二靠是AFER一下了。

///

 公共类MainActivity延伸活动{

受保护的静态最终字符串变量= NULL;
公众的ArrayList< FeedItem> feedList;
公众的ListView feedListView;
私人进度进度;
 私人CustomListAdapter ADAP;
 私人LayoutInflater mInflater;


@覆盖
公共无效的onCreate(包savedInstanceState)
{
      super.onCreate(savedInstanceState);
      的setContentView(R.layout.activity_main);
      feedListView =(ListView控件)findViewById(R.id.custom_list);

      mInflater =(LayoutInflater)getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
      字符串URL =...;
      新DownloadFilesTask()执行(URL);

      getActionBar()的setIcon(R.drawable.angel)。
      进度=(进度)findViewById(R.id.progressBar);


       公共无效updateList(){
    ADAP =新CustomListAdapter(这一点,feedList);

           feedListView.setAdapter(ADAP);

            }


      公共类DownloadFilesTask扩展的AsyncTask<字符串,整数,太虚> {


      /// ....
 

CustomListAdapter.class

 公共类CustomListAdapter扩展了BaseAdapter
 {

私人的ArrayList< FeedItem>的ListData;
私人LayoutInflater layoutInflater;
私人语境mContext;
私人的ArrayList<字符串>数据;
受保护的ListView feedListView;
ArrayList的< HashMap的<字符串,字符串>>清单;

公共CustomListAdapter(上下文的背景下,ArrayList的< FeedItem>的ListData)
{
    this.listData =的ListData;
    layoutInflater =(LayoutInflater)上下文
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mContext =背景;
    数据=新的ArrayList<字符串>();
    的for(int i = 0;我小于10;我++){
        data.add(样本文字+将String.valueOf(一));
    }
}


@覆盖
公众诠释getCount将()
{
    返回listData.size();
}

@覆盖
公共对象的getItem(INT位置)
{
    返回listData.get(位置);
}

@覆盖
众长getItemId(INT位置)
{
    返回的位置;
}


公共查看getView(INT位置,查看convertView,父母的ViewGroup)
{
 最后ViewHolder持有人;
 查看排= convertView;
    如果((行== NULL)||(row.getTag()== NULL)){

     convertView = layoutInflater.inflate(R.layout.list_row_layout,NULL);
     持有人=新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(保持器);



    }
    其他
    {
        支架=(ViewHolder)convertView.getTag();

    }

   最后FeedItem newsItem =(FeedItem)listData.get(位置);
    holder.accept.setFocusable(真正的);

    holder.accept.setClickable(真正的);
    holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
    holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));

    holder.accept.setOnClickListener(新View.OnClickListener(){

        @覆盖
        公共无效的onClick(查看为arg0){


                    holder.accept.setText(Html.fromHtml(newsItem.getContent()));
        }
    });



    返回convertView;
}




静态类ViewHolder
{

    TextView的接受;
    TextView的headlineView;
    TextView的reportedDateView;
    ImageView的ImageView的;
    FeedItem newsItem;

}
 

解决方案 ListView展现数据

您需要了解的ListView回收机制的工作原理

如何ListView的回收机制的工作

使用一个模型类。假设你已经有了下面的

 公共类FeedItem {

字符串标题,内容;

公共字符串的getTitle(){
    返回称号;
}

公共无效的setTitle(字符串名称){
    this.title =称号;
}

公共字符串的getContent(){
    返回的内容;
}

公共无效setContent(字符串内容){
    this.content =内容;
}

}
 

getView

  holder.accept.setText(listData.get(位置).getContent());
holder.accept.setTag(位置);
holder.accept.setOnClickListener(mClickListener);
 

然后

 私人OnClickListener mClickListener =新OnClickListener(){
公共无效的onClick(视图v){
    INT POS =(整数)v.getTag();
    FeedItem newsItem =(FeedItem)listData.get(POS);
    newsItem.setContent(接受);
    CustomListadapter.this.notifyDataSetChanged();
}
};
 

Exaplanation:

您使用具有getter和setter一个模型类。

setTag 与位置的按钮。在你的onClick获得的标签,即位置并更改相应的内容。您可以通过调用 notifyDataSetChanged 适配器上刷新列表视图。

有关此人的利益的一个例子

 公共类MainActivity延伸活动{

   ArrayList的<持有>名单=新的ArrayList<持有>();
   ListView的LV;
   CustomListAdapter CUS;
    @覆盖
    保护无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
        LV =(ListView控件)findViewById(R.id.listView1);
        的for(int i = 0;我小于10;我++)
        {
            保持架H =新的持有人();
            h.setTitle(标题+ I);
            h.setContent(内容+ I);
            h.setColor(Color.BLACK);
            list.add(H);
        }
        CUS =新CustomListAdapter(这一点,清单);
        lv.setAdapter(CUS);
    }
}
 

Model类持有人

 公共类持有人{

    字符串标题,内容;
    INT的颜色;

    公众诠释的getColor(){
返回的颜色;

    公共无效setColor(INT颜色){
this.color =颜色;
    }

    公共字符串的getTitle(){
        返回称号;
    }

    公共无效的setTitle(字符串名称){
        this.title =称号;
    }

    公共字符串的getContent(){
        返回的内容;
    }

    公共无效setContent(字符串内容){
        this.content =内容;
    }

}
 

CustomListAdapter

 公共类CustomListAdapter扩展了BaseAdapter {

    LayoutInflater充气;
    ArrayList的<持有>清单;
    公共CustomListAdapter(MainActivity mainActivity,ArrayList的<持有>列表){
        充气= LayoutInflater.from(mainActivity);
        this.list =清单;
    }
    @覆盖
    公众诠释getCount将(){
        // TODO自动生成方法存根
        返回则为list.size();
    }
    @覆盖
    公共对象的getItem(INT位置){
        // TODO自动生成方法存根
        返回的位置;
    }
    @覆盖
    众长getItemId(INT位置){
        // TODO自动生成方法存根
        返回的位置;
    }
    公共查看getView(INT位置,查看convertView,ViewGroup中父){
        ViewHolder持有人;
        如果(convertView == NULL){
            convertView = inflater.inflate(R.layout.list_item,
                    父母,假);
            持有人=新ViewHolder();
            holder.tv =(TextView中)convertView.findViewById(R.id.textView1);
            holder.b =(按钮)convertView.findViewById(R.id.button1);
           convertView.setTag(保持器);
       } 其他 {
           支架=(ViewHolder)convertView.getTag();
       }
       保持架H = list.get(位置);
       holder.tv.setText(h.getTitle());
       holder.b.setText(h.getContent());
       holder.b.setTextColor(h.getColor());
       holder.b.setOnClickListener(mClickListener);
       holder.b.setTag(位置);
       返回convertView;
}
     私人OnClickListener mClickListener =新OnClickListener(){

            公共无效的onClick(视图v){
                INT POS =(整数)v.getTag();
                保持架H =(持有人)list.get(POS);
                h.setContent(接受);
                    h.setColor(Color.BLUE);
                CustomListAdapter.this.notifyDataSetChanged();

            }

            };
    静态类ViewHolder
    {
        TextView的电视;
        按钮B;
    }
}
 

list_item.xml

 < XML版本=1.0编码=UTF-8&GT?;
< RelativeLayout的的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>

    <按钮
        机器人:ID =@ + ID /按钮1
        机器人:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_alignParentRight =真
        机器人:layout_alignParentTop =真
        机器人:layout_marginRight =40dp
        机器人:文本=按钮/>

    <的TextView
        机器人:ID =@ + ID / textView1
        机器人:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_alignBottom =@ + ID /按钮1
        机器人:layout_alignParentLeft =真
        机器人:layout_marginLeft =22dp
        机器人:文本=TextView的/>

< / RelativeLayout的>
 

activity_main.xml

 < RelativeLayout的的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    的xmlns:工具=htt​​p://schemas.android.com/tool​​s
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:paddingBottom会=@扪/ activity_vertical_margin
    机器人:以下属性来=@扪/ activity_horizo​​ntal_margin
    机器人:paddingRight =@扪/ activity_horizo​​ntal_margin
    机器人:paddingTop =@扪/ activity_vertical_margin
    工具:上下文=MainActivity。>
    <的ListView
        机器人:ID =@ + ID / ListView1的
        机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT
        >
    < / ListView控件>

< / RelativeLayout的>
 

按钮在行1和5被点击,因此更改为接受,是蓝色的。

After asking a question and spending 15 days to solve this, i am looking for help and solution here again. In MainActivity i have created Json Downloading Task which is downloading data from http and with CustomListAdapter.class i populate the listview. Everything works. Now, in the listview i have 2 textview's which i want to be clickable, one of them is "Accept", that textview is just in xml it's not populated with Adapter or Json. "Accept" should work like this "Change the text to Accepted and change color" and its working like everything else. BUT when i click on first "Accept"(Position 0) in listview it changes other listview items (Position 4,9). It's like i clicked textviews on Position 4,9. On first image is before clicking the "Accept" and second on is afer clicking.

///

 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;

}

解决方案

You need to understand how listview recycle mechanism works

How ListView's recycling mechanism works

Use a Model Class. Assume you already have the below

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;
}

}

In getView

holder.accept.setText(listData.get(position).getContent()); 
holder.accept.setTag(position);
holder.accept.setOnClickListener(mClickListener);

Then

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 :

You use a model class which has getters and setters.

You setTag to the button with position. In onClick you get the tag ie position and change the content accordingly. You refresh listview by calling notifyDataSetChanged on the adapter.

For the benefit of others here's a example

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);
    }
}

Model class Holder

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>

Snap

Button at row 1 and 5 is clicked so it is changed to Accepted and is Blue.