我有一个带有自定义单元格的列表视图,其中包含一个计时器,一个文本视图和一个开关。此列表视图中填充了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;