在列表视图中单击项目时出错位置

时间:2014-02-24 15:51:51

标签: android listview

预条件: -

  • 我的listview中有一个复选框和两个textview。
  • 我的arraylist的大小为2,因此正在创建两行。

功能性: - 如果选中该复选框,相应的文本视图将被启用,因此它们将变为可点击。

这个逻辑工作正常,但问题是如果我检查第0个位置复选框,第1个位置的文本视图会启用

另一种情况是即使选中的第一个复选框仅启用了第一个textview,在textview的监听器上我调用日期选择器和设置日期,但日期设置为第二个textview

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    ViewHolder viewHolder = null;
    if (rowView == null) {
      LayoutInflater inflater = context.getLayoutInflater();
      rowView = inflater.inflate(R.layout.rowlayout, null);
      viewHolder = new ViewHolder();
      viewHolder.textview1 = (TextView) rowView.findViewById(R.id.TextView11);
      viewHolder.textview2 = (TextView) rowView.findViewById(R.id.TextView12);
      viewHolder.checkbox = (CheckBox) rowView.findViewById(R.id.checkBox1);
      rowView.setTag(viewHolder);
    }
    else{
        holder = (ViewHolder) rowView.getTag();
    }
    viewHolder.textview1.setEnabled(false) //default textview is false
    viewHolder.textview2.setEnabled(false) //default textview is false

    viewHolder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener()
    {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
        {
            if ( isChecked )
            {
                holder.textview1.setEnabled(true);
                holder.textview2.setEnabled(true);
            }
            else if ( !isChecked )
            {
                holder.textview1.setEnabled(false);
                holder.textview2.setEnabled(false);
            }

    }
});

// Textview's listeners here- showing toast in it. 
//When checking first checkbox, second position textviews are getting enabled

    return rowView;
  }

这是我完整的custyom listview类: -

    package com.list.filter.datefilter;

import java.util.ArrayList;
import java.util.Date;

import android.app.Activity;
import android.app.FragmentManager;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;

import com.exzeo.jarvis.ApplicationController;
import com.exzeo.jarvis.R;
import com.exzeo.jarvis.ui.DatePickerFragment;
import com.exzeo.jarvis.ui.DatePickerFragment.onDateSet;
import com.exzeo.jarvis.workards.list.filter.datefilter.model.AdvanceDateFilter;

public class AdvanceDateFilterList extends ListView{
    private boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
    private CustomFilterAdapter dataAdapter = null;
    private Context context;
    private OnCheckChangedClickListener changedClickListener;

    public AdvanceDateFilterList(Context context, ArrayList<AdvanceDateFilter> filterArray) {
        super(context);
        this.context=context;
        displayListView((Activity) context, filterArray);
    }

    public void setOnCheckChangedClickListener(OnCheckChangedClickListener listener) {
        this.changedClickListener = listener;
    }

    public interface OnCheckChangedClickListener {
        public void onClick(ArrayList<AdvanceDateFilter> filter/*, int position*/); 
        //      public void onDateChange(AdvanceDateFilter filter, int position);
    }

    @Override
    public void setId(int id) {
        super.setId(id);
    }

    @Override
    public void setLayoutParams(android.view.ViewGroup.LayoutParams params) {

        //TODO:set height dynamic
        if (dataAdapter == null) {
            // pre-condition
            return;
        }

        int width = ApplicationController.getInstance().getDeviceWidth();
        int height = ApplicationController.getInstance().getDeviceHeight();

        if(height<width)
            height=width;

        int totalHeight = 0;
        for (int i = 0; i < dataAdapter.getCount(); i++) {
            totalHeight +=height/10;
        }
        if(totalHeight>(height/4))
            totalHeight=height/4;
        params.height = totalHeight + (this.getDividerHeight() * (dataAdapter.getCount() - 1));
        /*
        if(tabletSize){

        for (int i = 0; i < dataAdapter.getCount(); i++) {
            totalHeight +=height/10;
        }
        if(totalHeight>(height/4))
            totalHeight=height/4;
        params.height = totalHeight + (this.getDividerHeight() * (dataAdapter.getCount() - 1));

        }else{
            for (int i = 0; i < dataAdapter.getCount(); i++) {
                if(tabletSize)
                totalHeight +=height/25;
                else
                    totalHeight +=height/18;
            }
            if(totalHeight>(height/3))
                totalHeight=height/3;
            params.height = totalHeight + (this.getDividerHeight() * (dataAdapter.getCount() - 1));


        }*/
        params.width = -1;
//      params.height = -1;
        super.setLayoutParams(params);
    }
    private void displayListView(Activity activity, ArrayList<AdvanceDateFilter> filterArray) {

        dataAdapter = new CustomFilterAdapter(activity, context, R.layout.advance_date_filter_row, filterArray);
        setAdapter(dataAdapter);

    }

    private class CustomFilterAdapter extends ArrayAdapter<AdvanceDateFilter> {

        private ArrayList<AdvanceDateFilter> filterList;
        private ViewHolder holder = null;
        private Activity activity;
        private int dateCheck = -1;
        FragmentManager fragmentManager;
        DatePickerFragment newFragment;
        public CustomFilterAdapter(Activity activity, Context context, int textViewResourceId,  ArrayList<AdvanceDateFilter> filterList) {
            super(context, textViewResourceId, filterList);
            this.filterList = new ArrayList<AdvanceDateFilter>();
            this.filterList.addAll(filterList);
            this.activity=activity;
            fragmentManager =((Activity) context).getFragmentManager();
            newFragment = new DatePickerFragment(context);
        }

        private class ViewHolder {
            CheckBox datefiltercheckbox;
            TextView fromDate, toDate;
        }

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

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {

            if (convertView == null) {
                LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = vi.inflate(R.layout.advance_date_filter_row, null);
                holder = new ViewHolder();

                holder.fromDate = (TextView) convertView.findViewById(R.id.fromdate);
                holder.toDate = (TextView) convertView.findViewById(R.id.todate);
                holder.datefiltercheckbox = (CheckBox) convertView.findViewById(R.id.datefiltercheckbox);
                convertView.setTag(holder);

            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            holder.fromDate.setEnabled(false);
            holder.toDate.setEnabled(false);

            holder.fromDate.setText("From: "+filterList.get(position).getFromDate());
            holder.toDate.setText("To: "+filterList.get(position).getToDate());         

            if(filterList.get(position).getTypeOfDate().equals("WORKKARDLOSSDATEFILTER"))
                holder.datefiltercheckbox.setText("Loss Date");
            else if (filterList.get(position).getTypeOfDate().equals("WORKKARDREPORTEDDATEFILTER")) {
                holder.datefiltercheckbox.setText("Reported Date");
            }

            int checkBoxPaddingLeft = (int) (getResources().getDimension(R.dimen.rightDrawerFilterCheckbox)/getResources().getDisplayMetrics().density);
            holder.datefiltercheckbox.setPadding(checkBoxPaddingLeft, 0, 0, 0);

            holder.datefiltercheckbox.setOnCheckedChangeListener(null);
            holder.datefiltercheckbox.setChecked(filterList.get(position).isSelected());
            holder.datefiltercheckbox.setTag(filterList.get(position));

            if(filterList.get(position).isSelected()){
                holder.fromDate.setEnabled(true);
                holder.toDate.setEnabled(true);
                if(dateCheck == 0){
                    holder.fromDate.setText("From: "+filterList.get(position).getFromDate());
                }
                else{
                    holder.toDate.setText("To: "+filterList.get(position).getToDate());
                }

            }
            else{
                holder.fromDate.setEnabled(false);
                holder.toDate.setEnabled(false);
                if(dateCheck == 0){
                    holder.fromDate.setText("From: "+filterList.get(position).getFromDate());
                }
                else{
                    holder.toDate.setText("To: "+filterList.get(position).getToDate());
                }
            }
            newFragment.setDateListener(new onDateSet() {

                @Override
                public void onDate(int year, int monthOfYear, int dayOfMonth) {

                    if(dateCheck == 0){
                        filterList.get(position).setFromDate(dayOfMonth+"/"+monthOfYear+"/"+year);
                        holder.fromDate.setText("From: "+filterList.get(position).getFromDate());

                    }
                    else{
                        filterList.get(position).setToDate(dayOfMonth+"/"+monthOfYear+"/"+year);
                        holder.toDate.setText("To: "+filterList.get(position).getToDate());
                    }

                    //              changedClickListener.onDateChange(filterList.get(position), position);
                    changedClickListener.onClick(filterList);
                }
            });


            holder.datefiltercheckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if(isChecked){
                        holder.fromDate.setEnabled(true);
                        holder.toDate.setEnabled(true);
                    }
                    else{
                        holder.fromDate.setEnabled(false);
                        holder.toDate.setEnabled(false);
                    }
                    notifyDataSetChanged();
                    filterList.get(position).setSelected(isChecked);

                    changedClickListener.onClick(filterList);

                }
            });

            holder.fromDate.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    dateCheck = 0;
                    newFragment.show(fragmentManager, "datePicker");
                    newFragment.setDateRange(new Date(filterList.get(position).getFromDate()).getTime(), 
                            new Date(filterList.get(position).getToDate()).getTime());


                }
            });

            holder.toDate.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    dateCheck = 1;
                    newFragment.show(fragmentManager, "datePicker");
                    newFragment.setDateRange(new Date(filterList.get(position).getFromDate()).getTime(), 
                            new Date(filterList.get(position).getToDate()).getTime());
                }
            });

            return convertView;
        }

    }
}

4 个答案:

答案 0 :(得分:0)

看看这个关于在列表项中添加多个可点击视图的优秀教程。 您的问题的主要罪魁祸首可能是listview回收。看看这个:

http://cyrilmottier.com/2011/11/23/listview-tips-tricks-4-add-several-clickable-areas/

答案 1 :(得分:0)

正如你在答案中所说,由于充气操作会大量使用CPU,因此视图是由android回收,所以这样做,android尝试减少充气操作的数量。 我真的不认为假设rowView为null是一个好主意。我认为您必须要做的是,在onChange侦听器中,检查包含您要更改的文本的rowView是否与它应该相同,否则您不需要更改该文本,因为该视图已被删除再循环,不再可见。当适配器再次需要视图时,将正确设置文本视图。

答案 2 :(得分:0)

我注意到你在界面onCheckedChanged()上设置了两个复选框,你可以使用一个参数来查看哪一个被按下了:

viewHolder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
    {
        if ( isChecked )
        {  
          switch(buttonView.getId()){
           case R.id.checkbox1:
           holder.textview1.setEnabled(true);                 
           break;
           case R.id.checkbox2:
           holder.textview2.setEnabled(true);                
           break;
          }
        }
        else if ( !isChecked )
        {
            holder.textview1.setEnabled(false);
            holder.textview2.setEnabled(false);
        }
}
});

答案 3 :(得分:-1)

我已经遇到了这个问题。我是因为视图被系统或其他东西重用。

只需强制if (rowView == null)true。我的意思是改变

if (rowView == null) {
  LayoutInflater inflater = context.getLayoutInflater();
  rowView = inflater.inflate(R.layout.rowlayout, null);
  viewHolder = new ViewHolder();
  viewHolder.textview1 = (TextView) rowView.findViewById(R.id.TextView11);
  viewHolder.textview2 = (TextView) rowView.findViewById(R.id.TextView12);
  viewHolder.checkbox = (CheckBox) rowView.findViewById(R.id.checkBox1);
  rowView.setTag(viewHolder);
}
else{
    holder = (ViewHolder) rowView.getTag();
}

  LayoutInflater inflater = context.getLayoutInflater();
  rowView = inflater.inflate(R.layout.rowlayout, null);
  viewHolder = new ViewHolder();
  viewHolder.textview1 = (TextView) rowView.findViewById(R.id.TextView11);
  viewHolder.textview2 = (TextView) rowView.findViewById(R.id.TextView12);
  viewHolder.checkbox = (CheckBox) rowView.findViewById(R.id.checkBox1);
  rowView.setTag(viewHolder);