I'm creating a small Financecontrol-App. Now I'm facing a problem i don't think I can handle without hitting my phone =D
I got an Activity with a ViewPager created from Android-Template. I got 3 tabs. The second and third tabs use the same Fragment-Class. Here is the snippet for the tabs:
in AccountActivity:
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
Bundle args = new Bundle();
switch (position) {
case POSITION_OVERVIEW:
fragment = new OverviewSectionFragment();
break;
case POSITION_INCOME:
args.putString("flag", TransactionSectionFragment.INCOME);
fragment = new TransactionSectionFragment();
fragment.setArguments(args);
break;
case POSITION_OUTGO:
args.putString("flag", TransactionSectionFragment.OUTGO);
fragment = new TransactionSectionFragment();
fragment.setArguments(args);
break;
}
return fragment;
}
the Fragment itself looks like this:
public class TransactionSectionFragment extends Fragment {
OnDataChangedListener mCallback;
public interface OnDataChangedListener {
public void onDataChanged(int rnd);
}
// Private variables for IncomeSectionFragment
private FinanceDataSource datasource;
private ListView transactionList;
private CustomFinanceListAdapter adapter;
private String flag;
private Button newTran;
// public constants
public static final String INCOME = "i";
public static final String OUTGO = "o";
// Variables for Contextmenu
private static final int DETAILS_OPTION = Menu.FIRST;
private static final int DELETE_OPTION = DETAILS_OPTION + 1;
public TransactionSectionFragment() {
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (OnDataChangedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnDataChangedListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_account_transactions, container, false);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
newTran = (Button) getView().findViewById(R.id.new_entry_btn);
transactionList = (ListView) this.getView().findViewById(
R.id.transactionlist);
flag = getArguments().getString("flag");
datasource = new FinanceDataSource(getActivity());
datasource.open();
updateList();
registerForContextMenu(transactionList);
transactionList
.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
Transaction tran = (Transaction) transactionList
.getItemAtPosition(position);
showTransactionDetails(tran);
}
});
newTran.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
datasource.insertSomeTransactions();
updateList();
}
});
}
@Override
public void onResume() {
datasource.open();
super.onResume();
}
@Override
public void onPause() {
datasource.close();
super.onPause();
}
private void showTransactionDetails(Transaction tran) {
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v.getId() == R.id.transactionlist) {
menu.setHeaderTitle("Optionen ");
menu.add(Menu.NONE, DETAILS_OPTION, 0, "Details");
menu.add(Menu.NONE, DELETE_OPTION, 1, "Eintrag löschen");
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
.getMenuInfo();
Transaction tran = (Transaction) transactionList
.getItemAtPosition(info.position);
switch (item.getItemId()) {
case DETAILS_OPTION:
showMsg(tran.getID() + "");
break;
case DELETE_OPTION:
try {
datasource.deleteTransaction(tran);
updateList();
showMsg("Entry deleted!");
} catch (Exception e) {
Log.i("Exception", e.getMessage());
}
break;
}
return true;
}
// Show Toast
private void showMsg(String message) {
Toast msg = Toast.makeText(getActivity(), message, Toast.LENGTH_LONG);
msg.show();
}
private void updateList() {
adapter = new CustomFinanceListAdapter(
datasource.getAllTransactions(flag), getActivity());
transactionList.setAdapter(adapter);
mCallback.onDataChanged(new Random().nextInt());
}
}
and now the problem: the first Fragment which represents the income is filled with data from a sqlite database flagged with an "i". the second Fragment is outgo flagged with an "o". This works pretty fine. ervery entry in the listview represents a Transaction ---> see here:
public class Transaction {
// private variables
int id;
String date;
double value;
String desc;
String flag;
// Empty constructor
public Transaction() {
}
// constructor
public Transaction(String date, double value, String desc, String flag) {
this.date = date;
this.value = value;
this.desc = desc;
this.flag = flag;
}
// constructor
public Transaction(int id, String date, double value, String desc,
String flag) {
this.id = id;
this.date = date;
this.value = value;
this.desc = desc;
this.flag = flag;
}
// get name
public int getID() {
return this.id;
}
// get name
public String getDate() {
return this.date;
}
// set name
public void setDate(String date) {
this.date = date;
}
// get value
public double getValue() {
return this.value;
}
// set value
public void setValue(double value) {
this.value = value;
}
// get description
public String getDesc() {
return this.desc;
}
// set description
public void setDesc(String desc) {
this.desc = desc;
}
// get flag
public String getFlag() {
return this.flag;
}
// set flag
public void setFlag(String flag) {
this.flag = flag;
}
@Override
public String toString() {
return this.getDesc();
}
}
by long-clicking a list-item i get the ID of the Transaction which should be the same like it has in the database (autoincrementy primary key etc.). so it should be unique. but the first item on outgo-list has the same id as the first item on income-list. by deleting an item from income-list the last item in the outcome list gets a outofboundexception because theoretically there should have been one less than displayed. but the outcome-list does not refresh itself like income and is more like a "copy" of income with different values.
hope you get my problem.... if you need more code please tell me =)
EDIT 1: Here is the SQL-Statement creating the table:
USERS_TABLE_CREATE = "CREATE TABLE "
+ TABLE_FINANCES + " (" + COLUMN_ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," + COLUMN_DATE
+ " DATETIME NOT NULL," + COLUMN_VALUE + " REAL NOT NULL," + COLUMN_DESC
+ " NVARCHAR(255)," + COLUMN_FLAG + " NVARCHAR(1) NOT NULL);";
Datasets itself look like:
(id, date, value, description, flag) ==> ex1: (2, 23.08.2013, 33.33, "tip", "i") for an income dataset and ex2: (3, 23.08.2013, 12.12, "tickets", "o") for an outcome-dataset
Now some pictures: income screen with getID() of first entry --> https://i.stack.imgur.com/lCeeD.png outgo screen with getID() of first entry --> https://i.stack.imgur.com/6gdUQ.png
EDIT 2: I solved the problem with help from: Wrong fragment in ViewPager receives onContextItemSelected call
you have to wrap the onContextItemSelected Call with this because the fragmentmanager takes the first availabe fragment returning true for contextmenu and not the one you're actually on
if (getUserVisibleHint()) {
// Handle menu events and return true
} else
return false; // Pass the event to the next fragment
}