我有一个带有自定义单元格的列表视图,其中包含一个计时器,一个文本视图和一个开关。此列表视图中填充了ArrayList中的杜比数据。每当单击开关时,它总是会影响列表视图中的最后一项,而不是我打算单击的项目。

这是我自定义的timeTrackCellAdapter类

public class timeTrackCellAdapter extends ArrayAdapter {
    private final Activity activity;
    private final List timeParams;
    TimeView tView = null;
    View rowView;
    //Constructor
    public timeTrackCellAdapter(Activity activity, List objects){
        super(activity, R.layout.cell_layout, objects);
        this.activity = activity;
        this.timeParams = objects;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
         rowView = convertView;


        if(rowView == null)
        {
            // Get a new instance of the row layout view
            LayoutInflater inflater = activity.getLayoutInflater();
            rowView = inflater.inflate(R.layout.cell_layout, null);

            // Hold the view objects in an object,
            // so they don't need to be re-fetched
            tView = new TimeView();
            tView.timer = (Chronometer) rowView.findViewById(R.id.timeTracker);
            tView.jobText = (TextView) rowView.findViewById(R.id.secondaryRowText);
            tView.jobSwitch = (Switch) rowView.findViewById(R.id.timeSwitch);

            // Cache the view objects in the tag,
            // so they can be re-accessed later
            rowView.setTag(tView);
        } else {
            tView = (TimeView) rowView.getTag();
        }

        // Transfer the job/time from the data object
        // to the view objects
        final timeTrackCell currentTime = (timeTrackCell) timeParams.get(position);

        tView.timer.setBase(currentTime.getChronometerTime());
        tView.jobText.setText(currentTime.getJobString());
        tView.jobSwitch.setChecked(currentTime.getSwitchPosition());


        //OnClick for switch toggle
        tView.jobSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Boolean newCheck = tView.jobSwitch.isChecked();
                System.out.println(tView.jobText.getText());

                //If newCheck returns true, the switch is being turned on
                //If newCheck returns false, the switch is being turned off
                tView.timer.stop();
                System.out.println(newCheck);
                if(newCheck){

                    tView.jobSwitch.setChecked(true);
                    tView.jobText.setText(currentTime.getJobString());
                    tView.timer.setBase(currentTime.getChronometerTime());
                    tView.timer.start();


                }else{

                    tView.timer.stop();
                    tView.jobSwitch.setChecked(false);
                    tView.jobText.setText(currentTime.getJobString());
                    tView.timer.setBase(currentTime.getChronometerTime());

                }


            }
        });

        return rowView;

    }


    protected static class TimeView {
        protected Chronometer timer;
        protected TextView jobText;
        protected Switch jobSwitch;
    }
}


这是我的timeTrackCell类,其中包含适配器的所有获取和设置

public class timeTrackCell {
    private boolean switchPosition;
    private long chronometerTime;
    private String jobString;

    public timeTrackCell(boolean switchPosition, long chronometerTime, String jobString){
        this.switchPosition = switchPosition;
        this.chronometerTime = chronometerTime;
        this.jobString = jobString;
    }
    //sets
    public void setSwitchPosition(boolean switchPosition){
        this.switchPosition = switchPosition;
    }
    public void setChronometerTime(long chronometerTime){
        this.chronometerTime = chronometerTime;
    }
    public void setJobString(String jobString){
        this.jobString = jobString;
    }
    //gets
    public boolean getSwitchPosition(){
        return switchPosition;
    }
    public long getChronometerTime(){
        return chronometerTime;
    }
    public String getJobString(){
        return jobString;
    }


}


这是我的单元格的xml文件cell_layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minHeight="140px"
    >
    <!--140px Seems to be the right height for 7 cells per page-->
    <!-- Block for custom listview items -->
    <Chronometer
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/timeTracker"
        android:layout_gravity="left"
        android:textSize="25sp"
        android:paddingLeft="10px"
        android:layout_centerVertical="true">
    </Chronometer>

    <TextView
        android:id="@+id/secondaryRowText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/timeTracker"
        android:textSize="15sp"
        android:paddingLeft="10px"
        android:paddingTop="30px"
        >
    </TextView>

    <Switch
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/timeSwitch"
        android:gravity="right"
        android:layout_centerVertical="true"
        android:focusable="false"
        android:clickable="false"
        >
    </Switch>
</RelativeLayout>


这是创建列表视图并填充数据的java类。 timeKeeping.java

public class timeKeeping extends AppCompatActivity {
    public String empName = "Zach";
    private ListView lv;
    //tempchange
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /////
        //Button that shows who is logged in
        setContentView(R.layout.activity_time_keeping2);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setImageResource(R.drawable.ic_temp_profile_image);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String greetingString = "Welcome back, " + empName + "!";
                Snackbar.make(view, greetingString, Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        /////
        lv = (ListView) findViewById(R.id.timeList);
        //DUMBY DATA TO TEST WITH
        final List timeData = new ArrayList();
        Long testData = (long) 1000000;
        String tempJobTest = "test job ";
        for(int i = 0; i<5;i++){
            String nTempJobTest = tempJobTest + i;
            timeData.add(new timeTrackCell(false, testData, nTempJobTest));

        }


        lv.setAdapter(new timeTrackCellAdapter(this, timeData));

    }
}


我相当确定我的问题是timeTrackCellAdapter类中的onClick出现的,但是如果不是,则可以提供更多代码。任何帮助深表感谢!

最佳答案

您在每个tView中引用相同的onView变量。因为变量在类范围而不在方法范围内。如果创建5行,则第一行使用class变量,第二行也使用(从第一行删除引用),依此类推。

这就是为什么当您单击任何行时都在修改最后添加的行。

解决方法可能只是在方法内部创建一个局部变量。但是,我建议您使用RecyclerView,它是ListView的继承者。

无论如何,首先从类中删除变量:

public class timeTrackCellAdapter extends ArrayAdapter {
    private final Activity activity;
    private final List timeParams;
    View rowView;
    ....


然后,在方法内部创建它:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
     rowView = convertView;
     TimeView tView;

10-07 15:12