To start off I'm a beginner with this android programming.
My app has 2 activites defined in TabHost, hence Tab 1 and Tab 2.
In Tab 1 I receive an EditText input that I would like to show in tab 2 (activity 2) in a ListView.
For this I created a Custom ListView with this tutorial: http://www.ezzylearning.com/tutorial/customizing-android-listview-items-with-custom-arrayadapter
Now:
I pass the EditText value as a String with the help of an intent in tab 1, to tab 2.
//Intent to tab 2
Intent intent = new Intent(getBaseContext(), Tab2Activity.class);
intent.putExtra("values", streetName);
startActivity(intent);
In my Tab 2 (Tab2Activity) I receive this intent like this:
public void onResume (){
super.onResume();
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
if (bundle != null) {
updateData(bundle);
}
}
public void updateData (Bundle bundle) {
String data = bundle.getString("values");
Toast.makeText(this, data, Toast.LENGTH_LONG).show();
Bostad bostad_data[] = new Bostad[]{new Bostad (streetName, money)};
adapter = new BostadAdapter(this, R.layout.listview_item_row, bostad_data);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
...
}
I have two question (two problems).
1) I know that since I call "startActivity(intent) in Tab1 this will open up the activity and not in the tab. Is it possible to just switch tab and update the listView? (This isn't necessary. Only if it's an easy solution)
2) I get the activity with the right info up on my screen, but the listView in Tab2 isn't updated with this information. How can I fix this?
What I mean is, a row doesn't get added to the listview. What am I doing wrong?
Thanks for any help!
EDIT: Adding the onCreate in Activity2 as well.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab2);
//Create listView and connect to the .xml (activity_tab2)
listView = (ListView) findViewById(R.id.listView1);
//Arrayen which the list will receive values from
Bostad bostad_data[] = new Bostad[]{
new Bostad("", "")
};
adapter = new BostadAdapter(this, R.layout.listview_item_row, bostad_data);
View header = getLayoutInflater().inflate(R.layout.listview_header_row, null);
listView.addHeaderView(header);
listView.setAdapter(adapter);
...
}
Edit 2: Adding BostadAdapter.java
public class BostadAdapter extends ArrayAdapter<Bostad> {
Context context;
int layoutResourceId;
Bostad data[] = null;
public BostadAdapter(Context context, int layoutResourceId, Bostad[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
BostadHolder holder = null;
if(row == null) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new BostadHolder();
holder.gatunamn = (TextView)row.findViewById(R.id.gatunamn);
holder.totalkostnad = (TextView)row.findViewById(R.id.totalkostnad);
row.setTag(holder);
}
else {
holder = (BostadHolder)row.getTag();
}
Bostad bostad = data[position];
holder.gatunamn.setText(bostad.gatunamn);
holder.totalkostnad.setText(bostad.totalkostnad+" SEK per månad");
return row;
}
static class BostadHolder
{
TextView gatunamn, totalkostnad;
}
}
Edit 3: Adding Bostad.java
public class Bostad {
String gatunamn, totalkostnad;
public Bostad (){
super();
}
public Bostad (String gatunamn, String totalkostnad) {
super();
this.gatunamn = gatunamn;
this.totalkostnad = totalkostnad;
}
}
If I understand properly, I think what you are doing is creating a new activity that looks identical to tab 2 but isn't the same object. So that activity you start in startActivity() is the only one that gets the data. What I would suggest is using a ViewPager with fragments and interfaces to pass/update data from the parent activity. That may be a bit too advanced yet and it's not something you can easily write out as an answer, however there are a lot of tutorials on the process. As you're just starting out you may want to explore faster options but it is what I'd do.
A quick fix might be to access the tab host and replace the existing tab 2 activity with the activity you just made that has the data.
Related
I created a test project, and in that project I am trying to create a listview that the user can add to when they click a button. The button opens an new activity with an editText and another button to go back to the listview activity and an item should have been added. It works the first time, but when I add another Item it replaces the old one. I have search for a while now, and all the other answer don't seem to help me. Thanks in advance.
public class MainActivity extends Activity {
ListView simpleList;
String input;
ArrayList<Item> listItems =new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
simpleList = (ListView) findViewById(R.id.listView);
addData();
MyAdapter myAdapter=new MyAdapter(this,R.layout.row, listItems);
simpleList.setAdapter(myAdapter);
}
public void addData(){
Bundle extras = getIntent().getExtras();
if (extras != null) {
input = extras.getString("Homework");
listItems.add(new Item(input, input, input));
}
}
public void toInput(View view){
Intent intent = new Intent(this, inputScreen.class);
startActivity(intent);
}}
This is my main activity, the adapter is a custom adapter that is made in this class.
public class MyAdapter extends ArrayAdapter<Item> {
ArrayList<Item> listItems = new ArrayList<>();
public MyAdapter(Context context, int textViewResourceId, ArrayList<Item> objects){
super(context, textViewResourceId, objects);
listItems = objects;
}
public int getCount(){
return super.getCount();
}
public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.row, null);
TextView textView = (TextView) v.findViewById(R.id.homeworkDisplay);
TextView textView2 = (TextView) v.findViewById(R.id.dueDisplay);
TextView textView3 = (TextView) v.findViewById(R.id.classDisplay);
textView.setText(listItems.get(position).getHomework());
textView2.setText(listItems.get(position).getDate());
textView3.setText(listItems.get(position).getClasses());
return v;
}}
The string that is added to the listview is sent from the another activity that gets it from an editText, here is it's class
public class inputScreen extends Activity{
EditText userInput;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.input_screen);
userInput = (EditText) findViewById(R.id.editText);
}
public void sendInfo(View view){
Intent goingBack = new Intent(this,MainActivity.class);
goingBack.putExtra("Homework", userInput.getText().toString());
startActivity(goingBack);
}}
I know there is alot of code there, you don't need to go through it all as I am sure the problem is in MainActivity. I have another class called items that returns homework. Thank you!
Used startActivity() is not correct.
your activity stack is like this :
the start
~~~~~~~~~~~~
MainActivity
~~~~~~~~~~~~
after you call toInput in MainActivity()
~~~~~~~~~~~~
InputScreen(activity)
MainActivity
~~~~~~~~~~~~
then when you call send() in InputScreen
~~~~~~~~~~~~
MainActivity
InputScreen
MainActivity
~~~~~~~~~~~~
see what's happening?
the first time in InputScreen you called send() start MainActivity with extras
then you started a new MainActivity ,then went the addData() ,you got data, and changed listView.
but when you do it again , you always start new Activities ,so only the first one was gonna change
always repeat the first step always start a new activity
you should call startActivityForResult() in MainActivity to start inputScreen and override the onActivityResult method in MainActivity
just google startActivity and startActivityForResult you will work this out .
and anther key word you should google is ,listView --> data source
sorry,I am not a native English speaker, if I did something wrong ,please forgive me ~~~~
Written by: https://stackoverflow.com/users/2936153/rohit5k2
Source: Listview replaces first item instead of creating new items
Every time you call changeText() your adapter is reset so only one
item will be displayed
Change your fragment like this
public class ListViewFragment1 extends Fragment {
protected ArrayAdapter<String> adapter1;
ListView list1;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_view_fragment1, container, false);
adapter1 = new ArrayAdapter<String>(getActivity(), R.layout.items);
list1 = (ListView) view.findViewById(R.id.listview1);
list1.setAdapter(adapter1);
return view;
}
public void changeText(String data){
adapter1.add(data);
adapter1.notifyDataSetChanged();
}
}
I am an application, which is basically an empty activity (empty list-view) where in the toolbar there is an Add button, clicking the button takes you to another activity with two edit text fields and a button (to submit the activity, in other words send the intent extras to the first activity). I want to take those input (both are strings) from that activity and display them in the list-view in the first activity.
I have made the toolbar and the button, and placed the custom list-view with its adapter in the first activity, and in the second activity I created the necessary views and along with the intent (for passing the two strings).
The problem is, that in the second activity, when I pass the intent extras to the first activity, a new list-view gets created every time instead of appending the list-view.
Can someone help me append the intent extras rather than creating a new list every time the user adds the two inputs?
This is the onCreate method in the first activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_countries);
ActionBar actionBar = getActionBar();
if(actionBar != null)
actionBar.setDisplayHomeAsUpEnabled(true);
listView = (ListView) findViewById(R.id.listView);
populateList();
}
This is the populateList();
public void populateList(){
Bundle countryData = getIntent().getExtras();
if (countryData == null){
return;
}
String country = countryData.getString("country");
String year = countryData.getString("year");
ArrayAdapter<Country> adapter = new CustomAdapter();
listView.setAdapter(adapter);
countryList.add(new Country(country, year));
}
This is the adapter:
private class CustomAdapter extends ArrayAdapter<Country>{
public CustomAdapter() {
super(MyCountries.this, R.layout.list_item, countryList);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null){
view =getLayoutInflater().inflate(R.layout.list_item, parent, false);
}
Country currentCountry = countryList.get(position);
TextView countryText = (TextView) view.findViewById(R.id.countryName);
countryText.setText(currentCountry.getCountryName());
TextView yearText = (TextView) view.findViewById(R.id.yearOfVisit);
yearText.setText(currentCountry.getYear());
notifyDataSetChanged();
return view;
}
}
And this is the onClick() for submitting the input:
public void onClick(View v) {
String country = addCountry.getText().toString();
String year = addYear.getText().toString();
Intent result = new Intent(this, MyCountries.class);
result.putExtra("country", country);
result.putExtra("year", year);
startActivity(result);
}
Thank you very much.
Any help, or guidance will be greatly appreciated.
So I have 2 activities.
The first (ActivityOne) displays a listview with data from SQLite cursor, and a button.
On click of that button, I want to add an item to the listview, so I display the second activity (ActivityTwo), that contains a number of editTexts and a save Button, that does the saving in the Database.
But what I want is:
after saving the new item to the DB, the ActivityTwo should close and the ActivityOne should be displayed with the refreshed content from the DB
.
This seems a reasonable workflow. How do I achieve it?
Code for ActivityOne:
public class ActivityOne extends Activity {
private ArrayList<String> idclient = new ArrayList<String>();
private ArrayList<String> numeclient = new ArrayList<String>();
private ArrayList<String> tipclient = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView mylist = (ListView) findViewById(R.id.lv_clienti);
LoadList();
Button btnex = (Button) findViewById(R.id.btnNewCli);
btnex.setOnClickListener(
new View.OnClickListener()
{
public void onClick(View aView)
{
Toast.makeText(getApplicationContext(), "Add new client... " , Toast.LENGTH_SHORT).show();
Intent toAnotherActivity = new Intent(aView.getContext(), NewClientActivity.class);
startActivity(toAnotherActivity);
}
}
);
}
public void LoadList(){
SQLiteDatabase db = new myDbHelper(getApplicationContext()).getWritableDatabase();
Cursor mCursor = db.rawQuery("select idclient,nameclient,typeclient from clienti order by numeclient" , null);
idclient.clear();
numeclient.clear();
tipclient.clear();
if (mCursor.moveToFirst()) {
do {
idclient.add(Integer.toString(mCursor.getInt(0)));
nameclient.add(mCursor.getString(1));
typeclient.add(mCursor.getString(2));
} while (mCursor.moveToNext());
}
DisplayClientiAdapter disadpt = new DisplayClientiAdapter(ClientiActivity.this,idclient,nameclient, typeclient);
ListView lv = (ListView) findViewById(R.id.lv_clienti);
lv.setAdapter(disadpt);
mCursor.close();
db.close();
}
}
And in the ActivityTwo, I have in a button click:
db.execSQL("insert into clients (idclient, nameclient,typeclient,...");
DisplayClientiAdapter da = new DisplayClientiAdapter(getApplicationContext());
da.notifyDataSetChanged();
finish();
Also the displayAdapter is something like:
public class DisplayClientiAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> idclient;
private ArrayList<String> numeclient;
private ArrayList<String> tipclient;
public DisplayClientiAdapter(Context c){
this.mContext = c;
}
public DisplayClientiAdapter(Context c, ArrayList<String> idclient, ArrayList<String> numeclient, ArrayList<String> tipclient) {
this.mContext = c;
this.idclient = idclient;
this.numeclient = numeclient;
this.tipclient = tipclient;
}
public int getCount() {
return idclient.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int pos, View child, ViewGroup parent) {
Holder mHolder;
LayoutInflater layoutInflater;
if (child == null) {
layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
child = layoutInflater.inflate(R.layout.clienti_item, null);
mHolder = new Holder();
mHolder.txt_idclient = (TextView) child.findViewById(R.id.tv_cl_id);
mHolder.txt_numeclient = (TextView) child.findViewById(R.id.tv_cl_nume);
mHolder.txt_tipclient = (TextView) child.findViewById(R.id.tv_cl_tip);
child.setTag(mHolder);
} else {
mHolder = (Holder) child.getTag();
}
mHolder.txt_idclient.setText(idclient.get(pos));
mHolder.txt_numeclient.setText(numeclient.get(pos));
mHolder.txt_tipclient.setText(tipclient.get(pos));
return child;
}
public class Holder {
TextView txt_idclient;
TextView txt_numeclient;
TextView txt_tipclient;
}
Of course it does not work like this. The list is not refreshed... I assume it has to do with the displayAdapter !?!?!
I cannot call the LoadList method since it is static or something like that...
Please help.
Thank you
Its not a problem with your adapter. You have to call Loadlist() in onresume method instead of oncreate method in ActivityOne. It will work then.
First of all, have a look at this two articles:
http://www.doubleencore.com/2013/05/layout-inflation-as-intended/
http://www.doubleencore.com/2013/06/context/
You shouldn't inflate your views with null in your inflate method if you have parent view available.
Also, using application context for inflating may cause strange behaviour, as it may not use correct theme you may've set in app manifest for your Activity.
On the other hand - why don't you use CursorAdapter instead of BaseAdapter?
The problem with your adapter is, that you don't set the data in it! :)
///EDIT:
I checked the wrong activity - why do you create second adapter in there?
The easiest solution would be to move the LoadList() to onStart.
If you want to do it right, you should use ContentObserver and (probably) CursorAdapter.
I have a problem that is a little hard to explain. I am building an android application for trip planning. I have a main activity that contains the map item and some other buttons and an AsyncTask class where the communication with the server is done and the path is displayed on the map. I am trying to make it work offline by saving the response from the server in sqllite database.
I have an Activity called MainActivity. There, I have a method for menu items
public boolean onOptionsItemSelected(final MenuItem pItem) {
switch (pItem.getItemId()) {
case R.id.recent_trips:
startActivity(new Intent(this, recentTripsActivity.class));
break;
default:
break;
}
return false;
}
}
Here is the current method for calling the AsyncTask class
btnPlanTrip.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tripReq = new TripRequest(MainActivity.this,activityHandler,db);
tripReq.execute(request);
}
});
}
When I click on the recent_trips from the menu button, recentTripsActivity opens. Basically, in this class I retrieve some data from mysqllite database and present it on a listView through an adapter. There, I have a method view.setOnClickListener in which when a list item is clicked I take a certain value (res=listItem.getofflineResult();). I would like to use that value on Main Activity (see below for more details).
Here is the code.
public class recentTripsActivity extends Activity implements Serializable {
private ImageButton stopSearch;
private AutoCompleteTextView searchField;
SQLiteDatabase db;
OfflineTripRequest tripReq;
String res;
//db = openOrCreateDatabase("AndroidDatabase.db", SQLiteDatabase.CREATE_IF_NECESSARY, null);
private ListView listview;
private ArrayList mListItem;
ItemBO listItem;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recent_trips);
//open database connection
db = openOrCreateDatabase("AndroidDatabase.db", SQLiteDatabase.CREATE_IF_NECESSARY, null);
int i=0;
String [] str={"id","description","offlineResult"};
listview = (ListView) findViewById(R.id.lview_trips);
mListItem = new ArrayList<ItemBO>();
Cursor cursor = db.query("tbl_offlinePathResult",str, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
i++;
ItemBO listItem = new ItemBO(i,cursor.getString(1),cursor.getString(2));
mListItem.add(listItem);
cursor.moveToNext();
if(i==10){
break;
}
}
// Make sure to close the cursor
cursor.close();
i++;
listview.setAdapter(new ListAdapter(recentTripsActivity.this, R.id.lview_trips,mListItem));
db.close();
}
//***ListAdapter***
class ListAdapter extends ArrayAdapter { //--CloneChangeRequired
private ArrayList mList; //--CloneChangeRequired
private Context mContext;
#SuppressWarnings("unchecked")
public ListAdapter(Context context, int textViewResourceId,
ArrayList list) { //--CloneChangeRequired
super(context, textViewResourceId, list);
this.mList = list;
this.mContext = context;
}
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
try {
if (view == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.list_item_saved_paths, null); //--CloneChangeRequired(list_item)
}
final ItemBO listItem = (ItemBO) mList.get(position); //--CloneChangeRequired
if (listItem != null) {
// setting list_item views
((TextView) view.findViewById(R.id.tv_name))
.setText(listItem.getDescription());
view.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) { //--clickOnListItem
res=listItem.getofflineResult();
}
});
}
} catch (Exception e) {
Log.i(recentTripsActivity.ListAdapter.class.toString(), e.getMessage());
}
return view;
}
}
}
I would like to pass the data mentioned above(res=listItem.getofflineResult() to MainActivity. After doing that I would like to call an AsyncTask class and pass that data to that class. How can I do all this by clicking on the listItem? As I said before the map is on MainActivity but the click will happen from a different Activity.
I hope I made my self clear enough, If you have any questions please ask me
First, you need to override onListItemClick in your list. You will then need to put the needed information into a bundle and end the activity. This bundle gets "returned" to the calling activity in that activity's onActivityReuslt method (which you will need to override). See:
Passing Data Between Activities
I generally use a singleton method when passing data in an android app. If you are unfamiliar, it is basically a static class that always returns the same instance. This allows you to create multiple 'instances' of the class that all share the same data.
Singleton Design Pattern
Well you can pass the res (String?) in many ways, the simple is throw preferences:
SharedPreferences settings = context.getSharedPreferences(APPNAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("res", res);
editor.commit();
and then in MainActiviy get:
SharedPreferences settings = context.getSharedPreferences(APPNAME, 0);
res = settings.getString("res","");
You can also save in the local database, or like "tkcsam" says using a static and abstract variable.
public abstract Global{
public static String res;
}
and you can acess in any Activity like :
Global.res = "A"
I created a custom SimpleCursorAdapter, because i want a text and 2 buttons per row.
If i click on a button, he should call the Activity Lektion.
In this Lektion he should know from which Button the call came, so i thought about sending the id of the Lektion as a Bundle in the onClickEvent.
But this doesnt work, it just saves me always the last id..
How can i do this?
public class LektionenCursorAdapter extends SimpleCursorAdapter{
private Cursor c;
private Context context;
private Bundle bundle;
public LektionenCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.c = c;
this.context = context;
}
public View getView(int pos, View inView, ViewGroup parent){
if(inView == null){
inView = View.inflate(context, R.layout.lektionenoverview_entry, null);
}
View row = inView;
this.c.moveToPosition(pos);
String id = this.c.getString(this.c.getColumnIndex("_id"));
Log.i("Cursor", id);
String description = this.c.getString(this.c.getColumnIndex("Description"));
String info = this.c.getString(this.c.getColumnIndex("Info"));
String test = this.c.getString(this.c.getColumnIndex("Test"));
TextView descriptionTextView = (TextView)row.findViewById(R.id.description);
Button infoButton = (Button)row.findViewById(R.id.infoButton);
Button testButton = (Button)row.findViewById(R.id.testButton);
bundle = new Bundle();
bundle.putString("LektionNummer", id);
descriptionTextView.setText(id+". "+description);
if(info != null && info.length() > 0){
infoButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(context, Lektion.class);
intent.putExtras(bundle);
context.startActivity(intent);
}
});
}
if(test != null && test.length() > 0){
}
return row;
}
}
No need to use a CursorAdapter because you want to show 2 lines and button, you can use any other simpler adapter.
getView method is called multiple times for each view, not when you click on the view or button. You are re-instantiating the Bundle everytime and it is just saving the id for the last getView call (because every call destroys the previous one), and you are also creating a new OnClickListener on every call.
You probably want to use OnItemClickListener and create only one instance outside getView() method.