我有一个自定义单元格的列表视图,其中包含计时器,文本视图和开关。此列表视图使用ArrayList中的dumby数据填充。无论何时单击一个开关,它总是会影响列表视图中的最后一项而不是我想要点击的那一项。
这是我的自定义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>
这是创建listview并填充数据的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,但如果不是,我可以提供更多代码。非常感谢任何帮助!!
答案 0 :(得分:2)
您在每个tView
中引用了同一个onView
变量。因为变量在类范围内而不在方法范围内。如果创建5行,则第一行使用类变量,第二行使用(从第一行中删除引用),依此类推。
这就是为什么当你点击任何一行时,你正在修改最后添加的行。
解决方案可能只是在方法中创建一个局部变量。但是,我建议你使用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;
答案 1 :(得分:0)
致电notifyDataSetChanged();
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());
}
//call this method
notifyDataSetChanged();
}
答案 2 :(得分:-2)
@Override
public View getView(int position, View convertView, ViewGroup parent
{
//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());
}
}
});
}
在getView方法中设置监听器可能是您应用程序可能遇到的最大错误。这个方法被隐式调用,即使在任何项目发生单个更新时,您可能会创建一个MEMORY-BLACKHOLE,因为每次滚动或进行更新时都会调用getView(int,View,ViewGroup),因此您可能已经声明了在这种情况下,你的听众一千次。尝试一些其他代码片段来设置你的监听器,这不是一个解决方案,而是一个严格的建议