我有一个带有适配器的自定义 ListView,它允许用户查看对数据库的条目。ListView 的一切工作正常,直到我尝试单击列表中除第一个条目之外的任何条目。单击时,条目应加载到编辑器中。出于某种原因,无论单击哪个条目,列表中的第一个条目都会加载到编辑器中。这是 ListView 的活动代码:
public class MainActivity extends Activity {
public static final String KEY_ID = "listviewId";
public static final String KEY_SHORT = "projectShortTextView";
public static final String KEY_FULL = "projectFullTextView";
public static final String KEY_HOURS = "listviewHoursTV";
public static final String KEY_PROID = "projectIdTV";
private SQLiteDatabase db;
private TimesheetDatabaseHelper dbHelp = new TimesheetDatabaseHelper(this);
/** Gets a valid calendar instance for use */
final Calendar c = Calendar.getInstance();
/** Strings for formatting the date's for use */
public String dateViewForm = "EEE MM/dd/yyyy";
public String dateForm = "MM/dd/yyyy";
public String timeForm = "HH:mm";
/** Strings to store formated calendar outputs */
public String date, dateView;
/** Prepares buttons and EditText for use */
public Button minusButton, plusButton, quickAdd;
public EditText dateEditText;
public ListView list;
TimestampAdapter adapter;
SimpleDateFormat formDateView = new SimpleDateFormat(dateViewForm, Locale.US);
SimpleDateFormat formDate = new SimpleDateFormat(dateForm, Locale.US);
SimpleDateFormat formTime = new SimpleDateFormat(timeForm, Locale.US);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BugSenseHandler.initAndStartSession(MainActivity.this, "8b04fe90");
setContentView(R.layout.activity_main);
try {
updateCheck();
} catch (NameNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
/** Method to get todays date and display it in the proper places */
date = initialDates();
getDailyTimestamps(date);
/**
* Implements the Minus Button with OnCLickListener and
* calls the minusButtonHandler if called */
minusButton = (Button)findViewById(R.id.minusButton);
minusButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
date = minusButtonHandler();
getDailyTimestamps(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
});
/**
* Implements the Plus Button with OnCLickListener and
* calls the plusButtonHandler if called */
plusButton = (Button)findViewById(R.id.plusButton);
plusButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
date = plusButtonHandler();
getDailyTimestamps(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
});
quickAdd = (Button)findViewById(R.id.quickAddButton);
quickAdd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
quickAddHandler(v);
getDailyTimestamps(date);
}
});
}
@SuppressWarnings("deprecation")
private void updateCheck() throws NameNotFoundException, IOException, InterruptedException, ExecutionException {
Log.d("Checking for updates", "true");
String urlVersion;
UpdateCheck check = new UpdateCheck();
urlVersion = check.execute().get();
Log.d("urlVerion", urlVersion);
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
String packageVersion = pInfo.versionName;
Log.d("Package Version", packageVersion);
if (!urlVersion.equals(packageVersion)) {
AlertDialog alert = new AlertDialog.Builder(this).create();
alert.setTitle("Version Check");
alert.setMessage("You're version is out of date. Please visit "
+ "www.ubundude.com/p/beta.html to update to the latest version.");
alert.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
alert.show();
}
}
@Override
protected void onResume() {
super.onResume();
getDailyTimestamps(date);
}
private void getDailyTimestamps(String date) {
ArrayList<HashMap<String, String>> stampList = new ArrayList<HashMap<String, String>>();
/** Open the database table for reading and writing */
db = dbHelp.getReadableDatabase();
String getTimestamps = "select ti._id, pr.name, pr.shortcode, ti.hours, ti.project "
+ "from timestamp ti inner join projects pr "
+ "where ti.project = pr._id and ti.date_in = '" + date + "'";
Cursor cu = db.rawQuery(getTimestamps, null);
if(cu != null && cu.getCount() > 0){
cu.moveToFirst();
do {
HashMap<String, String> map = new HashMap<String, String>();
map.put(KEY_ID, Integer.toString(cu.getInt(0)));
map.put(KEY_SHORT, cu.getString(1));
map.put(KEY_FULL, cu.getString(2));
map.put(KEY_HOURS, cu.getString(3));
map.put(KEY_PROID, Integer.toString(cu.getInt(4)));
stampList.add(map);
} while(cu.moveToNext());
}
cu.close();
db.close();
list = (ListView)findViewById(R.id.timestampListView);
adapter = new TimestampAdapter(this, stampList);
list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.d("ListView On Click", "Position: " + position);
TextView idTV = (TextView)findViewById(R.id.listviewId);
TextView proIdTV = (TextView)findViewById(R.id.projectIdTV);
TextView full = (TextView)findViewById(R.id.projectShortTextView);
String test = full.getText().toString();
Log.d("Listview", "Project Name: " + test);
int timeId = Integer.parseInt(idTV.getText().toString());
Log.d("Listview", "Timestamp ID: " + timeId);
int proId = Integer.parseInt(proIdTV.getText().toString());
Log.d("Listview", "Project ID: " + proId);
Intent intent = new Intent(MainActivity.this, TimestampEditorActivity.class);
intent.putExtra("TIMESTAMP_ID", timeId);
intent.putExtra("PROJECT_ID", proId);
startActivity(intent);
}
});
}
private String initialDates() {
dateView = formDateView.format(c.getTime());
date = formDate.format(c.getTime());
/** Sets the text in the dateEditText to the current date */
dateEditText = (EditText)findViewById(R.id.dateEditText);
dateEditText.setText(dateView, TextView.BufferType.NORMAL);
return date;
}
/** Gets the next day and displays to dateEditText
* @throws ParseException */
private String plusButtonHandler() throws ParseException {
c.setTime(formDateView.parse(dateView));
c.add(Calendar.DAY_OF_MONTH, 1);
dateView = formDateView.format(c.getTime());
date = formDate.format(c.getTime());
dateEditText = (EditText)findViewById(R.id.dateEditText);
dateEditText.setText(dateView, TextView.BufferType.NORMAL);
return date;
}
/** Gets the previous day and displays to dateEditText
* @throws ParseException */
private String minusButtonHandler() throws ParseException {
c.setTime(formDateView.parse(dateView));
c.add(Calendar.DAY_OF_MONTH, -1);
dateView = formDateView.format(c.getTime());
date = formDate.format(c.getTime());
dateEditText = (EditText)findViewById(R.id.dateEditText);
dateEditText.setText(dateView, TextView.BufferType.NORMAL);
return date;
}
/**
* Intent to move to TimestampEditorActivity
*
* @param view Gets the current view context to pass with the intent
*/
public void addNewHandler(View view) {
Intent intent = new Intent(this, TimestampEditorActivity.class);
startActivity(intent);
}
/**
* Get current date and time and place them into Timestamp table as generic entry
*
* @param view
* @throws SQLException
*/
public void quickAddHandler(View view) throws SQLException {
String timeIn, timeOut, dateIn, dateOut;
int project = 1; //Will get from Default project in settings
timeIn = formTime.format(c.getTime());
timeOut = timeIn;
dateIn = formDate.format(c.getTime());
dateOut = dateIn;
db = dbHelp.getWritableDatabase();
String insertSQL = "insert into timestamp (date_in, time_in, date_out, time_out, hours, project) " +
"values('" + dateIn + "', '" + timeIn + "', '" + dateOut +
"', '" + timeOut + "', 0, '" + project + "')";
try {
db.execSQL(insertSQL);
} catch(Exception e) {
Log.d("save Fail", e.getLocalizedMessage(), e.fillInStackTrace());
}
db.close();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
这是 ListView 的 xml:
<TextView
android:id="@+id/projectShortTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="@string/defaultText"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/projectFullTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/projectShortTextView"
android:text="@string/defaultText"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/listviewId"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/projectShortTextView"
android:text="@string/defaultInt" />
<Button
android:id="@+id/listviewEditButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/listviewHoursTV"
android:background="@drawable/edit"
android:focusable="false" />
<TextView
android:id="@+id/listviewHoursTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="@string/defaultTime"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/projectIdTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/projectFullTextView"
android:layout_toRightOf="@+id/listviewId"
android:text="@string/defaultInt"
android:visibility="invisible" />
</RelativeLayout>
这是适配器: public class TimestampAdapter extends BaseAdapter { private Activity activity; 私有数组列表>数据;私有静态 LayoutInflater inflater = null;
public TimestampAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data = d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return data.get(position);
}
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.listview_timestamp, null);
TextView projectShort = (TextView)vi.findViewById(R.id.projectShortTextView);
TextView projectFull = (TextView)vi.findViewById(R.id.projectFullTextView);
TextView stampId = (TextView)vi.findViewById(R.id.listviewId);
TextView hoursEdit = (TextView)vi.findViewById(R.id.listviewHoursTV);
TextView projectId = (TextView)vi.findViewById(R.id.projectIdTV);
HashMap<String, String> timestamp = new HashMap<String, String>();
timestamp = data.get(position);
stampId.setText(timestamp.get(MainActivity.KEY_ID));
projectShort.setText(timestamp.get(MainActivity.KEY_SHORT));
projectFull.setText(timestamp.get(MainActivity.KEY_FULL));
hoursEdit.setText(timestamp.get(MainActivity.KEY_HOURS) + " hrs");
projectId.setText(timestamp.get(MainActivity.KEY_PROID));
return vi;
}
}
上面代码中的调试行显示了每行单击的正确位置,但第一行信息的 id 是唯一显示的信息。这与仅将第一行加载到编辑器中是一致的。