I have a listview of shopping lists in a fragment and when I click one I get a new activity that shows a listview with all the products in the clicked shopping list. What I am trying to do is to add products this list by selecting some checkboxes in the newly created activity and pass them to the previous activity.
public class DisplayShoppingListDetailsActivity extends AppCompatActivity{
private ShoppingList list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//defines the activity layout
setContentView(R.layout.shopping_list_details);
ListView listView = (ListView) findViewById(R.id.shopping_list_details);
Intent intent = getIntent();
list = (ShoppingList) intent.getSerializableExtra("ShoppingList");
ProductsOnListAdapter ad = new ProductsOnListAdapter(this, -1, Service.getService().getProductsOnList(list));
listView.setAdapter(ad);
FloatingActionButton button = (FloatingActionButton) findViewById(R.id.floatingButton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivityForResult(new Intent(DisplayShoppingListDetailsActivity.this, ListOfProductsActivity.class));
//This method here is not working...it says it cannot resolve the method
}
});
}
You really should not have one activity try to modify another activity's instance. That will lead to bugs in your code.
Instead, in the first activity, you can use startActivityForResult() to launch the second activity, then the second activity can use setResult() to return data to the first activity. This is all documented if you read the javadoc for Activity under the heading "Starting Activities and Getting Results".
Related
I have an Activity with a ListView (ItemsActivity) which its contents come from a JSON API. When I press in one item in the ListView it loads another Activity with the details information (DetailActivity) . The problem is, when I press the Back Button, ItemsActivity reload the ListView again.
I don't know where I can find more information about this. I came from iOS where the previous screen is not reload every time.
I want to keep the ListView data between activities. I tested to call loadListItems() method from onResume() but same result.
Here is and brief sample of my code. Any help and suggestions will be really appreciated.
/* ItemsActivity.java */
public class ItemsActivity extends AppCompatActivity {
private ListView listItemView;
private Movie[] movies;
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler);
listItemView = (ListView) findViewById(R.id.listItemView);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
loadListItems();
}
private void loadListItems(){
// Http call
...
// Iterate JSON and saving to movies array
...
progressBar.setVisibility(INVISIBLE);
ListAdapter adapter = new ListAdapter(ItemsActivity.this, movies);
listItemView.setAdapter(adapter);
}
/* Adapter Class */
#Override
public void onClick(View v) {
Intent i = new Intent(this, DetailActivity.class);
i.putExtra("item_id", 1);
startActivity(i);
}
}
I just tested with a new Project with 2 Activities, ActivityOne and ActivityTwo. ActivityOne have a button, when a pressed its load ActivityTwo and when I press the back button, in ActivityOne the method onCreate() is called again.
You mentioned that "I tested to call loadListItems() method from onResume() but same result." This onResume() code is culprit.
OnResume() will get called whenever your activity gets focus again. If you are calling loadListItems() in onResume() then it will get called everytime you come back from your second activity to this activity.
http://developer.android.com/reference/android/app/Activity.html#onResume()
A solution is to use StartActivityForResult and not StartActivity. Then in the second activity, override the onBackPressed method and finish() the second activity within this method. Override the onActivityResult method in your first activity and this activity will be called and not the onCreate method and the ListView will not be reloaded.
The problem was only when I pressed the back button from Action Bar and I fix it with onOptionsItemSelected method.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
On button click event I'm using setContentView(R.layout.activity_main); it works correctly.
When if I try to start new activity with Intent and startactivity commands it loads layout twice it looks like layout loading correctly then 1 second same layout loaded again.
Before start activity its loaded single time.
show.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
String selected = spinner0.getSelectedItem().toString();
if(selected.equals("Item 2"))
{
Intent intent = new Intent(second_layout.this,MainActivity.class);
setContentView(R.layout.activity_main);
startActivity(intent);
}
}
});
I'm guessing this line is the problem.-
setContentView(R.layout.activity_main);
setContentView will just change the layout for the current activity, so you're changing the current layout to activity_main, and then you open the Intent for MainActivity class.
Just remove that line.
When you are starting a new activity, there is no need of setContentView while starting the intent.
The intent which is getting started will have the code for loading the layout. So please remove this line.
I hope, in your MainActivity.class, you will already be writing setContentView(R.layout.activity_main) and this is enough for showing the required layout. So remove this extra line which you have included while starting the intent.
You can not set your second activity layout in your first activity before starting your second activity. It will set automatically in your second activity's onCreate() method. So you should write setContentView(R.layout.activity_main); in your MainActivity's onCreate() method. Just remove it from the onClick listener.
So write in your onClick as below:
show.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
String selected = spinner0.getSelectedItem().toString();
if(selected.equals("Item 2"))
{
Intent intent = new Intent(second_layout.this,MainActivity.class);
startActivity(intent);
}
}
});
And in your MainActivity you have to set your layout as below:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
I'm getting an app together that basically displays database information nicely.
Main activity:
public class MainActivity extends FragmentActivity {
public static List<Entry> entryTitles;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MySQLiteHelper db = new MySQLiteHelper(this);
entryTitles= db.getEntryTitles();
.....
}
....
}
Fragment for navigation drawer
public class PositionsFrag extends Fragment {
public static EntryListAdaptor entryAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
int i = getArguments().getInt(ARG_ENTRY_NUMBER);
switch(i){
case 0:
entryAdapter = new EntryListAdapter(getActivity(), MainActivity.entryTitles);
lv.setAdapter(entryAdapter);
break;
.....
}
}
}
And finally, clicking on one of the action bar buttons opens a new activity to allow the user to add fields to a new entry. The 'done' action bar button in this new activity (creatively called NewActivity.java) should - in theory - create a new Entry object, add this new object into the Entries database, store the first element of each entry as a string into a new list and notify the entryAdapter that the List has been updated.
public class NewActivity extends Activity {
db = new MySQLiteHelper(this);
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.action_done:
db.newEntry(new Entry(title, date, location));
MainActivity.entryTitles= db.getEntryTitles();
PositionsFrag.entriesAdapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), db.printFirstTitle(), Toast.LENGTH_SHORT).show();
finish();
....
}
}
}
When I run this the toast correctly displays the first entry's title field (showing that the database is at least getting the new entry and that I have successfully written an SQLite read function) but the ListView in the PositionFragment never changes.
Any guidance on how to get this to work or suggestions of better structure would be greatly appreciated.
Cheers!
It looks like you are trying to refresh an UI element owned by another Activity (PositionsFrag.entriesAdapter.notifyDataSetChanged();), which is something you shouldn't do. You can start NewActivity with startActivityForResult() and wait for the add result in onActivityResult(), where you can safely call entriesAdapter.notifyDataSetChanged();
I have 3 tabs in my sample application with activity group. First tab contains search activity i.e.Home/Root activity and am displaying the results of search in another activity but under same tab i.e Tab1. When I press back button in result activity, it is going to search activity. Everything works fine till here. Now I want to go search activity by pressing tab1 instead of pressing back button. How can achieve this? I tried something like this
public class TabSample extends TabActivity {
public TabHost tabHost;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("OPT")
.setContent(new Intent(this, TabGroup1Activity.class)));
tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("EDIT")
.setContent(new Intent(this, TabGroup2Activity.class)));
tabHost.setCurrentTab(1);
tabHost.setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String arg0) {
if (tabHost.getCurrentTabTag().equals("tab1")) {
//What should I do to display search activity here
} else {
tabHost.setCurrentTab(1);
}
}
});
tabHost.setFocusable(true);
tabHost.requestFocus();
}
}
Can anyone please help let me know how to invoke search activity when tab is pressed? What will go into if part? Because if I use tabHost.setCurrentTab(index), it will display result activity but not search activity.
NOTE: I followed the tutorial given in this link.
I think what you want to do is this: when the 'tab1' tag is selected, go back to TabGroup1Activity if (and only if) the current activity is not that activity (basically you want to simulate a 'back' press).
If so, what you want is this:
if (getCurrentActivity().getClass() != TabGroup1Activity.class)
getCurrentActivity().finish()
I'm not 100% sure I understand you fully, but let's see :)
In your onTabChanged listener you can switch on which tab have been tabed, and then open the activity as normal inside an activitygroup:
public void onTabChanged(String tabId) {
if (tabId.contentEquals("tab1")) {
Intent intent = new Intent(tabHost.getContext(), TabGroup1Activity.class);
View view = StartGroup.group.getLocalActivityManager().startActivity("tab1", intent).getDecorView();
StartGroup.group.setContentView(view);
}
}
I just reviewed my code and think there's a bit more to explain here. The problem is that you don't stack activities as normal. Instead the workaround is to make a content stack and change these instead. So what I have done is to create a class StartGroup which extends
ButtonHandlerActivityGroup:
public class StartGroup extends ButtonHandlerActivityGroup {
// Keep this in a static variable to make it accessible for all the nested activities, lets them manipulate the view
public static StartGroup group;
// Need to keep track of the history if you want the back-button to work properly,
// don't use this if your activities requires a lot of memory.
private ArrayList<View> history;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.history = new ArrayList<View>();
group = this;
// Start the root activity within the group and get its view
View view = getLocalActivityManager().startActivity("UserList", new Intent(this, UserList.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)).getDecorView();
replaceView(view);
}
public void back() {
if (history.size() > 0) {
// pop the last view
history.remove(history.size()-1);
setContentView(history.get(history.size()-1));
} else {
finish();
}
}
}
Then from the TabMaster class or what you call it you can use the StartGroup class to change the content view of an activity group.
This is something I wrote to work on devices from 2.2, so there might be an easier and more androidish way to accomplished it, but this works on almost all devices :)
Here is another thread where the use a similar approach:
Launching activities within a tab in Android
Let me know if I can help more.
There is an ArrayList in your ActivityGroup so override onPause() method in ActivityGroup and remove all the ids from ArrayList except the first one which must be your SearchActivity.
So when you go to other tab then comes back to SearchActivity( or on Tab1 ) Home will be displayed.
I have TabActivityGroup:
MainActivity class contain some tab, that name loading from db. Sales, Admin, Inquiry like wise I have tab name
For Sales I created SalesActivityGroup.That class is :
public class SalesActivityGroup extends ActivityGroup {
public static SalesActivityGroup group;
private ArrayList<View> history;
private LocalActivityManager mActivityManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.history = new ArrayList<View>();
group = this;
mActivityManager = getLocalActivityManager();
Intent i = new Intent(getBaseContext(), SalesRouteActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("positions", -1);
i.putExtras(bundle);
View view = mActivityManager.startActivity("Sales",i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP )).getDecorView();
replaceView(view);
}
public void replaceView(View v) {
history.add(v);
setContentView(v);
}
public void back(){
if ( history.size() > 1 ){
history.remove(history.size() - 1);
View v = history.get(history.size() - 1);
setContentView(v);
}
else {
this.finish();
}
}
#Override
public void onBackPressed() {
SalesActivityGroup.group.back();
}
}
SalesRouteActivity is first Activity .In there i want to set up the title name.I did using this ways.But not working
public class SalesRouteActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.sales_routes);
//getWindow().setTitle("Route");
View viewToLoad = LayoutInflater.from(SalesActivityGroup.group).inflate(R.layout.sales_routes, null);
this.setContentView(viewToLoad);
//this.setTitle("Route");
//getWindow().setTitle("Route");
SalesActivityGroup.group.setTitle("Route");
}
}
Please advice me How can i set the Title name.
Thanks in advance
You can access the parent tab activity like
getParent().getParent().setTitle("New Tilte");
EXPLANATION:
Based on my understanding,
When you call the getParent the first time, you get the activity group that started the child activity.
When you call getParent the second time, you will get the tab activity that started the activity group.
setTitle should work for the activity window which is held by the tabactivity. The sub activities are rendered in the framelayout of the tab activity. So in the child activities access the parent tab activity to set the title.
The best way to do this is to implement the method
protected void onChildTitleChanged(Activity childActivity,CharSequence title) {
super.onChildTitleChanged(childActivity, title);
setTitle(title);
}
Implement this method in the parent activity. For example, In my case I have three activities.
Home Activity
Artists Activity
Album Activity
My Home activity contains a TabHost with Artists activity and Album activity.
I implemented the above method in the Home Activity. The title for Artists activity and Album activity is set in the OnResume methods of those respective activities.
It is not advisable to use ActivityGroup, it has been deprecated.
Refer to this link
Please use Fragment and FragmentManager using Compatibility Library