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'.
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.
Activity A has a listView , Activity B has a checkBox and save button.
When save button in B is clicked, it will return to Activity A. When the list in Activity A is pressed, how to show the check box is checked in Activity B if it is checked before return to A ?
Activity B
if(getIntent().getExtras()!=null) // when Activity A list is pressed
{
final String from = getIntent().getStringExtra("from");
travelFrom.setText(from);
// how to show check box is checked ?
}
save.setOnClickListener(new View.OnClickListener() { // if save button clicked, return from and outstation to A
#Override
public void onClick(View v) {
String from=travelFrom.getText().toString();
returnIntent.putExtra("from", from);
if(checkbox.isChecked()) {
returnIntent.putExtra("outstation", checkbox.getText().toString());
}
}
});
Activity A
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { // if listView is clicked
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
mClickedPosition = position;
Object o = listview.getItemAtPosition(position);
SearchResults fullObject = (SearchResults) o;
String from=fullObject.getFrom();
Intent i = new Intent(getApplication(),B.class);
i.putExtra("from",from);
startActivityForResult(i, PROJECT_REQUEST_CODE);
}
});
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { // receive from Activity B and populate ListView A
if (resultCode == RESULT_OK) {
if (requestCode == PROJECT_REQUEST_CODE) {
from=data.getStringExtra("from");
check=data.getStringExtra("outstation");
objMyCustomBaseAdapter.addNewItem(from,check); // save from and "outstation" into MySQL
}
}
}
When I press the list in A to B, the check box always not checked. How to make it check ?
Do something like implementing setOnclicklistner for checkbox. and assume an int variable to be zero. and when ever we click the checkbox increase the number by 1 every time. When we are moving from one activity to another send the data of int variable to Activity B. check Activity check the condition int variable as variable%2 if the value is equal to 1 the check box is checked. else it is not.
Assuming you have some object with this...
class MyData {
private boolean check;
public boolean getCheck() { return check; }
}
Here is some rough pseudo-code to demonstrate the concept, so not copy-paste worthy
Activity A - Pass in the boolean value that you want to the next activity
class ActivityA {
private ListView listView
onCreate() {
listView = (ListView) findViewById(R.id.list);
ArrayAdapter adapter = new ArrayAdapter();
listView.setAdapter(adapter);
listView.setOnItemClickListener( new ItemClickListener() {
onClick(int position) {
MyData listObject = adapter.getItem(position);
boolean checked = listObject.getCheck();
Intent i = new Intent(ActivityA.this, ActivityB.class);
i.putExtra("checkTheBox", check);
startActivity(i);
}
});
}
}
Activity B - Get the value out of the intent and set the checkbox to checked
class ActivityB {
private Checkbox checkbox;
onCreate() {
checkbox = (Checkbox) findViewById(R.id.checkbox);
Bundle extras = getIntent().getExtras();
if (extras != null) {
checkbox.setChecked(extras.getBooleanExtra("checkTheBox"));
}
}
}
You have to save the checked status for the selected list item when returning back from Activity B to Activity A.
In order to do that, you can simply store information in Activity A for the currently selected list item.
(for example TreeMap<View, Boolean> - item-> isSelected)
Then in onActivityResult you can set if there has been a check or not for the last selected item. When selecting again, before you create the intent you can check if this item has already been selected.
To know ActivityA ListItem is checked in ActivityB (ie CheckBox) or not. Check this below code hope this helps
ActivityA stuff
int selectedPosition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//your UI setup and findViewById stuff
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedPosition = position;
startActivityForResult(activityBIntent, REQ_CODE);
}
});
}
int REQ_CODE = 7;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_CODE)
if (resultCode == RESULT_OK) {
adapter.changeStatus(selectedPosition, true);//update adapter
} else {
//checkbox not checked
adapter.changeStatus(selectedPosition, false);//update adapter
}
}
ActivityB stuff
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//your UI stuff
setResult(RESULT_CANCELED);//default
//check box setup and save button onclick listener
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.save_button){
if (checkBox.isChecked())
setResult(RESULT_OK);
else
setResult(RESULT_CANCELED);//default
finish();//finish ActivityB and take the result to ActivityA
}
}
I have a notebook sample project and I want to add a "note counter" to it using shared preferences and each time the user adds a note increment the counter in createNote() method. I also added a TextView to show the counter, but the counter is always zero and doesnt increment by creating a new note! ! Help me please!
public class MainActivity extends ListActivity {
private static final int EDITOR_ACTIVITY_REQUEST = 1001;
private static final int MENU_DELETE_ID = 1002;
private int currentNoteId;
private NotesDataSource datasource;
List<NoteItem> notesList;
int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
datasource = new NotesDataSource(this);
refreshDisplay();
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText(""+count);
}
private void refreshDisplay() {
notesList = datasource.findAll();
ArrayAdapter<NoteItem> adapter =
new ArrayAdapter<NoteItem>(this, R.layout.list_item_layout, notesList);
setListAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_create) {
createNote(null);
}
return super.onOptionsItemSelected(item);
}
public void createNote(View v) {
NoteItem note = NoteItem.getNew();
Intent intent = new Intent(this, NoteEditorActivity.class);
intent.putExtra(NoteItem.KEY, note.getKey());
intent.putExtra(NoteItem.TEXT, note.getText());
startActivityForResult(intent, EDITOR_ACTIVITY_REQUEST);
int defaultValue = getPreferences(MODE_PRIVATE).getInt("count_key", count);
++defaultValue;
getPreferences(MODE_PRIVATE).edit().putInt("count_key", defaultValue).commit();
count = getPreferences(MODE_PRIVATE).getInt("count_key", count);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
NoteItem note = notesList.get(position);
Intent intent = new Intent(this, NoteEditorActivity.class);
intent.putExtra(NoteItem.KEY, note.getKey());
intent.putExtra(NoteItem.TEXT, note.getText());
startActivityForResult(intent, EDITOR_ACTIVITY_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == EDITOR_ACTIVITY_REQUEST && resultCode == RESULT_OK) {
NoteItem note = new NoteItem();
note.setKey(data.getStringExtra(NoteItem.KEY));
note.setText(data.getStringExtra(NoteItem.TEXT));
datasource.update(note);
refreshDisplay();
}
}
}
Your help is appreciated. Thanks!
Based on discussion and answer given by #Rahul Tiwari...do the following modifications in your code.....
First create the instance TextView variable
//your instance variables
int count;
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
//your code...
tv = (TextView) findViewById(R.id.textView1);
count = getSharedPreferences("NAME_FOR_SHARED_PREFERENCES", Context.MODE_PRIVATE).getInt("count_key", 0);
updateTextView();
}
void updateTextView(){
tv.setText(""+count);
}
//your code till here....
public void createNote(View v) {
NoteItem note = NoteItem.getNew();
SharedPreferences sharedPref = getSharedPreferences("NAME_FOR_SHARED_PREFERENCES", Context.MODE_PRIVATE);
sharedPref.edit().putInt("count_key", ++count).commit();
updateTextView()
/*for intial testing commenting this code block
Intent intent = new Intent(this, NoteEditorActivity.class);
intent.putExtra(NoteItem.KEY, note.getKey());
intent.putExtra(NoteItem.TEXT, note.getText());
startActivityForResult(intent, EDITOR_ACTIVITY_REQUEST);
*/
}
//your code.
Then you can start app multiple times and check want is the count value.
Note: When naming your shared preference files, you should use a name
that's uniquely identifiable to your app, such as
"com.example.myapp.PREFERENCE_FILE_KEY" for more detail refer
your counter is not being refreshed as you are not changing text in your text view after changing the count.
you need to use
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText(""+count);
at the end of your createNote function
use getDefaultSharedPreferences to access your shared preference across activities in your app. refer this answer for example.
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.
i know this question has been asked a couple of times before and i tried all of the suggestions there and i still cant refresh my list view after i add a new item to the list
can anyone please try to explain how can i do it?
thnaks
this is the code of the adding:
public class MainActivity extends ListActivity {
private DBHandler dataBase;
private ArrayList<Movies> list;
private ArrayAdapter<Movies> adapter;
private ListView lv;
private ImageButton addMovie;
private Intent intent;
final static int FLAG_FOR_ADDING=1;
final static int FLAG_FOR_EDITING=2;
final static int FLAG_FROM_MENU=3;
private int selected_movie;
private String the_movie;
private String movie_title;
private String movie_description;
private String movie_url;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
dataBase = new DBHandler(MainActivity.this);
// by pressing this button the user will get instructions about how to use this application
Button start = (Button)findViewById(R.id.how_to_start);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Toast.makeText(MainActivity.this, "Press the plus button for adding a movie or the menu button for the menu", Toast.LENGTH_LONG).show();
}
});
// by pressing this button, the menu of this application will open
ImageButton menu = (ImageButton)findViewById(R.id.menu_context);
menu.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openOptionsMenu();
}
});
addMovie = (ImageButton)findViewById(R.id.add_movie);
addMovie.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
registerForContextMenu(addMovie);
openContextMenu(addMovie);
}
});
// the array list is getting the movies from the database
list = dataBase.getAllMovies();
// here i am setting the adapter that will handle the list
adapter = new ArrayAdapter<Movies>(MainActivity.this, R.layout.row,list);
// i am getting a default xml
lv=getListView();
// i am connecting between the list and the adapter
lv.setAdapter(adapter);
// by short pressing an item on the list the user will move to the edit_a_movie page
// in order to edit the movie
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
intent = new Intent(MainActivity.this,Edit_A_Movie.class);
// i am sending the information of the item that been pressed to the edit_a_movie page
// the id, title,description and the url_photo
intent.putExtra("item_id", list.get(position).getId());
intent.putExtra("item_title", list.get(position).getTitle().toString());
intent.putExtra("item_description", list.get(position).getDescription().toString());
intent.putExtra("item_url", list.get(position).getPhoto_url().toString());
startActivityForResult(intent, FLAG_FOR_EDITING);
}
});
// a long press on a movie in the list will open a context menu for deleting or editing the item
lv.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
// i am getting the information of the movie that was pressed
selected_movie = list.get(position).getId();
the_movie = String.valueOf(selected_movie);
movie_title = list.get(position).getTitle().toString();
movie_description = list.get(position).getDescription().toString();
movie_url = list.get(position).getPhoto_url().toString();
// i register to a context menu
registerForContextMenu(lv);
openContextMenu(lv);
return true;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
// by pressing the exit option, the user will exit the application
case R.id.menu_exit:
finish();
android.os.Process.killProcess(android.os.Process.myPid());
super.onDestroy();
break;
// this option will delete all the movies from the list
case R.id.menu_delete:
dataBase.deleteAllMovies();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
// if the user will press the menu button he will get the menu and if he will press
// the plus button he will get 2 options: 1. move to the edit a movie page
// 2. move to the search a movie from the Internet page
// if the user will press a long press on a movie he will get 2 options:
//1. update the movie
//2. delete the movie
if(v.getId() == R.id.menu_context){
getMenuInflater().inflate(R.menu.main, menu);
}
else if (v.getId() == R.id.add_movie){
getMenuInflater().inflate(R.menu.aad_menu, menu);
}
else {
getMenuInflater().inflate(R.menu.edit_or_delete, menu);
}
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()){
// selecting this option will exit the application
case R.id.menu_exit:
finish();
android.os.Process.killProcess(android.os.Process.myPid());
super.onDestroy();
break;
// this option will delete all the movies from the list
case R.id.menu_delete:
dataBase.deleteAllMovies();
break;
// this option will move the user to the edit a movie page
case R.id.move_to_edit:
intent = new Intent(MainActivity.this,Edit_A_Movie.class);
startActivityForResult(intent, FLAG_FOR_ADDING);
break;
// this option will get the user move to the add a movie from the Internet page
case R.id.move_to_search:
break;
// if the user will press on a movie he will be able to update the movie or delete it
//this option will delete the movie
case R.id.delete_menu_movie:
dataBase.deleteMovie(the_movie);
break;
// this option will move the user to the edit_a_movie page
case R.id.edit_menu_movie:
intent = new Intent(MainActivity.this,Edit_A_Movie.class);
// i am sending the information of the pressed movie
intent.putExtra("item_id",selected_movie);
intent.putExtra("item_title", movie_title);
intent.putExtra("item_description", movie_description);
intent.putExtra("item_url", movie_url);
startActivityForResult(intent, FLAG_FROM_MENU);
break;
default:
break;
}
return super.onContextItemSelected(item);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
// this is the info i am getting from the edit_a_movie page in order to put it in the database
// i am using it to add a new movie to the list
if(requestCode==FLAG_FOR_ADDING && resultCode==RESULT_OK){
// this is the info i received
String title_from_adding = data.getStringExtra("user_title");
String description_from_adding = data.getStringExtra("user_desciption");
String url_from_adding = data.getStringExtra("user_url");
// here i am putting the info in the database
dataBase.addMovie(title_from_adding, description_from_adding, url_from_adding);
// in case that the user pressed the cancel button he will get a massage
} else if
(requestCode==FLAG_FOR_ADDING && resultCode==RESULT_CANCELED){
Toast.makeText(MainActivity.this, "No movie has been added", Toast.LENGTH_LONG).show();
}
// i am using the info from the edit_a_movie page in order to update a movie
else if
(requestCode==FLAG_FOR_EDITING && resultCode==RESULT_OK ){
String position_from_editing = data.getStringExtra("position");
String title_from_editing = data.getStringExtra("user_title");
String description_from_editing = data.getStringExtra("user_desciption");
String url_from_editing = data.getStringExtra("user_url");
// the database is being updating
dataBase.updateMovie(position_from_editing, title_from_editing, description_from_editing, url_from_editing);
}
// this case is for editing the movie that was long pressed
else if
(requestCode==FLAG_FROM_MENU && resultCode==RESULT_OK){
// i am receiving the updated information from the edit_a_movie page
String position_from_menu = data.getStringExtra("position");
String title_from_menu = data.getStringExtra("user_title");
String description_from_menu = data.getStringExtra("user_desciption");
String url_from_menu = data.getStringExtra("user_url");
//the database is being updating with the new information
dataBase.updateMovie(position_from_menu, title_from_menu, description_from_menu, url_from_menu);
}
}
}
You should call notifyDataSetChanged on the adapter.
After dataBase.addMovie(..)
adapter.notifyDataSetChanged();