I'm using listView and in every line I have a button. I'm using OnClick and not a listener.
When I press the button I need to update the database. How can I know what is the ID?
here is my code:
public void saleButtonClick(View v) {
int quantity = 0;
TextView mQuantityTextView = (TextView) findViewById(R.id.main_quantity);
quantity = Integer.parseInt(mQuantityTextView.getText().toString());
if (quantity > 0){
quantity --;
Uri updateUri = ContentUris.withAppendedId(BookEntry.CONTENT_URI, v.getId());
ContentValues values = new ContentValues();
values.put(BookEntry.COLUMN_BOOK_QUANTITY, quantity);
int rowsUpdated = getContentResolver().update(
updateUri,
values,
null,
null);
if (rowsUpdated == 1) {
Toast.makeText(this, R.string.sellable, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, R.string.not_sellable, Toast.LENGTH_SHORT).show();
}
} else {
// Out of stock
Toast.makeText(this, R.string.out_of_stock, Toast.LENGTH_LONG).show();
}
mQuantityTextView.setText(Integer.toString(quantity));
}
If you use ListView with CursorAdapter (+ContentProvider) then you should add onClickListener in your CursorAdapter. In this case all of your List Items will have the SaleButton connected to your product (with it's unique id).
Try this code in your Adapter:
Button saleButton = view.findViewById(R.id.sale_button);
saleButton.setOnClickListener(v -> {
sellItem(_id, productQuantity);
});
/**
* helper method for sell a product
* #param id - id of product
* #param productQuantity - original quantity which must decreased by one
*/
private void sellItem(long id, int productQuantity) {
int newQuantity = --productQuantity;
// check that new quantity is greater than 0. In this case we update product
if (newQuantity > 0) {
ContentValues sellItem = new ContentValues();
sellItem.put(BookEntry.COLUMN_BOOK_QUANTITY, quantity);
int result= mContext.getContentResolver().update(ContentUris.withAppendedId(BookEntry.CONTENT_URI,id),sellItem,null,null);
if(result==1){
// rest of your code
}
}
}
Hope it helps.
I had a very similar project, take a look at: https://github.com/csongi77/InventoryApp
Best regards!
Related
I'm developing a recipe book and I'm implementing this method to insert my Recipe in the Database. In the for cycle I get the ingredient's name and quantity from multiples EditText, saving each of them in an Ingredient.class instance (newIngredient). Then I insert the instance into the DB and add it to an ArrayList. The followings "if conditions" are for the title, time and other Recipe's attributes. Finally, I also insert Recipe and Tag instances in the relatives DB's tables and I close DB.
public void saveRecipe() {
dbHelper = new DatabaseHelper(context);
// creating new recipe from user input
Ingredient newIngredient;
String title, childIngredient, instruction, tag;
int target, time, childQuantity, calories;
int countIngredients = parentIngredientLayout.getChildCount();
int countTags = chipGroup.getChildCount();
ArrayList<Ingredient> ingredients = null;
ArrayList<Tag> tags = null;
View childViewIng = null;
EditText childTextViewI = null;
EditText childTextViewQ = null;
// ingredients fields settings
for (int d=0; d<countIngredients; d++) {
childViewIng = parentIngredientLayout.getChildAt(d);
childTextViewI = childViewIng.findViewById(R.id.ingredientsField);
childTextViewQ = childViewIng.findViewById(R.id.quantityField);
childIngredient = childTextViewI.getText().toString();
childQuantity = Integer.parseInt(childTextViewQ.getText().toString());
newIngredient = new Ingredient(childIngredient, childQuantity);
dbHelper.insertIngredient(newIngredient);
ingredients.add(newIngredient);
}
//recipe fields settings
if (photoPath1 == null)
photoPath1 = "";
if (photoPath2 == null)
photoPath2 = "";
if (photoPath3 == null)
photoPath3 = "";
if (titleText.getText().toString().isEmpty()) {
title = "";
} else {
title = titleText.getText().toString();
}
if (targetNumber.getText().toString().isEmpty()) {
target = 0;
} else {
target = Integer.parseInt(targetNumber.getText().toString());
}
if (timeNumber.getText().toString().isEmpty()) {
time = 0;
} else {
time = Integer.parseInt(timeNumber.getText().toString());
}
if (instructionText.getText().toString().isEmpty()) {
instruction = "";
} else {
instruction = instructionText.getText().toString();
}
if (caloriesNumber.getText().toString().isEmpty()) {
calories = 0;
} else {
calories = Integer.parseInt(caloriesNumber.getText().toString());
}
if (tagName.getText().toString().isEmpty()) {
tag = "";
} else {
tag = tagName.getText().toString();
}
Recipe newRecipe = new Recipe(title, photoPath1, photoPath2, photoPath3, instruction, target, time, calories, ingredients);
Tag newTag = new Tag(tag);
dbHelper.insertRecipe(newRecipe);
dbHelper.insertTag(newTag);
dbHelper.close(); }
I found out by debugging that in this case is inserted only the first ingredient. I tried to move the FOR until the end of code, but in that case, are inserted both recipe and tag and always only the first ingredient. I think the problem is relative to the opening/closing of the DB. Can somebody help me?
Ingredient constructor:
public Ingredient(String ingredient_name, int quantity) {
this.ingredient_name = ingredient_name;
this.quantity = quantity;
}
dbHelper.insertIngredient(newIngredient) method:
public boolean insertIngredient(Ingredient ingredient) {
db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(INGREDIENT_NAME, ingredient.getIngredient_name());
contentValues.put(QUANTITY, ingredient.getQuantity());
contentValues.put(KEY_CREATED_AT, time.getTime().toString());
long result = db.insert(TBL_INGREDIENTS, null, contentValues);
//db.close();
Log.e(TAG, "Ingredient inserted!");
if (result == -1) {
return false;
} else {
return true;
}
}
Ok, thanks to your comment we got the problem :)
You are calling .add(newIngredient) on a list that you initialized with ArrayList<Ingredient> ingredients = null;
Change it to
ArrayList<Ingredient> ingredients = new ArrayList<Ingredient>();
and it will work :)
Good luck!
I hope you can help me with these
I am trying to extract information from my parse database for my android app (just a viewing app)
Basically what I want to do is I go select on my two spinners and click view
Once I click view it should query on three conditions
1st condition: current parse user = current user (from database)
2nd condition: selected item on spinner one (spin Month) = month (from database)
3rd condition: selected item on spinner two (spin Year) = year (from database)
Then it will give me the data needed for each text view (I was able to do this with just one condition but I need to specify it into 3 conditions)
Class Name: payslip
Column Name from class: username, month, year
I'm not sure which or what kind of if statement, switch case, or anything I can use so I can fit these 3 conditions
Thanks a bunch for the help!
a = (Spinner) findViewById(R.id.spinMonth);
ArrayAdapter adapterA = new ArrayAdapter(this,
android.R.layout.simple_spinner_item, month);
a.setAdapter(adapterA);
b = (Spinner) findViewById(R.id.spinYear);
ArrayAdapter adapterB = new ArrayAdapter(this,
android.R.layout.simple_spinner_item, year);
b.setAdapter(adapterB);
ParseQuery<ParseObject> query = ParseQuery.getQuery("payslip");
query.whereEqualTo("username",ParseUser.getCurrentUser().getUsername());
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> res, ParseException e) {
if (res == null) {
Toast.makeText(getApplicationContext(),
"Data Retrieved",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Data Not Retrieved",
Toast.LENGTH_LONG).show();
}
}
});
stringmonth = (String) a.getSelectedItem();
stringyear = (String) b.getSelectedItem();
view.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
ParseQuery<ParseObject> mainQuery = ParseQuery.getQuery("payslip");
mainQuery.whereEqualTo("month",stringmonth);
mainQuery.whereEqualTo("year",stringyear);
mainQuery.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> results, ParseException e) {
// TODO Auto-generated method stub
if (e == null) {
for (ParseObject x : results) {
String name = x.getString("name");
basic = x.getDouble("basicpay");
Double regot = x.getDouble("regot");
Double nightdiff = x.getDouble("nightdiff");
Double sss = x.getDouble("sss");
Double hdmf = x.getDouble("hdmf");
Double philhealth = x.getDouble("philhealth");
Double tax = x.getDouble("tax");
Double adjustment = x.getDouble("adjustment");
txtName.setText(name);
String stringbasic = Double.toString(basic);
txtBasic.setText(stringbasic);
String stringregot = Double.toString(regot);
txtRegot.setText(stringregot);
String stringnd = Double.toString(nightdiff);
txtND.setText(stringnd);
String stringsss = Double.toString(sss);
txtSSS.setText(stringsss);
String stringhdmf = Double.toString(hdmf);
txtHDMF.setText(stringhdmf);
String stringphilhealth = Double.toString(philhealth);
txtPhilhealth.setText(stringphilhealth);
String stringtax =Double.toString(tax);
txtTax.setText(stringtax);
String stringadjust = Double.toString(adjustment);
txtAdjust.setText(stringadjust);
gross = Double.valueOf(basic)+Double.valueOf(regot)+Double.valueOf(nightdiff);
String stringgross = Double.toString(gross);
txtGross.setText(stringgross);
deduction = Double.valueOf(sss)+Double.valueOf(hdmf)+Double.valueOf(tax)+Double.valueOf(philhealth);
String stringdeduction= Double.toString(deduction);
txtDeductions.setText(stringdeduction);
netpay= gross-deduction;
BigDecimal bd = new BigDecimal(netpay).setScale(2, RoundingMode.HALF_EVEN);
netpay = bd.doubleValue();
String stringnetpay=Double.toString(netpay);
txtNetpay.setText(stringnetpay);
}
}else {
// error
}
}
});
so apparently I got the answer I need
I omitted the first parse query I used
Inserted the two spinner.selected item inside the on click function of btnView
And also created the three line condition query which works!
The problem it doesn't apply the three conditions because in my parse database year is number and here I get it as a string..
public void onClick(View arg0) {
stringmonth = (String) a.getSelectedItem();
stringyear = (String) b.getSelectedItem();
numyear = Double.valueOf(stringyear);
ParseQuery<ParseObject> mainQuery = ParseQuery.getQuery("payslip");
mainQuery.whereEqualTo("username",ParseUser.getCurrentUser().getUsername());
mainQuery.whereEqualTo("month",stringmonth);
mainQuery.whereEqualTo("year",numyear);
mainQuery.findInBackground(new FindCallback<ParseObject>()
Sorry for the mouthful of a title, I have to cut it down because I exceeded the 150 character limit.
I have an AutoCompleteTextView (ACTV) and I am using a SimpleCursorAdapter since the normal ACTV only searches the user input at the start of each substring (substring are separated by whitespaces) and not within those substrings. For example, having a list with Adipose and Bad Wolf and searching ad will show Adipose only and not Bad Wolf. I already made the Adapter as shown below:
//create ACTV Here
AutoCompleteTextView search = (AutoCompleteTextView) findViewById(R.id.actvCatalogueSearch);
search.setThreshold(1);
String[] from = { "name" };
int[] to = { android.R.id.text1 };
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_dropdown_item_1line, null, from, to, 0);
cursorAdapter.setStringConversionColumn(1);
FilterQueryProvider provider = new FilterQueryProvider(){
#Override
public Cursor runQuery(CharSequence constraint) {
// TODO Auto-generated method stub
String constrain = (String) constraint;
constrain = constrain.toUpperCase();
Log.d("hi", "runQuery constraint: " + constraint);
if (constraint == null) {
return null;
}
String[] columnNames = { Columns._ID, "name" };
MatrixCursor c = new MatrixCursor(columnNames);
try {
for (int i = 0; i < pdflist.length; i++) {
if(pdflist[i].contains(constrain)){
Log.d("Hello","Match! pdflist item = " + pdflist[i]);
c.newRow().add(i).add(pdflist[i]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
};
cursorAdapter.setFilterQueryProvider(provider);
search.setAdapter(cursorAdapter);
This code enables me to show the other list items that contains the substring from the user input.
Now, I am trying to make the OnItemClickListener function properly. Here is what I have so far:
search.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
MatrixCursor matrix = (MatrixCursor)parent.getItemAtPosition(position);
Log.d("hello", "matrix values is = " + matrix);
String selection = matrix.getString(position);
Log.d("hallo","selection = " + selection);
Log.d("hello","item id at position = " + parent.getItemIdAtPosition(position));
int pos = (int) parent.getItemIdAtPosition(position);
Log.d("sup", "position is = " + pos);
String path = imagelist[pos].getAbsolutePath();
openPdfIntent(path);
}
});
Here, I am trying to get the MatrixCursor element at the given position. It works fine of the user selects the first 2 suggestions. However, when the user clicks the 3rd suggestion onwards, the application throws a CursorIndexOutOfBoundsException Requested Column: 2, # of columns: 2 Clicking on the logCat lines pointed me to the code String selection = matrix.getString(position);
I think that doing matrix.getString(position) causes the error since getString returns the value of the requested column as a String, and since there are only 2 columns, selecting a suggestion in the ACTV whose position (position as it is shown to the user, not the position of the said item in the list) is greater than 2 causes the code to screw up.
My question is, is there a better way to get the String value of the selected item given that I am using SimpleCursorAdapter? I've looked over the documentation of Matrix Cursor in the android dev site and I can't find a way to get a row/element based on the position.
Any help is very much appreciated.
Edit:
using matrix.moveToFirst(); as such did not help as well:
search.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
MatrixCursor matrix = (MatrixCursor)parent.getItemAtPosition(position);
if(matrix != null) {
if(matrix.getCount() > 0) {
matrix.moveToFirst();
String selection = matrix.getString(position);
int pos = (int) parent.getItemIdAtPosition(position);
String path = imagelist[pos].getAbsolutePath();
openPdfIntent(path);
}
}
}
});
and I still got the exception:
android.database.CursorIndexOutOfBoundsException: Requested column: 4, # of columns: 2
The requested column 4 is the position of the selected ACTV suggestion, indexed zero.
Try out like this
MatrixCursor matrix = .............
Log.d("hello", "matrix values is = " + matrix);
/***** Check here Cursor is NOT NULL *****/
if(matrix != null) {
if(matrix.getCount() > 0) {
matrix.moveToFirst();
/***
Your Stuff will be here....
**/
}
}
Made it work using a different approach. I get the View and cast it as a TextView. From there, I get the String input. I then use this string and look for its position in the original list. Note that my list is an Array, not an ArrayList, that's why I had to loop through all the items.
search.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView) view;
String userSelection = tv.getText().toString();
Log.d("hello", "selection is = " + userSelection);
int pos = -1;
for (int i = 0; i < pdflist.length; i++) {
if(pdflist[i].equalsIgnoreCase(userSelection)){
pos = i;
}
}
Log.d("hello","int position = " + pos);
String path = imagelist[pos].getAbsolutePath();
openPdfIntent(path);
}
});
Can't seem to find a solution to this. I'm trying to edit the data in my List View item. The List View uses an array adapter to display the data in a row in the list view.
The user holds their finger over the list view item they wish to edit which causes a box to pop up containing the option of either 'Delete' or 'Edit'. When the user clicks to Edit the data, the data from that list view item is supposed to be transferred over to the other activity where the user can edit it. Instead of transferring the data that I want to edit, the data from the last item in the List View is transferred.
This is the code below.
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int position = info.position;
switch (item.getItemId()) {
case R.id.edit:
{
itemCheck = true;
String bCheck = String.valueOf(itemCheck);
iTitle = paymentTitle.get(position).toString();
iPaymentDate = paymentDate.get(position).toString();
iReminderDate = reminderDate.get(position).toString();
iReminderTime = reminderTime.get(position).toString();
iAmount = paymentVal.get(position).toString();
if(iReminderDate == "No Date Set")
{
iReminderDate = "";
}
else
{
Intent reminder = new Intent(this, MyBroadcastReceiver.class);
PendingIntent.getBroadcast(this.getApplicationContext(), 1, reminder,
PendingIntent.FLAG_UPDATE_CURRENT).cancel();
}
if(iReminderTime == "No Time Set")
{
iReminderTime = "";
}
Intent intent = new Intent(Payments.this, AddPayment.class);
intent.putExtra("PID", pID);
intent.putExtra("ITITLE", pTitle);
intent.putExtra("PAYMENTDAY", pDay);
intent.putExtra("PAYMENTMONTH", pMonth);
intent.putExtra("PAYMENTYEAR", pYear);
intent.putExtra("REMINDERDAY", rDay);
intent.putExtra("REMINDERMONTH", rMonth);
intent.putExtra("REMINDERYEAR", rYear);
intent.putExtra("REMINDERHOUR", rHour);
intent.putExtra("REMINDERMIN", rMin);
intent.putExtra("IAMOUNT", pValue);
intent.putExtra("ITEMCHECK", itemCheck);
startActivity(intent);
finish();
}
return true;
This is the data from my database
C = readableDB.query("PaymentTable", new String[] { "_ID", "PTITLE", "PA", "PDAY", "PMONTH", "PYEAR", "RDAY", "RMONTH",
"RYEAR", "RMIN", "RHOUR", "DATE"}, null, null, null, null, "DATE ASC");
This is how the variables is created using the data imported from the Database.
paymentID = C.getInt(C.getColumnIndex("_ID"));
pTitle = C.getString(C.getColumnIndex("PTITLE"));
pDay = C.getString(C.getColumnIndex("PDAY"));
pMonth = C.getString(C.getColumnIndex("PMONTH"));
pYear = C.getString(C.getColumnIndex("PYEAR"));
rDay = C.getString(C.getColumnIndex("RDAY"));
rMonth = C.getString(C.getColumnIndex("RMONTH"));
rYear = C.getString(C.getColumnIndex("RYEAR"));
rHour = C.getString(C.getColumnIndex("RHOUR"));
rMin = C.getString(C.getColumnIndex("RMIN"));
pValue = C.getString(C.getColumnIndex("PA"));
pID = paymentID.toString();
This is how the array list items are made which are used to display the data in my list view.
reminderDateStr = rDay + "/" + rMonth + "/" + rYear;
reminderTimeStr = rHour + ":" + rMin;
paymentDateStr = pDay + "/" + pMonth + "/" + pYear;
paymentTitleStr = pTitle;
paymentValue = "£" + pValue;
paymentTitle.add(paymentTitleStr);
reminderTime.add(reminderTimeStr);
paymentDate.add(paymentDateStr);
reminderDate.add(reminderDateStr);
paymentVal.add(paymentValue);
Would really appreciate it if someone could tell me how to get this working or at least tell me where I've went wrong and what I should try instead. Thanks to anyone who tries to help me with this.
Instead of using onContextItemSelected to open the new activity, I think you can use OnItemClickListener for that. You can declare it this ways:
yourListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
ListView lv = (ListView)parent;
#SuppressWarnings("unchecked")
ArrayAdapter<YourObject> adapter = ArrayAdapter<YourObject>)
lv.getAdapter();
YourObjectitem = adapter.getItem(position);
// The rest of the code goes here
}
});
I downloaded a class from Catch The Cows, it is akin to a Google Map object or at least that is what I am using it for.
It parses an XML file which lists the areas of the screen that should be touchable, and then creates them with this method.
This is here for context, I have commented out some parts of code, and added my own to try and resolve my issue
private Area addShape( String shape, String name, String coords, String id) {
Log.v("IDS:", "id was "+id);
Area a = null;
String rid = id.replace("#+id/", "");
Log.v("IDS:", "rid was "+rid);
// Generate a new ID for the area.
int _id = 1;
View vi = findViewById(_id);
while (vi!=null) {
_id++;
vi = findViewById(_id);
}
//View.generateViewId(); //=0;
Log.v("IDS:", "After conversion final time "+_id);
/*
try {
Class<R.id> res = R.id.class;
Field field = res.getField(rid); // eg. rid = area10
_id = field.getInt(null);
Log.v("IDS:", "After conversion "+_id);
}
catch (Exception e) {
_id = 0;
Log.e("Exception ",e.getMessage());
} finally {
Log.v("IDS:", "After conversion final time "+_id);
}
*/
if (_id != 0) {
if (shape.equalsIgnoreCase("rect")) {
String[] v = coords.split(",");
if (v.length == 4) {
a = new RectArea(_id, name, Float.parseFloat(v[0]),
Float.parseFloat(v[1]),
Float.parseFloat(v[2]),
Float.parseFloat(v[3]));
}
}
if (shape.equalsIgnoreCase("circle")) {
String[] v = coords.split(",");
if (v.length == 3) {
a = new CircleArea(_id,name, Float.parseFloat(v[0]),
Float.parseFloat(v[1]),
Float.parseFloat(v[2])
);
}
}
if (shape.equalsIgnoreCase("poly")) {
a = new PolyArea(_id,name, coords);
}
if (a != null) {
addArea(a);
}
} else {
Log.v("Loading ID: ","_id was 0");
}
return a;
}
Unfortunately nothing was rendering on the screen, and this was because _id = 0. This should be changed with this bit of code:
try {
Class<R.id> res = R.id.class;
Field field = res.getField(rid); // eg. rid = area10
_id = field.getInt(null);
}
How ever I am not sure what it does to try and debug it, can anyone explain what this snippet is doing?
R is a Read-Only class. It is generate at compile time and You should not use reflection to modify its field. Also you should avoid reflection to access the fields values. You should use the official API.
The comment at the first row of the class is
/* AUTO-GENERATED FILE. DO NOT MODIFY. */