Change SQL query based on button action - java

I have a listview that displays all the items in my database. I am trying to create a button that will change the data displayed to only show items that match today's date.
What is the best way to change the query that is being run in the app based on a button push and update the listview?
I've played with setting a flag in the onclick() method paired with if-else statements that held the query call, but it did not seem to switch which was being called.
The flag is the boolean filterToday. set in the onClickListener of todayButton.
public class MainActivity extends AppCompatActivity {
public final static String KEY_EXTRA_CONTACT_ID = "KEY_EXTRA_CONTACT_ID";
private ListView listView;
DBHelper dbHelper;
boolean filterToday;
Cursor cursor;
String [] columns;
int [] widgets;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button addButton = (Button) findViewById(R.id.addNew);
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, AddTaskActivity.class);
intent.putExtra(KEY_EXTRA_CONTACT_ID, 0);
startActivity(intent);
}
});
Button todayButton = (Button) findViewById(R.id.today);
todayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
filterToday = true;
}
});
dbHelper = new DBHelper(this);
if(filterToday == true){
Calendar cal = Calendar.getInstance();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String date = df.format(cal.getTime());
Toast.makeText(this,date,Toast.LENGTH_LONG).show();
cursor = dbHelper.getTodaysTasks(date);
}
else{
cursor = dbHelper.getAllTasks();
}
columns = new String[] {
DBHelper.TASK_COLUMN_NAME,
DBHelper.TASK_COLUMN_TYPE,
DBHelper.TASK_COLUMN_DATE
};
widgets = new int[] {
R.id.taskName,
R.id.taskType,
R.id.taskDate
};
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, R.layout.task_info,
cursor, columns, widgets, 0);
listView = (ListView)findViewById(R.id.listView1);
listView.setAdapter(cursorAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
Cursor itemCursor = (Cursor) MainActivity.this.listView.getItemAtPosition(position);
int taskID = itemCursor.getInt(itemCursor.getColumnIndex(DBHelper.TASK_COLUMN_ID));
Intent intent = new Intent(getApplicationContext(), AddTaskActivity.class);
intent.putExtra(KEY_EXTRA_CONTACT_ID, taskID);
startActivity(intent);
}
});
}
}
These are the two queries I am trying to switch between:
public Cursor getAllTasks() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery( "SELECT * FROM " + TASK_TABLE_NAME, null );
return res;
}
public Cursor getTodaysTasks(String date){
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("SELECT * FROM " + TASK_TABLE_NAME + " WHERE " +
TASK_COLUMN_DATE + " =?", new String[]{date});
return res;
}

OK so the first thing to notice is that your update filterToday = true; inside the onclick listener, the if(filterToday == true){...} outside doesn't know that. That part is only executed once in the oncreate()
If you'd like to perform that action I suggest a small change.. like below
Create a seperate function outside for the data loading
private void LoadMyData() {
if(filterToday == true){
Calendar cal = Calendar.getInstance();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String date = df.format(cal.getTime());
//you might need to update this line
//Toast.makeText(this,date,Toast.LENGTH_LONG).show();
//assume dbHelper is ready at this point
cursor = dbHelper.getTodaysTasks(date);
}
else{
cursor = dbHelper.getAllTasks();
}
}
Call this function inside onclick listner
filterToday = false;//initialize to false if necessary
todayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
filterToday = !filterToday ;//by doing it like this you can switch back and forth. add/check extra logic if necessary
LoadMyData();
}
});
LoadMyData(); //Call this outside in the oncreate to load the data initially
I'm not suggesting a code improvement here. Just changes to what you already have. Hope it helps.

There were two issues that I ran into, the first was comparing a string to to the SQL string[], which meant while the comparison was working, it did not behave as I expected. Once fixing this issue was updating the ListView object. This was handled by creating a new adapter and attaching it to ListView, which then updates itself.
Per this answer: Refresh Current Fragment (ListView Data) remaining in the same activity
The other option was to call notifyDataSetChanged() on the adapter, but this did not work well with the way I had my program set up.

Related

Android Studio - New Item in List is not shown

In my App i have a ListView, if i add some new Items, the ListView does not shown the Items. The items will be shown if i close the app and go back in it.
So my new Items are saved in my Database, but the list will not be synchronized.
i followed a Tutorial on youtube, if he tries it, it works fine, but not in my app. i hope someone can help me to find my problem.
In my newItem_Activity i have an Add-Button with following Code:
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(todo.getName() == null){
Toast.makeText(ToDoCreateNew.this, "Please insert some value.", Toast.LENGTH_LONG).show();
return;
}
ToDoDatabaseHelper.getInstance(ToDoCreateNew.this).createTodo(todo);
finish();
}
});
My Database looks like this:
public ToDo createTodo(final ToDo todo) {
SQLiteDatabase database = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(NAME_COLUMN, todo.getName());
contentValues.put(DUEDATE_COLUMN, todo.getDueDate() == null ? null : todo.getDueDate().getTimeInMillis() / 1000);
contentValues.put(FAVORITE_COLUMN, todo.isFavorite() ? 1 : 0);
contentValues.put(DESCRIPTION_COLUMN, todo.getDescription());
contentValues.put(DUETIME_COLUMN, String.valueOf(todo.getDueTime() == null ? null : todo.getDueTime().getTime()));
long newID = database.insert(TABLE_NAME, null, contentValues);
database.close();
return readToDo(newID);
}
public List<ToDo> readAllToDos(){
List<ToDo> todos = new ArrayList<>();
SQLiteDatabase database = this.getReadableDatabase();
Cursor c = database.rawQuery("SELECT * FROM " + TABLE_NAME, null);
if (c.moveToFirst()){
do {
ToDo todo = readToDo(c.getLong(c.getColumnIndex(ID_COLUMN)));
if (todo != null){
todos.add(todo);
}
} while (c.moveToNext());
}
database.close();
return todos;
}
and this Code is on my Activity with my ListView:
List<ToDo> dataSource;
ToDoOverviewListAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_to_do_overview);
lv = (ListView) findViewById(R.id.listToDo);
dataSource = ToDoDatabaseHelper.getInstance(this).readAllToDos();
adapter = new ToDoOverviewListAdapter(this, dataSource);
lv.setAdapter(new ToDoOverviewListAdapter(this, dataSource));
}
// Go to Activity to Add new Item - Add Button is in newItem_Activity
public void createToDo(){
startActivity(new Intent(ToDoOverview.this, ToDoCreateNew.class));
refreshListView();
}
private void refreshListView(){
dataSource.clear();
dataSource.addAll(ToDoDatabaseHelper.getInstance(this).readAllToDos());
adapter.notifyDataSetChanged();
}
Do one thing when you add lists in adapter , wrap it in a method and call that method in both onCreate and OnStart Method . So basically you have to add list in adapter two times On OnCreate method and OnStart method. So When you update the data and move back to your original activity it will trigger OnStart method and it will show updated data.

Display a SQLite colum one value after another

I'm really strugling to figure this out and had not found an answer or a way to do it.
What I'm trying to do is having questions that are saved in a SQLite colum to be displayed in a TextView one after another until they finish.
What I have done so far on the main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDatabaseHelper = new DatabaseHelper(this);
btn1star = (Button) findViewById(R.id.btn1star);
btn2star = (Button) findViewById(R.id.btn2star);
btn3star = (Button) findViewById(R.id.btn3star);
mListview = (ListView) findViewById(R.id.qlistview);
qTextView = (TextView) findViewById(R.id.qTextView);
questionsListView();
}
private void questionsListView() {
Cursor data = mDatabaseHelper.getData();
data.moveToFirst();
qTextView.setText(data.getString(1));
}
public void VoteClick(View view){
mDatabaseHelper.getReadableDatabase();
Cursor data = mDatabaseHelper.getData();
if (data.getCount() >=1){
for (int i = 0; i< data.getCount(); i++) {
data.moveToNext();
Log.i("Counted Questions are: ", String.valueOf(data.getCount()));
qTextView.setText(data.getString(1));
}
}
}
private void toastmessage (String message){
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
I'm able to display the first and when i click the button the last question
I'm unable to display the questions between.
Any tip or suggestion?
In your VoteClick method you do your getReadableDatabase, this is too late, move this line into onCreate method. You must open the database before reading from it (in questionsListView).
mDatabaseHelper.getReadableDatabase();//move to onCreate
add this:
startManagingCursor(data);
data.moveToFirst();
BEFORE the line:
if (data.getCount() >=1){
Hello found a solution to my problem
It turns out that i have to make a new int variable
Get its value from the first id
and incrise this by one at the end of each button press until i reach the last cursor place whhere i move the cursor to the first position
public void VoteClick(View view) {
Cursor data = mDatabaseHelper.getData();
data.moveToPosition(q);
data.moveToNext();
qTextView.setText(data.getString(1));
while (data.isLast()) {
data.moveToFirst();
q = data.getPosition();
}
q = q+1;
}

Changing the onClickListener of an Imagebutton dynamically without ever leaving the activity

I have an ImageButton with an onClickListener. That sets the "favorite" column of an entry in my database to "1" or "0" and changes the image of the button. What is the best way to refresh the view or activity, so the onClickListener changes dynamically.
If I failed to make myself clear:
Click 1: Update favorite column to 1, change image to ic_star_black_48dp
Click 2: Update favorite column to 0, change image to ic_star_border_black_48dp
Click 3: Update favorite column to 1, change image to ic_star_black_48dp
Click 4: Update favorite column to 0, change image to ic_star_border_black_48dp
All of this without ever leaving the activity.
star.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (cn.getFavorite() == 0) {
star.setImageResource(R.mipmap.ic_star_black_48dp);
db_verladestellen.updatePlace(new Location(cn.getID(), cn.getPlace_id(), cn.getName(), cn.getLongitude(), cn.getLatitude(), cn.getTor(), 1));
}
else{
star.setImageResource(R.mipmap.ic_star_border_black_48dp);
db_verladestellen.updatePlace(new Location(cn.getID(), cn.getPlace_id(), cn.getName(), cn.getLongitude(), cn.getLatitude(), cn.getTor(), 0));
}
}
});
EDIT:
Since you asked, this is the whole class. Below it is the method getAllDBPlaces().
public class UI_Verladestellen extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.verladestellen);
//Initialisation of the database
final DB_Verladestellen db_verladestellen = new DB_Verladestellen(this);
//Saves all entries from the database in a List
List<Location> placeList = db_verladestellen.getAllDBPlaces();
//Generates a button for each entry in the list
for (final Location cn : placeList) {
//Linear Layout for the buttons
final LinearLayout layout = (LinearLayout) findViewById(R.id.verladestellen_liste);
final LinearLayout row = new LinearLayout(this);
row.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
//Favorites-Button
final ImageButton star = new ImageButton(this);
star.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT));
if (cn.getFavorite() == 0) {star.setImageResource(R.mipmap.ic_star_border_black_48dp);}
else {star.setImageResource(R.mipmap.ic_star_black_48dp);}
star.setId(cn.getID());
row.addView(star);
star.setPadding(50,50,50,50);
star.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (cn.getFavorite() == 0) {
star.setImageResource(R.mipmap.ic_star_black_48dp);
db_verladestellen.updatePlace(new Location(cn.getID(), cn.getPlace_id(), cn.getName(), cn.getLongitude(), cn.getLatitude(), cn.getTor(), 1));
}
else{
star.setImageResource(R.mipmap.ic_star_border_black_48dp);
db_verladestellen.updatePlace(new Location(cn.getID(), cn.getPlace_id(), cn.getName(), cn.getLongitude(), cn.getLatitude(), cn.getTor(), 0));
}
}
});
//Location-Button
Button place = new Button(this);
place.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
place.setText(cn.getName());
place.setId(cn.getID());
row.addView(place);
row.setId(cn.getID());
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) place.getLayoutParams();
params.weight = 1.0f;
place.setLayoutParams(params);
place.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openMap(cn.getID());
}
});
layout.addView(row);
}
}
//Methode zum öffnen der Map in MainActivity. Übermittelt die ID des Buttons, von dem die Methode aufgerufen wird.
//Diese ID ist identisch mit der ID des Ortes in der Datenbank, den der Button repräsentiert.
public void openMap(int view) {
Intent intent = new Intent(UI_Verladestellen.this, UI_MainActivity.class);
intent.putExtra("findLocation", view);
startActivity(intent);
}
}
getALLDBPlaces:
public List<Location> getAllDBPlaces() {
List<Location> placeList = new ArrayList<Location>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_DB_VERLADESTELLEN_Eintrag;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Location location = new Location();
location.setID(Integer.parseInt(cursor.getString(0)));
location.setPlace_id(cursor.getString(1));
location.setName(cursor.getString(2));
location.setLongitude(cursor.getString(3));
location.setLatitude(cursor.getString(4));
location.setTor(cursor.getString(5));
location.setFavorite(cursor.getInt(6));
// Adding contact to list
placeList.add(location);
} while (cursor.moveToNext());
}
// return contact list
return placeList;
}
Well after you edited your question, my answer will be different.
First of all, you should check for Adapter implementation.
It will be easier to handle your scenario and be way more effective.
But then you should try to implement it yourself and come agian if you face any issues.

Dynamically Add onClick ActionListener to CheckBox in Android

I am creating an application, which creates checkboxes dynamically from the number of entries in the database.
The code runs fine. and creates number of checkboxes. But I want to add onClick Action Listener to the CheckBoxes, dynamically. How to do this.
I am posting the code here:
SQLiteDatabase db = this.getReadableDatabase();
String countQuery = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
int maxCount = cursor.getCount();
CheckBox[] check = new CheckBox[maxCount];
cursor.moveToFirst();
int checkboxid = 100;
int alarm_id;
for(int i=0;i<maxCount;i++)
{
check[i]= new CheckBox(this);
setCheckBoxId(i+maxCount);
}
Now how to add actionlistener to these dynamically created CheckBoxes.
check[i]= new CheckBox(this);
check[i].setOnClickListener(this);
You will want to check against the checkbox id or set a tag for the text boz when creating it.
check[i].setTag(someIdentifier);
then use the method
#Override
public void onClick(View v) {
if (v.getTag.equals(someIdentifier)){
//do stuff here
}
}
below check[i]= new CheckBox(this); add this, and your CheckBoxes will have a all clicklistener
check[i].setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// your code to be executed on click :)
}
});

Custom SimpleCursorAdapter with imageButton random values

I am trying to add image button to my custom SimpleCursorAdapter for my ListView in my project but I have got one problem with repeating and totally random value of one field.
This is a code of it:
public class MyCursorAdapter extends SimpleCursorAdapter {
public MyCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
super.bindView(view, context, cursor);
final Context t = context;
final Cursor c = cursor;
ImageButton delimageButton = (ImageButton)view.findViewById(R.id.deletebutton);
delimageButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Toast.makeText(t,
"Delete ID: " + c.getInt(c.getColumnIndex(MyDBAdapter.KEY_ID)), Toast.LENGTH_SHORT).show();
}
});
if(cursor.getLong(cursor.getColumnIndex(MyDBAdapter.KEY_OWNID))>0)
{
TextView own = (TextView)view.findViewById(R.id.ownInfo);
own.setText("OWN");
}
else
{
TextView own = (TextView)view.findViewById(R.id.ownInfo);
own.setText("");
}
}
}
Now, when I press delimageButton what I get is some random ID of one record (row) of ListView that is in current view (I can see it, but it is not the correct id) e.g. if you can see like 5 rows on screen and you press on one of buttons you will get id of other row (one of those 5) but not this one which you pressed (in most of the cases). I remember that there was some trick with this own TextView, but I don't see how it can be putted in here.
So, can you please advice me how can I make it to show correct ID?
I'll be glad for help.
EDIT
There is a whole code responsible for setting a ListView together with calling MyCursorAdapter:
private void refreshList() {
mySQLiteAdapter = new MyDBAdapter(this);
mySQLiteAdapter.open();
String[] columns = { MyDBAdapter.KEY_TITLE, MyDBAdapter.KEY_GENRE,
MyDBAdapter.KEY_OWNID, MyDBAdapter.KEY_ID };
Cursor contentRead = mySQLiteAdapter.getAllEntries(false, columns,
null, null, null, null, MyDBAdapter.KEY_TITLE, null);
startManagingCursor(contentRead);
Log.d(TAG, Integer.toString(contentRead.getCount()));
MyCursorAdapter adapterCursor = new MyCursorAdapter(this,
R.layout.my_row, contentRead, columns, new int[] {
R.id.rowTitle, R.id.detail });
this.setListAdapter(adapterCursor);
mySQLiteAdapter.close();
}
To clarify, the activity is ListActivity.
Your OnClickListener is getting the id from the cursor when it is clicked, not when it is constructed. Meanwhile, the listview is changing the cursor position as you scroll around.
I think if you look carefully, you'll find the Toast is displaying the id of the last item that was loaded into view rather than the item that contains the button you clicked.
You can solve this by getting the id when you construct the click listener, like this:
delimageButton.setOnClickListener(new OnClickListener() {
private int id = c.getInt(c.getColumnIndex(MyDBAdapter.KEY_ID));
#Override
public void onClick(View arg0) {
Toast.makeText(t,
"Delete ID: " + id, Toast.LENGTH_SHORT).show();
}
});

Categories

Resources