1

我有一个带有适配器的自定义 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 是唯一显示的信息。这与仅将第一行加载到编辑器中是一致的。

4

1 回答 1

2

您的问题可能在于以下几行:

TextView idTV = (TextView)findViewById(R.id.listviewId);
TextView proIdTV = (TextView)findViewById(R.id.projectIdTV);
TextView full = (TextView)findViewById(R.id.projectShortTextView);

您在 的布局中找到这些视图Activity而不是在 ListView 的行中。如果这些 id 在 ListView 中也重复,请通过以下方式访问整行

view.findViewById(R.id.yourId);

如果 StampList 是包含所有这些数据的复杂 Object 的列表,则可以跳过查找 View 并简单地使用适配器或 AdapterView 来访问该对象。

编辑:您正在使用 HashMap,这应该更容易:

@Override
public void onItemClick(AdapterView<?> parent, View view,
                        int position, long id) {
  HashMap <String,String> currentMap = stampList.get(position);
  Intent intent = new Intent(MainActivity.this, TimestampEditorActivity.class);
  intent.putExtra("TIMESTAMP_ID", currentMap.get(MainActivity.KEY_ID));
  intent.putExtra("PROJECT_ID", currentMap.get(MainActivity.KEY_PROID));
  startActivity(intent);
}

只要确保声明stampListfinal. 或者,如果您不想指定stampListfinal替换

HashMap <String,String> currentMap = stampList.get(position);

HashMap <String,String> currentMap = (HashMap<String,String>)parent.getItemAtPosition(position);
于 2013-03-06T03:12:10.100 回答