Android setShareIntent within fragment - android

1. Background
I have a screen that has a
ShareActionProvider
and a
ViewPager
that uses fragments.
What I was hoping to do was get some information from inside the currently visible fragment to create an intent, I would then be able to set the intent on the ShareActionProvider.
This is the code I use to set the intent of the ShareActionProvider:
MenuItem actionItem = men.getMenu().findItem(R.id.menu_item_share_action_provider_action_bar);
ShareActionProvider actionProvider = (ShareActionProvider) actionItem.getActionProvider();
actionProvider.setShareIntent(createShareIntent(mProduct.mProduct));
I have tried using this in several places such as within these functions of the Fragment class :
onCreateView
onStart
I have also tried using it in these functions within the FragmentPagerAdapter class :
getItem
2. The Problem
Although the intent is actually getting set within the ShareActionProvider, the information that is obtained is for the next fragment (the one not currently being shown). For example:
If I have 4 fragments : frag1, frag2, frag3, frag4
and I am currently viewing "frag1" the ShareActionProvider will attempt to share "frag2". This is true until it reaches "frag4" where it will share the correct value.
My guess is that the fragment pager creates the current view and the next view (hidden), which is in turn setting the ShareActionProvider. If this is the case then where is the correct place to "setShareIntent"?

I stumble on this question while dealing with similar problem. 2 things about accepted solution:
Don't save reference to the fragment anywhere, especially in some list in the adapter
Don't create fields in the fragment, always store data you need in the Bundle so you can get it by using Fragment#getArguments
Now - with this in mind here's a simple solution: put your ShareActionProvider initialization code to onPrepareOptionsMenu call. Something like this:
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem menuShare = menu.findItem(R.id.menuShare);
ShareActionProvider shareAction = (ShareActionProvider)
menuShare.getActionProvider();
shareAction.setShareIntent(createShareIntent());
}
protected Intent createShareIntent() {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
Job job = getArguments().getSerializable(JOB);
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, job.title);
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, job.toText());
return shareIntent;
}

I managed to figure out how to do this myself. What I ended up doing is overriding the
OnPageChangeListener
in the fragmentactivity
private final OnPageChangeListener mOnPageChangeListener = new OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
#Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
TestFragment frag = (TestFragment) adapter.mFragments.get(pager.getCurrentItem());
frag.setShareActionIntent();
}
};

http://developer.android.com/reference/android/widget/ShareActionProvider.html
the example from android sdk doc is:
// In Activity#onCreateOptionsMenu
public boolean onCreateOptionsMenu(Menu menu) {
// Get the menu item.
MenuItem menuItem = menu.findItem(R.id.my_menu_item);
// Get the provider and hold onto it to set/change the share intent.
mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
// Set history different from the default before getting the action
// view since a call to MenuItem.getActionView() calls
// onCreateActionView() which uses the backing file name. Omit this
// line if using the default share history file is desired.
mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
. . .
}
// Somewhere in the application.
public void doShare(Intent shareIntent) {
// When you want to share set the share intent.
mShareActionProvider.setShareIntent(shareIntent);
}

Related

How to call for a method from OnCreate with menu item?

I'm building an app with option to load a work space from remote (via ADB), using this code in OnCreate:
Bundle extras = this.getIntent ( ).getExtras ( );
if (extras != null && extras.containsKey("workspace"))
{
String param = extras.getString("workspace");
WSmethods.loadWorkspace(param); //work space methods class
}
This work space effect save menu item, therefore my workspace constractor contain this menu item, like this:
public workspaceMethods(MyActivity myActivity, MenuItem saveItem)
but, in order to receive MenuItem I have to wait for onCreateOptionsMenu method that called after OnCreate
Therefore, I found myself in a tangle: On the one hand I have to call my work space methods in OnCreate (in order to receive commands from ADB) and on the other hand I have to receive my menu item that initialize after OnCreate called.
Bottom line, the question: How can I call for method from OnCreate with a menu item? (to be more accurate, in my case the question is how to initialize class variable with menu item in OnCreate method?)
EDIT I initialize WSmethods like this (in onCreateOptionsMenu):
WSmethods = new workspaceMethods(this, menu.findItem(R.id.action_save));
You have all access to intent extras even from onCreateOptionsMenu. So just call your method from it - after inflating your menu.
EDIT:
I'm just going to restart as I was under the impression you were implementing the fragment framework.
try this:
#Override
public void onPostCreate(Bundle savedInstance)
{
super .onPostCreate(savedInstance);
WSmethods = new workspaceMethods(this, menu.findItem(R.id.action_save));
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
switch (id)
{
case R.id.action_save:
WSmethods = new workspaceMethods(Activity.this, item);
//do actions associated with method
break;
//other switch cases
default:
//implement a default action
break;
}
}

Android: Send info from activity to fragment

In my MainActivity I have an active search button on my Action Bar/Tool bar/menu. I was wondering if there is a way to filter a list in a Fragment form that active search? Thanks in advance!
It would be even better if each fragment (they are in a viewpager + action bar with tabs) Can have its own action bar!
You should create a custom adapter for your activity's view pager
Then show fragments from adapter, now you have 2 choices for your purpose :
define custom toolbar for each fragment in it's own layout (.xml) file and then use it or
pass data from activity to fragment adapter and from fragment adapter to your purpose fragment(s) and do filtering.
Good Luck my friend
If you do not want to implement using a system service for searching as described in docs, then one way of doing it would be as follows:
In the onCreate method get a handle to your fragment
// if you fragment is embedded with <fragment tag>
mMySearchFragment = (MySearchfragment)getFragmentManager()
.findFragmentById(R.id.your_fragment)
//in case your fragment is added programmatically then, of course,
getFragmentManager()
.beginTransaction()
.add(fragmentid, gragmentinstance, TAG)
.commit();
In the onCreateOptionsMenu do something like
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_searching, menu);
mSearchView = (SearchView) menu.findItem(R.id.menu_search_message).getActionView();
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
#Override
public boolean onQueryTextSubmit(String query) {handleSearch(query)}
#Override
public boolean onQueryTextChange(String newText) { ... }
});
return true;
}
And finally
private void handleSearch(String query){
if(mMySearchFragment != null){
mMySearchFragment.updateSearchResults(query);
}
}
Your fragment would need to have a public method updateSearchResults(String query) where you would run the search and update your list view's adapter with the new collection
Also, you can import the BasicContactables sample in the Studio (File -> Import Sample) and investigate the code

android action bar onNavigationItemSelected

I'm developing for android 3+
In my action bar i have a drop-down list(see how to hide/unhide the actionbar list on android 3? for the dropdown i intend). The problem is i need to do a certain action when the user selects something, but Android calls onNavigationItemSelected() as soons as it draws the view, so no selection actually happened.
How can i detect if the user actually pressed something and it is not a fake call from android ?
public class ListDittaListener implements OnNavigationListener{
private BaseActivity activity;
private ListDittaListener()
{
}
public ListDittaListener(BaseActivity activity)
{
this.activity = activity;
}
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId)
{
MyApp appState = ((MyApp)this.activity.getApplicationContext());
appState.setDittaSelezionata( (int) itemId);
SharedPreferences settings = this.activity.getSharedPreferences(MyApp.PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putInt("ditta_id_selezionata", (int) itemId);
////////restart activity this.activity.recreate();
return false;
}
}
You can easily just ignore the first call to onNavigationItemSelected if you like:
public class Whatever implements OnNavigationListener {
private boolean synthetic = true;
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
if (synthetic) {
synthetic = false;
return true;
}
// do whatever you really wanted here
}
}
Method onNavigationItemSelected(int itemPosition, long itemId) will be called anyway by the action bar.
What you may want to do is to tell action bar what itemPosition it should pass to the method on the first call. (In other words, to tell action bar what navigation item should be set after activity is created). Here is the code:
mActionBarMenuSpinnerAdapter = ...;
mActionBar = getActionBar();
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
mActionBar.setListNavigationCallbacks(mActionBarMenuSpinnerAdapter, this);
mActionBar.setSelectedNavigationItem(###your_default_navigation_item_here###);
After doing this you can solve your problem by applying changes in the onNavigationItemSelected(int itemPosition, long itemId) if only itemPosition is different.
The android system will call onNavigationItemSelected(0, 0) after the activity is setup. (Which means later than onResume()).
As other guys mentioned, you'd better not do any hack like ignore first call, otherwise the android system won't call onNavigationItemSelected() again when you select the first index. (The system thought the first item is already selected)
My solution is call actionbar.setSelectedNavigationItem(the real item# you want) after you setup the actionbar. Then the system will call onNavigationItemSelected() twice. First onNavigationItemSelected(0, 0) and then the onNavigationItemSelected(the real item#).
Well I cannot see anything wrong in your current code.
How did you create your dropdown elements. And what element is "select" by Android after the view is created. And what are your doing in your onCreate method where the ActionBar is initialized.
I did it as instructed here and it worked for me:
http://developer.android.com/guide/topics/ui/actionbar.html#Dropdown
I have viewpager with fragments and I need set custom action bar for every fragment in pager
In desired page I have navigation list, fragment fires onNavigationItemSelected automatically when I swipe pages, want to avoid this behavior and run tasks only if I selected nav item manually.
public class MyFragment extends Fragment implements ActionBar.OnNavigationListener {
private boolead fireReady = false;
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
// every time make it false, this method invoked on swipe action
fireReady = false;
if (isVisibleToUser) {
// setup actionbar, you also can setup action bar in activity
String[] array = getActivity().getResources().getStringArray(R.array.users_order);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, array);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
getActivity().getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getActivity().getActionBar().setListNavigationCallbacks(adapter, this);
}
}
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
if (fireReady) {
// task fire only when you directly press navigation item
UsersTask task = new UsersTask(getActivity());
task.setTaskListener(this);
task.execute(usersUrls[itemPosition]);
} else {
// make it true first time when page displayed
fireReady = true;
}
return false;
}
}
}

Deciding the menu's action dynamically

I add menu's in my application dynamically depending on the values i get from the back-end in the onPrepareOptionsMenu(Menu menu). Now i would want to decide the action that is to be performed for the menu added dynamically (as i do not know the action to be performed beforehand) depending on certain values that came associated with the menu from the back-end. How do i achieve this. Kindly provide me some ideas on this. Thanks in advance.
Look into onCreateOptionsMenu and onPrepareOptionsMenu. Basically you need to overwrite them in your Activity and handle menus there. You can either remove or add menus in these overwridden methods.
Whole procedure is well-documented and described here
If you mean the option menu, then this guide should help you: Changing the Menu.
It shows how you can dynamically add and remove items from the menu right before it is shown to the user using the onPrepareOptionsMenu() method, which passes you the menu. You can then add or remove items from the menu.
You have to play around with onPrepareOptionsMenu and onCreateOptionsMenu. Here is good example how to do that.
I found a way to achieve what i wanted. I put the values associated to the menu as a part of the MenuItems intent. In the onOptionsItemSelected(MenuItem item) i get the intent from the MenuItem retrieve the values from it and perform the action required. The code is as below:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
ApplicationManager.getInstance().resetCounter();
menu.removeGroup(1);
Vector listOfMenuToBeAdded=Service.getInstance().getMenuList();
Enumeration<com.data.Menu> menuEnumeration = listOfMenuToBeAdded.elements();
while (menuEnumeration.hasMoreElements()) {
com.data.Menu levelOptions = (com.pravaa.mobile.dashboard.data.Menu) menuEnumeration
.nextElement();
MenuItem levelMenuItem = menu.add(1, 100, Menu.NONE,
levelOptions.getCaption());
LevelOptionIntent levelOptionIntent = new LevelOptionIntent();
levelOptionIntent.setAppCode(levelOptions.getAppCode());
levelOptionIntent.setDashboardNumber(levelOptions.getNumber());
levelOptionIntent.setUniqueRecordId(levelOptions
.getUniqueRecordId());
levelOptionIntent.setLevelNumber(levelOptions.getLevelNo());
levelMenuItem.setIntent(levelOptionIntent);
}
return true;
}
Once a menu item is clicked on perform the action according to the values set in the intent.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case 100:
LevelOptionIntent levelOptionIntent = (LevelOptionIntent) item
.getIntent();
//Perform what you would want to based on the values set in the intent.
if (levelOptionIntent.getAppCode().equals(A)) {
// Start activity A
}elseif (levelOptionIntent.getAppCode().equals(B)) {
// Start activity B
}else if (levelOptionIntent.getAppCode().equals(C)) {
// Start activity C
}
break;
}
return true;
}
The LevelOptionsIntent class is as below:
public class LevelOptionIntent extends Intent {
private int dashboardNumber;
private String appCode;
private String uniqueRecordId;
private int levelNumber;
public LevelOptionIntent() {
super();
// TODO Auto-generated constructor stub
}
public int getDashboardNumber() {
return dashboardNumber;
}
public void setDashboardNumber(int dashboardNumber) {
this.dashboardNumber = dashboardNumber;
}
public String getAppCode() {
return appCode;
}
public void setAppCode(String appCode) {
this.appCode = appCode;
}
public String getUniqueRecordId() {
return uniqueRecordId;
}
public void setUniqueRecordId(String uniqueRecordId) {
this.uniqueRecordId = uniqueRecordId;
}
public int getLevelNumber() {
return levelNumber;
}
public void setLevelNumber(int levelNumber) {
this.levelNumber = levelNumber;
}}
I am not sure if this is the right way of doing it though.Can someone throw some light on this.
Thanks in advance.

Same Title Bar but different View below it in Android?

In one of my Android Application I need to keep the title bar same but the view that is shown in the rest of the screen changes. So, I have taken different Activity for all the views that I need to show and set the title bar in every Activities onCreate method.
Now, the problem is that I have a button in the title bar and need to perform certain action on its click event. Writing the same event handling code in every Activity class is very cumbersome. Is there any other way out that whenever there is a click event on that button of the title bar then we can have the same functionality without writing the same code in all the Activity classes.
Can we use ViewGroup for that? I don't have much idea about ViewGroup. Is that possible with ViewGroup?
If anyone knows the solution then please let me know.
Thanks & Regards
Sunil
If you are sharing view elements and functionality amongst several classes extending Activity, you might want to consider making a common superclass to handle this overlap.
The best solution is to keep a base activity like this.
public class HeaderBaseActivity extends AppCompatActivity{
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
mAppPreferences = AppUtil.getAppPreferences(this);
item_patients = menu.findItem(R.id.item_patients);
setBatchCountOnMenu(0);
RealmConfiguration realmConfig = new RealmConfiguration.Builder(this).build();
mRealm = Realm.getInstance(realmConfig);
mDotor = new Gson().fromJson(mAppPreferences.getString(Constants.SETTINGS_OBJ_DOCTOR, ""), Doctor.class);
mAppPreferences = AppUtil.getAppPreferences(this);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_logout:
/* DialogUtility.showShortToast(this, " Main manu Action Logout");*/
SharedPreferences.Editor Editor = mAppPreferences.edit();
Editor.putBoolean(Constants.SETTINGS_IS_LOGGED_IN, false);
Editor.apply();
clearRealmDB();
Intent loginIntent = new Intent(HeaderBaseActivity.this, LoginActivity.class);
loginIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(loginIntent);
finish();
break;
case R.id.item_patients:
System.out.println("current activity "+getApplicationContext());
Intent mPatientListIntent = new Intent(HeaderBaseActivity.this, PatientSummaryInfoActivity.class);
mPatientListIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(mPatientListIntent);
break;
case R.id.action_doctor_profile:
openDialogOfDoctorProfile();
break;
}
return super.onOptionsItemSelected(item);
}
}
Your other activities can extend the above activity like this:
public class MainActivity extends HeaderBaseActivity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
}
}

Categories

Resources