In my activity I have the ActionBar with an action button new(that adds a new item on the ListView) and a ListView. The problem is that after I add some items and then I press back button, the ListView returns to the previous ListView with an item less and after one/two seconds shows the complete listviews with all items. I think the problem is something like the listview duplicate one over the previous.
Here is my activity:
public class ListNotesActivity extends ActionBarActivity {
private ArrayList<Note> notes;
private Database db;
private long lastBackPressTime = 0;
private Toast toast;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_notes);
notes = new ArrayList<Note>();
db = new Database(this);
getNotes();
ActionBar ab = getSupportActionBar();
ab.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#E89619")));
ab.setTitle("Your notes");
}
#Override
public void onBackPressed() {
if (this.lastBackPressTime < System.currentTimeMillis() - 4000) {
toast = Toast.makeText(this, "Press back again to exit", 4000);
toast.show();
this.lastBackPressTime = System.currentTimeMillis();
} else {
if (toast != null)
toast.cancel();
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list_notes, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case R.id.action_new:
//In this activity that I start, It will save the new Item in the database and then it starts this activity again that will read the database with the new item.
Intent i = new Intent(ListNotesActivity.this,
NotesActivity.class);
i.putExtra(NEWNOTE, true);
startActivity(i);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void getNotes() {
final Toast t = Toast.makeText(this, R.string.retrieving_notes,
Toast.LENGTH_SHORT);
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
notes = db.getNotes();
Log.v("MyActivity",
"Read notes on the database: " + notes.size());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
populateList();
}
};
t.show();
task.execute();
}
public void populateList() {
NoteAdapter adapter = new NoteAdapter(this, notes);
final ListView listView = (ListView) findViewById(R.id.list_notes);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parentView, View childView,
int position, long id) {
Note note = notes.get(position);
Log.v("MyActivity",
"LISTNOTESACTIVITY: note's title: " + note.getTitle());
Bundle b = new Bundle();
b.putSerializable(EDITNOTE2, note);
Intent i = new Intent(ListNotesActivity.this,
NotesActivity.class);
i.putExtra(EDITNOTE, true);
i.putExtra(EDITNOTE2, b);
startActivity(i);
}
});
}
I hope I made me clear.
Thanks in advance!
try to remove this line from your getNotes() Method
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Your list view is update only when activity is created ( not when is resumed ) , because you call getNotes() only in onCreate(). In method getNotes(), you make asynch operation.
If you want to update immediately your list view, should take strategy like this.
Start new activity for result, and in second activity after create new item pass data back to the first.
In NotesActivity after create new item add and call this method
private void saveItem(Note note)
{
Intent data = new Intent();
// set all data from your item
data.putExtra(name, value);
setResult(RESULT_OK, data);
}
In ListNotesActivity you should start new activity by using this call
startActivityForResult(intent, 1);
And override this method
#Override
protected void onResume()
{
super.onResume();
// This call on your list view to update rows
listViewAdapter.notifyDataSetChanged();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(resultCode == RESULT_OK && requestCode == 1)
{
Note note = new Note();
// Extract your data from intent
data.getExtra(name); // and set to note variable
// add your new item to list view adapter
listViewAdapter.addNewItem(note);
}
}
I hope this will help you.
Related
I have a List View in one activity with one info icon in custom adapter. When user taps on that info button then the next activity will open and after marking attendance in next activity when user taps the update button then the second activity should finish and first activity listview should be updated.
What i successfully did:
I have successfully mark the attendance and change the color of listview but i did that after closing the second activity and restarting the first activity. In this way the listview gets updated because of starting activity again.
What I am unable to do:
I want that when user taps on update button then only finish() will call and user returns to previous first activity with listview updated. But when i do so then the listview not get updated. I have to go back and open the activity again then the listview gets updated otherwise not. I do not want that. I also tried to notify adapter in the onResume method of first activity so that when user returns from second activity then the first activity listview adapter will be updated because of onResume method but it isn't work. Please Help
My Listview Activity Code:
public class TeacherWebserviceMainList extends Activity {
int attentedncemarkedCount = 0;
TextView addteacher;
DatabaseHandler databasehandler;
DetailsTeacherwebservice details;
String emis;
ArrayList<DetailsTeacherwebservice> addas = new ArrayList<DetailsTeacherwebservice>();
CustomAdapterTeacherWebservice cusadapter;
ArrayList<DetailsTeacherwebservice> teacherList;
private ListView listcontent = null;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teacherwebservicemainlist );
addteacher = (TextView) findViewById(R.id.addteachermenu);
databasehandler = new DatabaseHandler(TeacherWebserviceMainList.this);
listcontent = (ListView) findViewById(R.id.teacher_list);
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if(resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if(update.equals("1"))
{
//cusadapter.
CustomAdapterTeacherWebservice adapter = new CustomAdapterTeacherWebservice(this, addas);
listcontent.setAdapter(adapter);
}
}
}
}
private void Rsults() {
addas.clear();
//DatabaseHandler databaseHandler=new DatabaseHandler(this);
//ArrayList<ArrayList<Object>> data = databaseHandler.abcTeacherNew();
for (int p = 0; p < teacherList.size(); p++) {
details = new DetailsTeacherwebservice();
//ArrayList<Object> baris = data.get(p);
details.setId(teacherList.get(p).getId());
details.setTeachername(teacherList.get(p).getTeachername());
details.setTeachercnic(teacherList.get(p).getTeachercnic());
details.setTeacherno(teacherList.get(p).getTeacherno());
details.setTeachergender(teacherList.get(p).getTeachergender());
details.setAttendance(teacherList.get(p).getAttendance());
details.setTeacherattendancedetails(teacherList.get(p).getTeacherattendancedetails());
details.setAttendancedatesince(teacherList.get(p).getAttendancedatesince());
details.setAttendancetrasnferschool(teacherList.get(p).getAttendancetrasnferschool());
addas.add(details);
}
cusadapter = new CustomAdapterTeacherWebservice(TeacherWebserviceMainList.this, addas);
listcontent.setAdapter(cusadapter);
listcontent.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
});
}
My List Adapter Code
public class CustomAdapterTeacherWebservice extends BaseAdapter {
private static ArrayList<DetailsTeacherwebservice> searchArrayList;
DatabaseHandler databaseHandler;
private Context context;
private LayoutInflater mInflater;
public CustomAdapterTeacherWebservice(Context context, ArrayList<DetailsTeacherwebservice> results) {
searchArrayList = results;
mInflater = LayoutInflater.from(context);
databaseHandler = new DatabaseHandler(context);
}
#Override
public int getCount() {
return searchArrayList.size();
}
#Override
public Object getItem(int p) {
return searchArrayList.get(p);
}
#Override
public long getItemId(int p) {
return p;
}
public int getViewTypeCount() {
return 500;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public View getView(final int p, View v, ViewGroup parent) {
ViewHolder holder;
context = parent.getContext();
if (v == null) {
v = mInflater
.inflate(R.layout.teacherwebserviceadapter, null);
holder = new ViewHolder();
holder.name = (TextView) v.findViewById(R.id.teacher_name);
holder.cnic = (TextView) v.findViewById(R.id.teacher_cnic);
holder.no = (TextView) v.findViewById(R.id.teacher_phone);
holder.gender = (TextView) v.findViewById(R.id.gender);
holder.status = (TextView) v.findViewById(R.id.status);
holder.info = (ImageView) v.findViewById(R.id.edit);
holder.l1 = (LinearLayout) v.findViewById(R.id.main);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.name.setText(searchArrayList.get(p).getTeachername());
holder.cnic.setText(searchArrayList.get(p).getTeachercnic());
holder.no.setText(searchArrayList.get(p).getTeacherno());
holder.gender.setText(searchArrayList.get(p).getTeachergender());
holder.status.setText(searchArrayList.get(p).getAttendance());
if (searchArrayList.get(p).getAttendance().equals("Absent"))
{
holder.l1.setBackgroundColor(Color.parseColor("#DB674D"));
}
if (searchArrayList.get(p).getAttendance().equals("Present"))
{
holder.l1.setBackgroundColor(Color.parseColor("#7EB674"));
}
if (searchArrayList.get(p).getAttendance().equals("Transfer Out"))
{
holder.l1.setBackgroundColor(Color.parseColor("#FBE87C"));
}
if (searchArrayList.get(p).getAttendance().equals("Resigned"))
{
holder.l1.setBackgroundColor(Color.parseColor("#4FC3F7"));
}
holder.info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent view_order_intent = new Intent(context, Teacherwebservicemainlistupdate.class);
view_order_intent.putExtra("ID", searchArrayList.get(p).getId());
view_order_intent.putExtra("tname", searchArrayList.get(p).getTeachername());
view_order_intent.putExtra("tgender", searchArrayList.get(p).getTeachergender());
view_order_intent.putExtra("tcnic", searchArrayList.get(p).getTeachercnic());
view_order_intent.putExtra("tno", searchArrayList.get(p).getTeacherno());
view_order_intent.putExtra("tatt", searchArrayList.get(p).getAttendance());
view_order_intent.putExtra("tattdetails", searchArrayList.get(p).getTeacherattendancedetails());
view_order_intent.putExtra("tattdatesince", searchArrayList.get(p).getAttendancedatesince());
view_order_intent.putExtra("tatttrasnferout", searchArrayList.get(p).getAttendancetrasnferschool());
//context.startActivity(view_order_intent);
((Activity)context).startActivityForResult(view_order_intent, 1);
}
});
return v;
}
static class ViewHolder {
TextView name, cnic, no, gender,status;
ImageView info;
LinearLayout l1;
}
here in adapter code when INFO button is clicked then another activity starts in which user can update the attendance.
This is Update activity code when button clicked:
update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DetailsTeacherwebservice schoolinfo = new DetailsTeacherwebservice();
schoolinfo.setTeachername(teachername.getText().toString());
schoolinfo.setTeacherno(teacherno.getText().toString());
schoolinfo.setTeachercnic(teachercnic.getText().toString());
schoolinfo.setTeachergender(teachergender.getText().toString());
schoolinfo.setAttendance(teachergroupstr);
schoolinfo.setTeacherattendancedetails(absentgrpstr);
schoolinfo.setAttendancedatesince(txtDate.getText().toString());
schoolinfo.setAttendancetrasnferschool(transferOutSchool.getText().toString());
databasehandler.updateteacherwebservice(schoolinfo, emis, identity);
Toast.makeText(Teacherwebservicemainlistupdate.this, "Updated Successfully", Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.putExtra("update", "1");
setResult(RESULT_OK, intent);
finish();
}
}
});
I can start the listview activity again when update button is clicked but that changes the index of the list item clicked i.e. because activity starts again. How ever what i want is that if i clicked on 10th item then when next activity opens and user updates attendance then it returns back to previous activity on same index position so that the user do not have to scroll again to go back on 10th item
Add this code for list item click:
Intent i = new Intent(context, YourAcitivityName.class);
i.putExtra("position",p);
startActivityForResult(i, 1);
Add this code in update button:
Intent intent = new Intent();
intent.putExtra("update", "1");
intent.putExtra("position",getIntent().getIntExtra("position",0));
setResult(RESULT_OK, intent);
finish();
When you get back from activity to the activity where list view is implemented this method called:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if(resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if(update.equals("1"))
{
// add your code to update list view
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
YourAdapterClassName adapter = new YourAdapterClassName(this, arrList);
listView.setAdapter(adapter);
listView.smoothScrollToPosition(getIntent().getIntExtra("position",0));
}
}
}
}
The following are two examples, the first is an example where the source for the ListView is a List (and in this case using a Custom Adapter), the second is where the source is a Cursor (using SimpleCursorAdapter)
The trap many fall into is just updating the List using something like :-
myList = method();
myAdapter.notifyDataSetChanged();
At a guess, that's the trap you've fallen into.
When what should be done is to use the List's methods to alter it (e.g. clear, add, addAll, remove).
I believe this explains the reasoning - Is Java “pass-by-reference” or “pass-by-value”?
Example 1 - List as the source :-
/**
* Build or rebuild the List of TaskData's, instantiate the
* Custom Array Adapter if needed and also notify the adapter
* if the List may have been changed.
*/
private void prepTasksCustomArrayList() {
// Determine if the adpater needs to be notified of changes
boolean notify_dataset_changed = (mCsr != null && mCustomArrayAdapter != null);
// If the List is not null then assume that it has changed
// otherwise just get the List
if (mTasks != null) {
mTasks.clear();
mTasks.addAll(dbhlpr.getAllTasks());
} else {
mTasks = dbhlpr.getAllTasks();
}
// If the adapter is null then instantiate it
if (mCustomArrayAdapter == null) {
mCustomArrayAdapter = new CustomArrayAdapter(
this,
R.layout.taskdata_item,
mTasks);
}
// Notify the adapter that the List has changed
if (notify_dataset_changed) {
mCustomArrayAdapter.notifyDataSetChanged();
}
}
Notes
This is used to both setup and alter/update the ListView that the adpater is attached to.
All that is needed is to call the method at the appropriate place/s in the code e.g. in the Activities onCreate, onResume, after onItemClick/LongClick.
e.g in onCreate :-
mTaskList = this.findViewById(R.id.tasklist); // The ListView
prepTasksCustomArrayList()
mTaskList.setAdapter(mCustomArrayAdapter)
and in onresume just (in conjunction with the 3 lines in onCreate)
prepTasksCustomArrayList()
I don't believe that this way is very common, normally you see the adapter being setup in onCreate.
mTasks.addAll(dbhlpr.getAllTasks()); is what gets the source data.
Example 2 - Cursor as the Source
/**
* Build or rebuild the List via Cursor using the bespoke layout
*/
private void prepCursorListBespoke() {
boolean swapcursor = (mCsr != null && mCursorAdapter2 != null);
if (mCursorAdapter2 == null) {
mCursorAdapter2 = new SimpleCursorAdapter(this,R.layout.taskdata_item,mCsr,
new String[]{ Datasource.TASKS_ID_COL,
Datasource.TASKS_TYPE_COL,
Datasource.TASKS_NAME_COL,
Datasource.TASKS_OWNER_COL,
Datasource.TASKS_EXPIRATION_COL},
new int[]{R.id.task_id,
R.id.task_type,
R.id.task_name,
R.id.task_owner,
R.id.task_expiration},
0);
}
if (swapcursor) {
mCursorAdapter2.swapCursor(mCsr);
}
}
Notes
The prepCursorListBespoke method is used in the same way as for example 1.
notifyDataSetChanged could be used instead of swapCursor
I use swapCursor because it's more descriptive).
However, you can only use swapCursor for Cursors.
Added
The following changes may work, roughly speaking I've applied the List example above.
i.e. Rsults is called by onResume(added) which will notify the adapter that the data has been changed.
The code hasn't been tested as there was insufficient code. (a no code for DatabaseHandler class, and b) no code for DetailsTeacherwebservice class). As such there may be errors.
Look for //++++++++++++++... comments should follow to say what has been done/changed.
public class MainActivity extends Activity {
int attentedncemarkedCount = 0;
TextView addteacher;
DatabaseHandler databasehandler;
DetailsTeacherwebservice details;
String emis;
ArrayList<DetailsTeacherwebservice> addas = new ArrayList<DetailsTeacherwebservice>();
CustomAdapterTeacherWebservice cusadapter;
ArrayList<DetailsTeacherwebservice> teacherList;
private ListView listcontent = null;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teacherwebservicemainlist);
addteacher = (TextView) findViewById(R.id.addteachermenu);
databasehandler = new DatabaseHandler(TeacherWebserviceMainList.this);
listcontent = (ListView) findViewById(R.id.teacher_list);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//MOVED On ItemClickListener block FROM Rsults to here.
listcontent.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
});
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
}
// Probably don't even need onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if (update.equals("1")) {
//cusadapter.
//CustomAdapterTeacherWebservice adapter = new CustomAdapterTeacherWebservice(this, addas);
//+++++++++++++++++++++++++++++++++++
// Commented out
//listcontent.setAdapter(adapter);
}
}
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Added onResume to call Rsults
#Override
public void onResume() {
super.onResume();
Rsults();
}
private void Rsults() {
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ADDED 4 lines to see if the notifyDataSetChanged is required
boolean notifydschg_needed = false;
if (cusadapter != null) {
notifydschg_needed = true;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// YOU NEED TO GET THE TEACHER LIST AGAIN AS THE DB HAS CHANGED
teacherList = databasehandler.teacherwebserviceList(emis);
addas.clear();
//DatabaseHandler databaseHandler=new DatabaseHandler(this);
//ArrayList<ArrayList<Object>> data = databaseHandler.abcTeacherNew();
for (int p = 0; p < teacherList.size(); p++) {
details = new DetailsTeacherwebservice();
//ArrayList<Object> baris = data.get(p);
details.setId(teacherList.get(p).getId());
details.setTeachername(teacherList.get(p).getTeachername());
details.setTeachercnic(teacherList.get(p).getTeachercnic());
details.setTeacherno(teacherList.get(p).getTeacherno());
details.setTeachergender(teacherList.get(p).getTeachergender());
details.setAttendance(teacherList.get(p).getAttendance());
details.setTeacherattendancedetails(teacherList.get(p).getTeacherattendancedetails());
details.setAttendancedatesince(teacherList.get(p).getAttendancedatesince());
details.setAttendancetrasnferschool(teacherList.get(p).getAttendancetrasnferschool());
addas.add(details);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Just create the adapter and attach it to the listview once
if (cusadapter == null) {
cusadapter = new CustomAdapterTeacherWebservice(TeacherWebserviceMainList.this, addas);
listcontent.setAdapter(cusadapter);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Notify the adapter that the data has been changed
if(notifydschg_needed) {
cusadapter.notifyDataSetChanged();
}
}
}
// you have to set data in adapter in onResume method
#Override
protected void onResume() {
super.onResume();
}
You can use eventbus for this case:
This is an example:
In your build.gradle file
compile 'org.greenrobot:eventbus:3.0.0'
In Activity has listview:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this); // register event
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this); // unregister event
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(EventBusInfo eventBusInfo) {
if (eventBusInfo.getProcessId() == 99) {
// eventBusInfo.getData();
notifyDataSetChanged();
}
}
In Update Activity
yourButtonFinish.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finish();
EventBusInfo event = new EventBusInfo();
event.setProcessId(99);
//event.setData(object) //if you want get data back
EventBus.getDefault().post(event);
}
});
Class EventBusInfo
public class EventBusInfo {
private int processId;
private Object data;
public EventBusInfo(int processId, Object data) {
this.processId = processId;
this.data = data;
}
public EventBusInfo() {
}
public EventBusInfo(int processId) {
this.processId = processId;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public int getProcessId() {
return processId;
}
public void setProcessId(int processId) {
this.processId = processId;
}
}
save the list items in every change then restart the Activity of adapter with intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) to close the old ListView.
Is what I do and it works fine.
if the list it is not empty, I restart the activity with the adapter and I have a new ListView closing the previous one. Or if it is empty, I start a different activity (to not have an empty ListView)
Saving and loading the list items every time to SharedPreferences with Gson
For a reason notifyDataSetChanged() does not work good in my case so I prefer this solution.
I'm working on a simple log app that lets the user enter a time and a note, and then displays the entered data in a ListView in a dedicated activity (MainActivty). The time and data are entered in a separate activity (AddTimeActivity) with two EditText's and are passed to MainActivity when tapping the save button through an adapter (TimeTrackerAdapter). Alternatively, a cancel button can be pressed when the user changes their mind. The AddTimeActivity can be accessed through an add button in the action bar default menu. Now I've added a delete button -which is working fine- and an edit button to each row in the list. Now The problem is: How can I add the editing feature without making a new activity dedicated to editing. In Other words, how can I make the AddTimeActivity work with editing and adding in the same time, how can I make my app know that the user tapped the add button and start the AddTimeActivity with empty EditText's, or the user tapped the edit button in one of the rows in the list and passes the the data to be edited to AddTimeActivity and displays them in the EditText's and saves the edited data in the same entry? Sorry for not showing any attempts but I'm actually clueless about the issue.
MainActivity.java
public class MainActivity extends AppCompatActivity {
public TimeTrackerAdapter timeTrackerAdapter;
public int TIME_ENTRY_REQUEST_CODE = 1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.time_list);
timeTrackerAdapter = new TimeTrackerAdapter();
listView.setAdapter(timeTrackerAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
super.onCreateOptionsMenu(menu);
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_main, menu);
return true;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TIME_ENTRY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
String time = bundle.getString("time");
String note = bundle.getString("note");
TimeRecord timeRecord = new TimeRecord(time, note);
timeTrackerAdapter.addTimeRecord(timeRecord);
timeTrackerAdapter.notifyDataSetChanged();
}
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
// noinspection SimplifiableIfStatement
if (id == R.id.add_time_item) {
Intent intent = new Intent(getApplicationContext(), AddTimeActivity.class);
startActivityForResult(intent, TIME_ENTRY_REQUEST_CODE);
return true;
}
else if (id == R.id.about) {
Intent aboutIntent = new Intent(getApplicationContext(), AboutScreen.class);
startActivity(aboutIntent);
}
return super.onOptionsItemSelected(item);
}
}
The AddTimeActivity, onSave and onCancel are the buttons' methods:
public class AddTimeActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_time);
}
public void onCancel(View view) {
finish();
}
public void onSave(View view) {
Intent intent = new Intent(AddTimeActivity.this, MainActivity.class);
EditText timeEditText = (EditText) findViewById(R.id.Time_Edit_Text);
String time = timeEditText.getText().toString();
EditText noteEditText = (EditText) findViewById(R.id.Note_Edit_Text);
String note = noteEditText.getText().toString();
intent.putExtra("time", time);
intent.putExtra("note", note);
this.setResult(RESULT_OK, intent);
finish();
}
}
TimeTrackerAdapter.java:
public class TimeTrackerAdapter extends BaseAdapter {
public ArrayList<TimeRecord> times = new ArrayList<TimeRecord>();
#Override
public int getCount() {
return times.size();
}
public TimeTrackerAdapter() {
times.add(new TimeRecord("12:30", "this is the best"));
times.add(new TimeRecord("2:30", "I need this"));
}
#Override
public Object getItem(int position) {
return times.get(position);
}
public void addTimeRecord(TimeRecord timeRecord) {
times.add(timeRecord);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
view = inflater.inflate(R.layout.menu_layout, parent, false);
}
TextView timeView = (TextView) view.findViewById(R.id.time_textView);
TextView noteView = (TextView) view.findViewById(R.id.note_TextView);
Button deleteButton = (Button) view.findViewById(R.id.delete_entry);
deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
times.remove(position);
notifyDataSetChanged();
}
});
TimeRecord time = times.get(position);
timeView.setText(time.getTime());
noteView.setText(time.getNote());
return view;
}
}
The question is
How can I add the editing feature without making a new activity dedicated to editing.
or, more generally,
"how do I hand over information to the activity I'm calling ?"
You achieve this by adding extras to the intent which you use to start the activity. For example, in your 'MainActivity' before calling 'startActivityForResult()':
Intent intent = new Intent(this, MyOtherActivity.class);
// in your case, 'extraInformation' could be a boolean (add = yes|no)
intent.putExtra("MyExtraInformationKey", extraInformation);
startActivityForResult(intent,TIME_ENTRY_REQUEST_CODE);
Then in the 'onCreate()' method of the other activity, you question the intent for extras:
Intent i = getIntent();
if (i != null && i.hasExtra(getString("MyExtraInformationKey"))
{
boolean myInfo = i.getBooleanExtra("MyExtraInformationKey");
// proceed as appropriate...
}
For your case of buttons inside ListView rows, you could make the OnClickListener method call another method (like 'doCallMayOtherActivity()') in your 'MainActivity', handing over all relevant information (like the position in the 'times' ArrayList).
This method would then start your add/edit activity, passing the old data out of 'times.get(position)' in a bundle as an extra to the intent.
To access the methods in 'MainActivity' from your adapter class, you could use the following code in 'getView()'
Button editButton=(Button) view.findViewById(R.id.edit_entry);
editButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity)parent.getContext()).doCallMyOtherActivity(times.get(position));
}
This way, your other activity could check for the existence of that bundle. If there is none, you have a case of 'add'. Else, you have a case of 'edit'.
//imports
public class MainActivity extends Activity implements OnCheckedChangeListener
{
int count=0,ints......;
TextView textviews...;
int itemCode,month;
ArrayList<String> Name = new ArrayList<String>();
AlertDialog alertDialog ;
SharedPreferences sp;
EditText EtItemCode;
Editor editor ;
RadioButton RbForItemCode,RbForItemName;
RadioGroup RgForItemVsName;
PopupWindow popupWindowItems;
String popUpItems[];
ProgressDialog pDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
//shared prefs
sp = this.getSharedPreferences("MySharedPrefsFile", Context.MODE_PRIVATE);
editor = sp.edit();
intForShardPref= sp.getInt("NEW_INSTALLATION",1); // getting Integer(1 is for no)
if(intForShardPref==1){
Intent intent = new Intent(this,Verify.class);
startActivityForResult(intent, 1);
}
else{
//do nothing
}
EtItemCode.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
ToCheckItemCodeOfEdittext = EtItemCode.getEditableText().toString();
DatabaseHandler db=new DatabaseHandler(MainActivity.this);
List<Item> Items = db.getAllItemWithSubString(ToCheckItemCodeOfEdittext,itemNumberOrNameSelectedInRadioButtonOptions);
if(EtItemCode.length()>2){
if(EtItemCode.length()>3||flagForPopUpWindow>EtItemCode.length())
popupWindowItems.dismiss();
Name.clear();
for (Item cn : Items) {
if(RbForItemCode.isChecked()==true){
Name.add(Integer.toString(cn.getItemNumber()));
}
else{
Name.add(cn.getName());
}
}
popUpItems = new String[Name.size()];
Name.toArray(popUpItems);
popupWindowItems = popupWindowItems();
***popupWindowItems.setFocusable(false);***
popupWindowItems.showAsDropDown(findViewById(R.id.et_item_code), -5, 0);
}
else{
if(flagForPopUpWindow==3&&EtItemCode.length()==2)
popupWindowItems.dismiss();
}
flagForPopUpWindow=EtItemCode.length();
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
});
}
private void init() {
// TODO Auto-generated method stub
//some code
}
public PopupWindow popupWindowItems() {
// initialize a pop up window type
PopupWindow popupWindow = new PopupWindow(this);
// the drop down list is a list view
ListView listViewItems = new ListView(this);
// set our adapter and pass our pop up window contents
ArrayAdapter<String> adapter=new ArrayAdapter<String>(
this, //context for activity
android.R.layout.simple_list_item_1, //layout used
Name){ //Items to be displayed
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// setting the ID and text for every items in the list
String item = getItem(position);
String text = item.toString();
// visual settings for the list item
TextView listItem = new TextView(MainActivity.this);
listItem.setText(text);
//listItem.setTag(id);
listItem.setTextSize(22);
listItem.setPadding(10, 10, 10, 10);
listItem.setTextColor(Color.WHITE);
return listItem;
}
};
listViewItems.setAdapter(adapter);
// set the item click listener
listViewItems.setOnItemClickListener(new ItemsDropdownOnItemClickListener());
// some other visual settings
//popupWindow.setFocusable(true);
popupWindow.setWidth(EtItemCode.getWidth());
//popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
Rect r = new Rect();
View rootview = this.getWindow().getDecorView(); // this = activity
rootview.getWindowVisibleDisplayFrame(r);
popupWindow.setHeight(r.height()-3*EtItemCode.getHeight());
// set the list view as pop up window content
popupWindow.setContentView(listViewItems);
return popupWindow;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater blowUp = getMenuInflater();
blowUp.inflate(R.menu.cool_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.phone_number:
Intent p = new Intent(MainActivity.this,PhoneNumber.class);
startActivity(p);
break;
case R.id.exit:
finish();
break;
}
return false;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
//some code
}
class LoadDataBase extends AsyncTask<String, String, String>{
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog.setMessage("DataBase Loading..");
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
DatabaseHandler db = new DatabaseHandler(MainActivity.this);
Log.d("Reading: ", "Reading all Items..");
List<Item> Items = db.getAllItem();
//some code
//DatabaseHandler db1 = new DatabaseHandler(this);
count= db.getItemCount();
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
}
}
public class ItemsDropdownOnItemClickListener implements OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> arg0, View v, int arg2, long arg3) {
Toast.makeText(MainActivity.this, "Item is: ", Toast.LENGTH_SHORT).show();
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(EtItemCode.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
// dismiss the pop up
popupWindowItems.dismiss();
// get the text and set it as the button text
String selectedItemText = ((TextView) v).getText().toString();
Toast.makeText(MainActivity.this, "Item is: " + selectedItemText, Toast.LENGTH_SHORT).show();
DatabaseHandler db =new DatabaseHandler(MainActivity.this);
Item item= new Item();
if(RbForItemCode.isChecked()==true){
item = db.getItem(Integer.valueOf(selectedItemText));
}
else if(RbForItemName.isChecked()==true){
item = db.getItem(selectedItemText);
}
itemCode=item.getItemNumber();
}
}
#Override
public void onCheckedChanged(RadioGroup arg0, int arg1) {
// TODO Auto-generated method stub
if(RbForItemCode.isChecked()==true){
itemNumberOrNameSelectedInRadioButtonOptions="id";
//some code
}
}
else if(RbForItemName.isChecked()==true){
//some code
}
}
}
This code is working fine on my phone galaxy note 2(custom rom of note 4.. Android 4.4.4).By fine I mean I can type in edittext and popupwidow shows up after 3rd text(because of condition I have put) and I can select an option from the popupwindow. When I try to run the code on any other phone like galaxy grand then callback to ItemsDropdownOnItemClickListener is not registered and I can only scroll the popupwindow and keep on typing in edittext but cannot select any of the options in the popupwindow. If I set popupWindowItems.setFocusable(false) to true i.e popupWindowItems.setFocusable(true), and then as soon as I type 3rd letter in edittext,edittext looses focus and popwindow gains it. Now I can select anything.. But now I cannot continue to type in edittext.I have to manually select edittext and type.
Now I want that after tying 3rd word in edittext a popupwindow should appear(which currently is appearing) and edittext doesn't loose focus(so that i can continue typing).. Further if I select anything from popupwindow ,ItemsDropdownOnItemClickListener should be called which is currently being not called in other phones when popupWindowItems.setFocusable(false);
I am doing this to load data from sqlite database and show in popupwindow once the user types 3rd word. Any suggestion is recommended
Edit: Problem solved. Now using AutoComplete TextView
Mainactivity where I check the clicking of the refresh button
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Will close the drawer if the home button is pressed
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
switch (item.getItemId()) {
case R.id.search:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
return false;
} else {
// Legacy search mode for Eclair
onSearchRequested();
return true;
}
case R.id.refresh:
startDownloadSchedule();
// TODO: resolve this
Toast.makeText(getApplication(), "Updating database", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
private void startDownloadSchedule() {
progressBar.clearAnimation();
progressBar.setIndeterminate(true);
progressBar.setProgress(100);
progressBar.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_out));
progressBar.setMax(100);
progressBar.setVisibility(View.VISIBLE);
//JsonToDatabase gets data from google sheets in json format and then saves it in a database
JsonToDatabase dataDownload = new JsonToDatabase(getApplicationContext());
dataDownload.setOnJsonToDatabaseCallback(new JsonToDatabase.JsonToDatabaseCallback() {
#Override
public void onDataLoaded() {
Toast.makeText(getApplication(), "done updating", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
TracksListFragment tracksListFragment1 = new TracksListFragment();
tracksListFragment1.onCreate(new Bundle());
}
});
dataDownload.startDataDownload();
}
TracklistFragment.class ( this is the activity whose data I want to refresh)
public class TracksListFragment extends SmoothListFragment {
//public String[] columns;
//public int[] to;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
displaydata();
}
public void displaydata() {
String[] columns = new String[]{DatabaseHelper.TABLE_COLUMN_NAME, DatabaseHelper.TABLE_COLOUMN_INFORMATION};
// THE XML DEFINED VIEWS WHICH THE DATA WILL BE BOUND TO
int[] to = new int[]{R.id.textView_track_title, R.id.textView_track_information};
DatabaseManager db = DatabaseManager.getInstance();
if (getActivity() != null) {
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(
getActivity(), R.layout.list_tracks, db.getTracks(), columns, to, CursorAdapter.NO_SELECTION);
setListAdapter(mAdapter);
Toast.makeText(getActivity(),"display data",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String text = ((TextView) v.findViewById(R.id.textView_track_title)).getText().toString();
Intent intent = new Intent(getActivity(), TrackActivity.class);
intent.putExtra("TRACK", text);
startActivity(intent);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setEmptyText("No data present");
}
}
I am just stuck at how to display the new refreshed data. I have checked that the data gets downloaded. Any help would be appreciated. Thanks in advance.
Version the database. Add SharedPreferences for the database and increment it each time new data is added, then Call updateDb from Open helper.
In my app I get a Force Close, and I don't know how to solve this. The problem is that I have a class that extends ListActivity. In this class there is a list of shops, and the user should select one of the shops. If he not select a shop and press button Back I get Force Close, because the previous class expect the name of the shop. How can I catch this error?
Here is my class for selecting a shop :
public class SelectShop extends ListActivity {
private ListView lv1;
SimpleCursorAdapter adapter = null;
Cursor cursor;
DbAdapter db;
ImageView iconshop;
private static final int ADD=Menu.FIRST;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shopselect);
iconshop = (ImageView) findViewById(R.id.iconshop);
lv1 = getListView();
DbApplication myApplication = (DbApplication) this.getApplication();
db= myApplication.getDatabaseAdapter();
cursor = db.getAllShops();
startManagingCursor(cursor);
if (cursor != null && cursor.moveToFirst()){
adapter = new SimpleCursorAdapter(this, R.layout.shopsrow, cursor,
new String[] { DbAdapter.NAME, DbAdapter.ADRESS }, new int[] {
R.id.title, R.id.address });
setListAdapter(adapter);
}else Toast.makeText(this,
"Choose Menu for adding a shop",
Toast.LENGTH_LONG).show();
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Intent j = new Intent(SelectShop.this,
com.ShoppingList.NewList.class);
Cursor c = (Cursor) parent.getAdapter().getItem(position);
j.putExtra("shop", c.getString(c.getColumnIndex(db.NAME)));
setResult(RESULT_OK, j);
finish();
}
});
}
/*Adaugarea meniului Add Shop*/
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, ADD, 0, "Add Shop").setIcon(R.drawable.additem);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case ADD:
Intent j = new Intent(SelectShop.this, Shops.class);
startActivityForResult(j, 0);
return true;
}
return false;
}
}
and in previuos class I have this:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
switch (requestCode) {
case 0: {
Bundle b = intent.getExtras();
shopselect = b.getString("shop");
shop.setText(shopselect);
}
break;
}
}
You have to check the null condition in onActivityResult like below.
if(b != null)
{
shopselect = b.getString("shop"); shop.setText(shopselect);
}
I think you need to implement a mechanism that won't let your user get back to previous activity without choosing any item in the list. Override your onKeyDown() method, and when the user presses Back key you should check whether any item is chosen. If it's not you can throw an alert dialog to inform user what he must do to proceed. Hope this helps!
Check the result code. do your thing only if the result code is Activity.RESULT_OK.