I have a listview with textviews that bring information from a table in sql server as id, description and quantity. I need that when the user clicks on an item in the listview, open another activity with that information that the user selected, the user can edit and save in the database.
I have the following code that queries the database and fills the listview, but I can't find the way to pass the information to another activity. Any help?
public void getProd() {
comandSQL = "Select * from Inventory where [Code] = '"+loccode+"' order by [Bin Code]";
try {
Statement statement = MainActivity.connect.createStatement();
rs = statement.executeQuery(comandSQL);
List<Map<String, String>> data = null;
data = new ArrayList<Map<String,String>>();
while(rs.next()){
Map<String, String> datanum = new HashMap<String, String>();
datanum.put("idProd", rs.getString("No_"));
datanum.put("desc", rs.getString("Description"));
datanum.put("ubic", rs.getString("Bin Code"));
datanum.put("cant", rs.getString("Inventory"));
data.add(datanum);
}
String[] from = {"idProd","desc","ubic","cant"};
int[] views = {R.id.id_prod,R.id.descripcion, R.id.ubicacion,R.id.cant};
AD = new SimpleAdapter(this, data, R.layout.list, from, views);
Lista.setAdapter(AD);
} catch (Exception e) {
Log.e("ERROR",e.getMessage());
}
}
You want to set up a click listener for each listview item:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Do something when a list item is clicked
}
When the item is clicked, you need to gather the data from that view and then simply start a new activity passing that data via an Intent
Intent intent = new Intent(mContext, YourNewActivity.class);
intent.putExtra("MyData", userData.toString());
startActivity(intent);
Related
My app layout apparently isn't a normal layout so I a having trouble setting my List Adapter to auto updated when an edit is made.
I make my edits to my database in this Java File which is controlled in its own activity and layout.
public void onClick(View view){
if (view == findViewById(R.id.addsave)) {
RecipeRepo repo = new RecipeRepo(this);
Recipe recipe = new Recipe();
if (editTextName.getText().toString().equals("")) {
editTextName.setError("Recipe name required!");
return;
} else {
recipe.name = editTextName.getText().toString();
}
if (textImagePath.getText().toString().equals("") ) {
recipe.image = ("");
}else{
recipe.image = textImagePath.getText().toString();
}
recipe.category = staticSpinner.getSelectedItem().toString();
if (editTextIngredients.getText().toString().equals("")) {
editTextIngredients.setError("Ingredient required!");
return;
} else {
recipe.ingredients = editTextIngredients.getText().toString();
}
if (editTextInstruct.getText().toString().equals("")) {
editTextIngredients.setError("Instruction required!");
return;
} else {
recipe.instructions = editTextInstruct.getText().toString();
}
recipe.cooktemp = editTextCookTemp.getText().toString();
recipe.cooktime = editTextCookTime.getText().toString();
recipe.serves = editTextServings.getText().toString();
recipe.recipe_Id = _Recipe_Id;
if (_Recipe_Id == 0) {
_Recipe_Id = repo.insert(recipe);
Toast.makeText(this, "New Recipe Added", Toast.LENGTH_SHORT).show();
finish();
it actually inserts and updates in this java file
int insert(Recipe recipe){
//Open connection to write data
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Recipe.KEY_SERVES, recipe.serves);
values.put(Recipe.KEY_COOKTIME, recipe.cooktime);
values.put(Recipe.KEY_COOKTEMP, recipe.cooktemp);
values.put(Recipe.KEY_INSTRUCT, recipe.instructions);
values.put(Recipe.KEY_INGREDIENTS, recipe.ingredients);
values.put(Recipe.KEY_CATEGORY, recipe.category);
values.put(Recipe.KEY_IMAGE, recipe.image);
values.put(Recipe.KEY_NAME, recipe.name);
//Inserting Row
long recipe_Id = db.insert(Recipe.TABLE, null, values);
db.close();// Closing database connection
return (int) recipe_Id;
}
void delete(int recipe_Id){
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete(Recipe.TABLE, Recipe.KEY_ID + "=?", new String[] {String.valueOf(recipe_Id)});
db.close();
}
void update(Recipe recipe){
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Recipe.KEY_SERVES, recipe.serves);
values.put(Recipe.KEY_COOKTIME, recipe.cooktime);
values.put(Recipe.KEY_COOKTEMP, recipe.cooktemp);
values.put(Recipe.KEY_INSTRUCT, recipe.instructions);
values.put(Recipe.KEY_INGREDIENTS, recipe.ingredients);
values.put(Recipe.KEY_CATEGORY, recipe.category);
values.put(Recipe.KEY_IMAGE, recipe.image);
values.put(Recipe.KEY_NAME, recipe.name);
db.update(Recipe.TABLE, values, Recipe.KEY_ID + "=?", new String[]{String.valueOf(recipe.recipe_Id)});
db.close();
}
and lastly it gets put into the list view from this Java file and separate layout. Which is where my adapters are but i cannot get the notifyDataSetChanged() to work here at all... as in it wont even come up.
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
RecipeRepo repo = new RecipeRepo(this);
if (id == R.id.nav_meat) {
final ArrayList<HashMap<String, String>> recipeList = repo.getRecipeMeat();
if(recipeList.size()!=0) {
ListView lv = (ListView) findViewById(R.id.list);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
recipe_Id = (TextView) view.findViewById(R.id.recipe_Id);
String recipeId = recipe_Id.getText().toString();
Intent objIndent = new Intent(getApplicationContext(), RecipeDetail.class);
objIndent.putExtra("recipe_Id", Integer.parseInt(recipeId));
startActivity(objIndent);
}
});
ListAdapter adapter = new SimpleAdapter(SousChef.this, recipeList, R.layout.view_recipe_entry, new String[]{"id", "category", "name"}, new int[]{R.id.recipe_Id, R.id.recipe_list_category, R.id.recipe_list_name});
lv.setAdapter(adapter);
}else {
Toast.makeText(this, "No recipe!", Toast.LENGTH_SHORT).show();
}
} else if (id == R.id.nav_veg) {
final ArrayList<HashMap<String, String>> recipeList = repo.getRecipeVeg();
if(recipeList.size()!=0) {
ListView lv = (ListView) findViewById(R.id.list);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
recipe_Id = (TextView) view.findViewById(R.id.recipe_Id);
String recipeId = recipe_Id.getText().toString();
Intent objIndent = new Intent(getApplicationContext(), RecipeDetail.class);
objIndent.putExtra("recipe_Id", Integer.parseInt(recipeId));
startActivity(objIndent);
}
});
ListAdapter adapter = new SimpleAdapter(SousChef.this, recipeList, R.layout.view_recipe_entry, new String[]{"id", "category", "name"}, new int[]{R.id.recipe_Id, R.id.recipe_list_category, R.id.recipe_list_name});
lv.setAdapter(adapter);
}else {
Toast.makeText(this, "No recipe!", Toast.LENGTH_SHORT).show();
}
So any advise on setting this up to automatically update would be a huge help. I have been racking my brain over this for a couple days now looking at different examples and what not, but no setup is quite like this one which doesnt allow me to have everything in one file.
And thank you in advance.
category picking image:
Category picking Image
There are for sure more answers but this is one that might help,
Quick Example for the proposed solution
SHORT EXPLANATION
inside MainActivity
//create a public static adapter
public static ListAdapter adapter
inside onCreateView()
//Create your adapter and set it to the right ListView
ListView lv = findViewById(R.id.listView_in_xml);
adapter = new SimpleAdapter(...)
lv.setAdapter(adapter)
inside CustomAdapter which in your case I assume is SimpleAdapter
//add a public method to be called so that the Adapter updates and displays the new data
public void updateMethod(){
//update your List<Recipe> that I would guess you have calling the database again
//if needed update your getCount() return value so that it returns the number of childs in your ListView which most of the cases is just the List<Recipe>.size()
//notifyDataSetChanged()
}
inside your DB HANDLER CLASS
//in every update, add, delete or any method that requires the ListView to Update just call the created method,
MainActivity.CustomAdapter.updateMethod();
PROBLEMS
You will have to make sure the public static adapter has been initialized and is not null, or simply check whether the adapter is not null and update, because if the adapter is null that activity has not launched yet thus no need to trigger the updateMethod().
OTHER SOLUTIONS
Instead of creating a public static adapter create a public static boolean, then whenever data changes set that boolean to true from the database.
Finally, whenever you resume your activity check against that boolean and update your ListViewAdapter if needed.
MORE COMPLICATED SOLUTIONS WHICH I KNOW WORK CAUSE I USE IT
Use TaskAsyncTaskLoader which utilizes a Loader in your MainActivity and implements LoaderManager.LoaderCallbacks.
Optionally, you can make the Loader be, public static Loaderand inside your DBHandler you trigger the loader to load the data again or use any other logic you want.
Proofs of Working suggested solution,
You can Broadcast Intent from the change database file after you get the response in the onCreate() of adapter loading class
Intent intent = new Intent("key_to_identify_the_broadcast");
Bundle bundle = new Bundle();
bundle.putString("edttext", "changed");
intent.putExtra("bundle_key_for_intent", bundle);
context.sendBroadcast(intent);
and then you can receive the bundle in your fragment by using the BroadcastReceiver class
private final BroadcastReceiver mHandleMessageReceiver = new
BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle =
intent.getExtras().getBundle("bundle_key_for_intent");
if(bundle!=null){
String edttext = bundle.getString("edttext");
}
//you can call any of your methods for using this bundle for your use case
}
};
in onCreate() of your adapter adding class you need to register the broadcast receiver first otherwise this broadcast receiver will not be triggered
IntentFilter filter = new IntentFilter("key_to_identify_the_broadcast");
getActivity().getApplicationContext().
registerReceiver(mHandleMessageReceiver, filter);
Finally you can unregister the receiver to avoid any exceptions
#Override
public void onDestroy() {
try {
getActivity().getApplicationContext().
unregisterReceiver(mHandleMessageReceiver);
} catch (Exception e) {
Log.e("UnRegister Error", "> " + e.getMessage());
}
super.onDestroy();
}
Description: I want to use share button. With share button user sending a list as a message. In the list each item has Title + Description
The problem: System get all items from a list and put it in the line one after another by using a comma.
I have: TitleItemOne,DescriptionItemOne,TitleItemTwo,DescriptionItemTwo
I need:
TitleItemOne - DescriptionItemOne
TitleItemTwo - DescriptionItemTwo
Or:
Maybe it is easier to replace all ODD comma "," with "-" so it will that style which i am looking for.
That's the code (needed code in Sharebutton method)
/**
* Displays list of list that were entered and stored in the app.
*/
public class CatalogActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
private static final String TAG = "myLogs";
/** Identifier for the pet data loader */
private static final int LIST_LOADER = 0;
/** Adapter for the ListView */
ListCursorAdapter mCursorAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_catalog);
Log.v(TAG, "Зашли в catalog activity oncreate");
// Setup FAB to open EditorActivity
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(CatalogActivity.this, EditorActivity.class);
startActivity(intent);
}
});
// Find the ListView which will be populated with the list data
ListView listListView = (ListView) findViewById(R.id.list);
// Find and set empty view on the ListView, so that it only shows when the list has 0 items.
View emptyView = findViewById(R.id.empty_view);
listListView.setEmptyView(emptyView);
// Setup an Adapter to create a list item for each row of list data in the Cursor.
// There is no items data yet (until the loader finishes) so pass in null for the Cursor.
mCursorAdapter = new ListCursorAdapter(this, null);
listListView.setAdapter(mCursorAdapter);
// Setup the item click listener
listListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
ShoppingListBdHelper helper = new ShoppingListBdHelper(view.getContext());
if (helper.setCompleted(id)) {
mCursorAdapter.setCompleted(view);
}
}
});
// Kick off the loader
getSupportLoaderManager().initLoader(LIST_LOADER, null, this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu options from the res/menu/menu_catalog.xml file.
// This adds menu items to the app bar.
getMenuInflater().inflate(R.menu.menu_catalog, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// User clicked on a menu option in the app bar overflow menu
switch (item.getItemId()) {
// Respond to a click on the "Insert dummy data" menu option
case R.id.action_share_button:
shareButton(mCursorAdapter.getCursor());
return true;
// Respond to a click on the "Delete all entries" menu option
case R.id.action_delete_all_entries:
deleteAllItems();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Share button
*/
private void shareButton(Cursor cursor) {
Log.v(TAG, "--- WE ARE IN SHARE BUTTON METHOD ---");
List<String> test;
test = new ArrayList<String>();
cursor.moveToFirst();
while(!cursor.isAfterLast()) {
Log.d(TAG, "field: " + cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_NAME)));
test.add(cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_NAME))); //add the item
test.add(cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_DESCRIPTION))); //add the item
cursor.moveToNext();
}
cursor.moveToFirst();
Log.v(TAG, "--- OUR LIST INCLUDES: " + test.toString());
Intent myIntent = new Intent();
myIntent.setAction(Intent.ACTION_SEND);
myIntent.putStringArrayListExtra("test", (ArrayList<String>) test);
myIntent.putExtra(android.content.Intent.EXTRA_TEXT, test.toString());
Log.v(TAG, "--- INTENT EXTRAS ARE: " + myIntent.getExtras());
myIntent.setType("text/plain");
startActivity(Intent.createChooser(myIntent, "Share using"));
}
/**
* Helper method to delete all list in the database.
*/
private void deleteAllItems() {
Log.v(TAG, "Сработал метод удаления всех данных");
long rowsDeleted = getContentResolver().delete(ListContract.ListEntry.CONTENT_URI, null, null);
Log.v("CatalogActivity", rowsDeleted + " rows deleted from list database");
}
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
Log.v(TAG, "Начал работать loader cursor");
// Define a projection that specifies the columns from the table we care about.
String[] projection = {
ListContract.ListEntry._ID,
ListContract.ListEntry.COLUMN_ITEM_NAME,
ListContract.ListEntry.COLUMN_ITEM_DESCRIPTION,
ListContract.ListEntry.COLUMN_ITEM_COMPLETED
};
// This loader will execute the ContentProvider's query method on a background thread
return new CursorLoader(this, // Parent activity context
ListContract.ListEntry.CONTENT_URI, // Provider content URI to query
projection, // Columns to include in the resulting Cursor
null, // No selection clause
null, // No selection arguments
null); // Default sort order
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Update {#link ListCursorAdapter} with this new cursor containing updated pet data
mCursorAdapter.swapCursor(data);
Log.v(TAG, "Cursor adapter загрузился");
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// Callback called when the data needs to be deleted
mCursorAdapter.swapCursor(null);
}
}
you can format your strings to html or using "\n"
string to html :
you can use Html.fromHtml() to use HTML tag in your string :
Html.fromHtml("<h2>Title</h2><br><p>Description here</p>"));
for using "\n" you can use System.getProperty("line.separator") wich is OS dependent line separator
Change
test.add(cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_NAME))); //add the item test.add(cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_DESCRIPTION)));
To
test.add(cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_NAME)) + "-" + (cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_DESCRIPTION)));
Note:
I may not have all the parenthesis correctly closed, but you get the idea
Im so new to this android development. What im trying to do is to pass the id from MainActivity to Details. So i need to get the id from the MainActivity in order to display the details of a person in Details class. I can pass the id already and display it, but im having trouble on displaying the details of that specific id which is from the database values. How can i display the contents of that specific id in the Details class using the Database function getDetails(id); ? I need to display it on the textviews of the Details activity class. Please help
DB Function
public Cursor getDetails(String id) {
return database.query(TABLENAME, null, id + "=" + id, null, null,
null, null);
}
MainActivity.java
this.listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3){
TextView txtID = (TextView) view.findViewById(R.id.id);
String id = txtID.getText().toString();
Intent intent = new Intent(MainActivity.this, Details.class);
intent.putExtra("id", id);
startActivity(intent);
}
});
In Details.java, i want to display here the contents of the ID which is on the database. How can i call on to that function and make it display using the ID from the intent being passed?
Details.java
Intent i = getIntent();
String id = i.getStringExtra("id");
txtId = (TextView) findViewById(R.id.id);
txtName= (TextView) findViewById(R.id.name);
txtAbout = (TextView) findViewById(R.id.about);
txtId.setText(id);
txtName.setText(name);
txtAbout .setText(about);
public HashMap<String,String> getDetails(String id) {
HashMap<String, String> hm = new HashMap<>();
SQLiteDatabase db = getWritableDatabase();
Cursor c = db.query(TABLENAME, null, "id=?", new String[]{id}, null, null, null);
if(c.getCount()>0){
c.moveToFirst();
hm.put(KEY, c.getString(c.getColumnIndex(COLUMN_NAME)));
// do this for all columns that you want.
}
c.close();
db.close();
return hm;
}
and in Details.java
String id = getIntent().getExtras.getString("id");
HashMap<String, String> hm = (Your database class Object).getDetails(id);
if(hm.size()>0){
String value1 = hm.get(KEY);
// get all data and show according to you.
}
I am trying to use parse to set comments for a specific post , I already have a Post class and a Comment class in the parse.com Data , anyway I tried to set a comment inside a column in the class and then get it , but the problem is , I can only get 1 comment per post , how to do that , is my question , I tried one to many relations , but it didn't work , I tried a pointer row in the Meal class that points to the Comment class , but I didn't know what to do then , here is some sample code :
public void addTheComment() {
// Create the Post object
ParseObject post = new ParseObject("Post");
post.put("textContent", txtComment.getText().toString());
// Create an author relationship with the current user
post.put("comment", getCurrentMeal());
// Save the post and return
post.saveInBackground(new SaveCallback () {
#Override
public void done(ParseException e) {
if (e == null) {
setResult(RESULT_OK);
finish();
} else {
Toast.makeText(getApplicationContext(),
"Error saving: " + e.getMessage(),
Toast.LENGTH_SHORT)
.show();
}
}
});
this adds a comment from edit text through out a button when pressed
and here is the list that shows the comments :
private void updateComments() {
ParseQueryAdapter<ParseObject> adapter =
new ParseQueryAdapter<ParseObject>(this, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery<ParseObject> create() {
// Here we can configure a ParseQuery to our heart's desire.
ParseQuery query = new ParseQuery("Post");
query.whereEqualTo("comment", getCurrentMeal());
return query;
}
});
adapter.setTextKey("comment");
adapter.setImageKey("photo");
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
}
and :
public Meal getCurrentMeal() {
return meal;
}
private void updateComments() {
ParseQueryAdapter<ParseObject> adapter =
new ParseQueryAdapter<ParseObject>(this, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery<ParseObject> create() {
// Here we can configure a ParseQuery to our heart's desire.
ParseQuery query = new ParseQuery("Comment");
query.whereContainedIn("parent", Arrays.asList(mealId));
return query;
}
});
adapter.setTextKey("content");
// adapter.setImageKey("photo");
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
}
and when pressing the button (activate the method addTheComment) it adds the text from the edit text (txtComment)to insert it into the Comment section where you make a relation to the Post class.
public void addTheComment() {
// Create the comment
ParseObject myComment = new ParseObject("Comment");
myComment.put("content", txtComment.getText().toString());
// Add a relation between the Post with objectId "1zEcyElZ80" and the comment
myComment.put("parent", ParseObject.createWithoutData("Meal", mealId));
// This will save both myPost and myComment
myComment.saveInBackground();
}
Here is the code:
ibtSearchStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
try{
searchQuery = etSearchThis.getText().toString();
searchQuery = searchQuery.toUpperCase();
cursor = searchActivity.getData(product, "product", tableColumns);
//Clean ArrayList
resultRow.clear();
resultTable.clear();
//Get Search Result
resultTable = searchActivity.searchByProductName(cursor, searchQuery);
//Display Search Result
for(int ctr = 0; ctr < resultTable.size(); ctr++){
HashMap<String, String> map = new HashMap<String, String>();
resultRow = resultTable.get(ctr);
String result = resultRow.get(2);
map.put("ProductName",result);
list.add(map);
}
Log.e("resultProduct", "" + list);
adapter = new SimpleAdapter(
SearchMain.this,
list,
R.layout.search_result,
new String[]{"ProductName"},
new int[]{R.id.tvProductName}
);
lvSearchResult.setAdapter(adapter);
}
finally{
product.close();
}
}
});
The function of this is that it will search for a match in the database then it will insert the result of the search in a HashMap then on a adapter.
But every click i am not able to remove the previous result.
What is the proper implementation to this?
When you are working with adapters and the information changes, be sure that you are calling adapter.notifyDataSetChanged();
You set a new adapter each time the OnClick event is triggered. As Jay Snayder wrote you should use adapter.notifyDataSetChanged(); instead. But be sure to set the adapter only once and move the following part of your code (e.g. to your onCreate() method of the activity):
adapter = new SimpleAdapter(
SearchMain.this,
list,
R.layout.search_result,
new String[]{"ProductName"},
new int[]{R.id.tvProductName}
);
lvSearchResult.setAdapter(adapter);
Just update the DataSet of your adapter (here: 'list').