Is there an option to modify the content view on the android panorama client? For example I want to display the action bar on top. But currently the action bar is just shown at the beginning and subsequently hidden by the loaded panorama client, since the panorama client is always shown in full screen mode, although it is started in an extra fragment.
I tried now to put the panorama client in a seperated frame through a fragment - this is my code so far:
1. This is the activity whit the panorama fragment and and a text field:
public class PanoramaActivity extends Activity {
public static final String TAG = PanoramaActivity.class.getSimpleName();
private ActionBar actionBar;
private Fragment panoramaClient = new PanoramaClientFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_snow);
actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
FragmentManager fragMan = getFragmentManager();
FragmentTransaction fragTrans = fragMan.beginTransaction();
fragTrans.replace(R.id.panoramaCLientFrame, panoramaClient, "PANO");
fragTrans.commit();
//Non fullscreen
requestWindowFeature(Window.FEATURE_ACTION_BAR);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.panorama, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
}
2.And this is the fragment class with the panorama client:
public class PanoramaClientFragment extends Fragment implements ConnectionCallbacks,
OnConnectionFailedListener, OnPanoramaInfoLoadedListener {
private View view;
private PanoramaClient panoramaClient;
public static final String TAG = PanoramaClientFragment.class.getSimpleName();
public PanoramaClientFragment() {
// TODO Auto-generated constructor stub
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanteState){
view = inflater.inflate(R.layout.panorama_client, container, false);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
panoramaClient = new PanoramaClient(getActivity().getApplicationContext(), this, this);
//Non fullscreen
//getActivity().requestWindowFeature(Window.FEATURE_ACTION_BAR);
//getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
//getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
#Override
public void onStart() {
super.onStart();
panoramaClient.connect();
}
#Override
public void onPanoramaInfoLoaded(ConnectionResult result, Intent viewerIntent) {
if (result.isSuccess()) {
Log.i(TAG, "found viewerIntent: " + viewerIntent);
if (viewerIntent != null) {
startActivity(viewerIntent);
}
} else {
Log.e(TAG, "error: " + result);
}
}
#Override
public void onConnectionFailed(ConnectionResult status) {
Log.e(TAG, "connection failed: " + status);
}
#Override
public void onConnected(Bundle arg0) {
Uri uri = Uri.parse("android.resource://" + this.getActivity().getPackageName() + "/" + R.raw.pano1);
panoramaClient.loadPanoramaInfo(this, uri);
}
#Override
public void onDisconnected() {
// Do nothing.
}
#Override
public void onStop() {
super.onStop();
panoramaClient.disconnect();
}
}
If i uncomment the three "non fullscreen"-lines in the fragment class, the app crashes and says:
android.util.AndroidRuntimeException: requestFeature() must be called before adding content
Thanks for your replies.
Greetings.
Try to create a fragment and add the panorama client activity to it.
I think you cannot show the action bar for one simple reason, when your panorama info is loaded you are starting a new activity which is completely out of your control.
if (viewerIntent != null) {
startActivity(viewerIntent);
}
So your code tries to modify the activity that handles the PanoramaClient instance, but not the one that loads the panorama image.
Related
Below is the MainActivity class that I'm using. The code checks to see if the phone is in landscape or portrait. If it's in portrait, it will show the main fragment in the main activity only (the main fragment is a static fragment in the main_activity.xml file). Then if a "Recipe" is clicked it will open a detail activity with its own fragment. If the phone is in landscape mode, it will show the main fragment and the detail fragment side by side. Everything works perfectly fine however when I follow the procedure below I get a white screen instead of the main activity:
Procedure:
Switch to landscape
Switch back to portrait
Choose an item and wait for the detail activity to open
Press back
Here instead of the main activity window I get a white screen
If I don't switch to landscape and just start with the portrait mode everything is fine. It seems like switching to landscape does something that causes the problem and I can't figure out what. Any tip on what's going on or where to look would be much appreciated.
public class MainActivity extends AppCompatActivity implements RecipesFragment.OnRecipeClickListener {
private String RECIPE_PARCEL_KEY;
private boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RECIPE_PARCEL_KEY = getString(R.string.ParcelKey_RecipeParcel);
if (findViewById(R.id.linearLayoutTwoPane) != null) {
mTwoPane = true;
if (savedInstanceState == null) {
RecipeFragment recipeFragment = new RecipeFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.recipeFrameForTwoPane, recipeFragment)
.commit();
}
} else {
mTwoPane = false;
}
}
#Override
public void OnRecipeClick(Recipe recipe) {
if (mTwoPane) {
RecipeFragment recipeFragment = new RecipeFragment();
recipeFragment.setRecipe(recipe);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.recipeFrameForTwoPane, recipeFragment)
.commit();
} else {
Class destinationClass = DetailActivity.class;
Intent intentToStartDetailActivity = new Intent(this, destinationClass);
intentToStartDetailActivity.putExtra(RECIPE_PARCEL_KEY, recipe);
startActivity(intentToStartDetailActivity);
}
}
}
EDIT:
Adding RecipeFragment's code below:
public class RecipeFragment extends Fragment {
private Recipe mRecipe;
#BindView(R.id.tv_recipeName) TextView recipeNameTextView;
public RecipeFragment(){
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recipe_fragment,container,false);
ButterKnife.bind(this,view);
if(mRecipe!=null) {
recipeNameTextView.setText(mRecipe.getName());
}else{
recipeNameTextView.setText(getString(R.string.messageSelectARecipe));
}
return view;
}
public void setRecipe(Recipe recipe){
mRecipe = recipe;
}
}
EDIT:
I followed #mt0s's advice and created different background colors for the fragments and activities and finally narrowed down the problem to a line in my recyclerview adapter code. My adapter code is below. Inside loadInBackground() on line URL url = new URL(getString(R.string.URL_RecipeJSON)); I get a Fragment RecipesFragment{96e9b6a} not attached to Activity exception. I don't understand why I'm getting this exception and what the best way to resolve this is. Have I placed the right code in the right fragment methods (ie OnCreate vs OnActivityCreated vs OnCreateView vs etc)?
public class RecipesFragment extends Fragment
implements RecipeAdapter.RecipeAdapterOnClickHandler,
LoaderManager.LoaderCallbacks<ArrayList<Recipe>> {
#BindView(R.id.rv_recipes) RecyclerView mRecyclerView;
private RecipeAdapter mRecipeAdapter;
private static final int LOADER_ID = 1000;
private static final String TAG = "RecipesFragment";
private OnRecipeClickListener mOnRecipeClickListener;
public RecipesFragment(){
}
public interface OnRecipeClickListener {
void OnRecipeClick(Recipe recipe);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recipes_fragment, container, false);
ButterKnife.bind(this, view);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mRecipeAdapter = new RecipeAdapter(this);
mRecyclerView.setAdapter(mRecipeAdapter);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(LOADER_ID, null, this);
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void OnClick(Recipe recipe) {
mOnRecipeClickListener.OnRecipeClick(recipe);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try{
mOnRecipeClickListener = (OnRecipeClickListener) context;
} catch (ClassCastException e){
Log.e(TAG, "onAttach: Host activity class must implement OnRecipeClickListener.");
}
}
#Override
public Loader<ArrayList<Recipe>> onCreateLoader(int i, Bundle bundle) {
return new AsyncTaskLoader<ArrayList<Recipe>>(getActivity()) {
#Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad();
}
#Override
public ArrayList<Recipe> loadInBackground() {
String response;
ArrayList<Recipe> recipes = null;
try {
URL url = new URL(getString(R.string.URL_RecipeJSON)); //***I get an exception here***
response = NetworkUtils.getResponseFromHttpUrl(url, getActivity());
recipes = RecipeJsonUtils.getRecipeFromJson(getActivity(), response);
} catch (Exception e) {
Log.e(TAG, "loadInBackground: " + e.getMessage());
}
return recipes;
}
};
}
#Override
public void onLoadFinished(Loader<ArrayList<Recipe>> loader, ArrayList<Recipe> recipes) {
mRecipeAdapter.setRecipeData(recipes);
}
#Override
public void onLoaderReset(Loader<ArrayList<Recipe>> loader) {
}
}
I finally figured out the problem and the solution. The problem is that onStartLoading() in the AsyncTaskLoader anonymous class in RecipesFragment class gets called every time the fragment is resumed whether the enclosing Loader is called or not. This causes the problem. I need to have control over when onStartLoading() is being called and I only want it to be called if and only if the enclosing Loader is being initialized or restarted. As such, I destroyed the loader in onPause() of the fragment and restarted it in onResume(). Hence, I added the following code to the RecipesFragment class:
#Override
public void onPause() {
super.onPause();
getLoaderManager().destroyLoader(LOADER_ID);
}
#Override
public void onResume() {
super.onResume();
getLoaderManager().restartLoader(LOADER_ID, null, this);
}
I also removed initLoader() from onCreate(). This way, every time the fragment is resumed (or created) onStartLoading() will be called. I tried this and it solves my problem.
When you switch from the landscape to portrait or the opposite the Android OS destroy your activity and recreate it again. this what probably trigger your problem
i decide to use AsyncTaskLoader for lifecycle aware when load data.
It successfully created, but i got one problem when rotate my device, my ProgressBar dismissed and not shown again.
I know it because Activity recreate it and execute onCreate() again.
But i don't know where to handle that, i think it already handled by initLoader
public class MainActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<String> {
public static final String TAG = MainActivity.class.getSimpleName();
public static final int LOADER_ID = 92;
public static final String SEARCH_VALUE = "java";
public static final String ARG_GITHUB_URL = "github_search_url";
#BindView(R.id.tv_results) TextView mResultTextView;
#BindView(R.id.pb_loading_indicator) ProgressBar mLoadingIndicatorProgressBar;
Bundle mBundle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mBundle = new Bundle();
// Initiate Loader at the first time
// when onCreate called (rotate device)
URL searchUrl = NetworkUtils.buildUrl(SEARCH_VALUE);
mBundle.putString(ARG_GITHUB_URL, searchUrl.toString());
getSupportLoaderManager().initLoader(LOADER_ID, mBundle, this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int menuItemId = item.getItemId();
if (menuItemId == R.id.action_reload) {
loadGithubRepository();
}
return super.onOptionsItemSelected(item);
}
private void loadGithubRepository() {
Log.e(TAG, "loadGithubRepository: Start load github repository");
mResultTextView.setText("");
// URL searchUrl = NetworkUtils.buildUrl(repoName);
// new GithubRepositoryTask().execute(searchUrl);
LoaderManager loaderManager = getSupportLoaderManager();
if (null == loaderManager.getLoader(LOADER_ID)) {
getSupportLoaderManager().initLoader(LOADER_ID, mBundle, this);
} else {
getSupportLoaderManager().restartLoader(LOADER_ID, mBundle, this);
}
}
// Implement Loader Callback method
#Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
return new AsyncTaskLoader<String>(this) {
#Override
protected void onStartLoading() {
mLoadingIndicatorProgressBar.setVisibility(View.VISIBLE);
if (args != null)
forceLoad();
}
#Override
public String loadInBackground() {
String response = null;
Log.d(TAG, "loadInBackground: " + (args != null));
if (args != null) {
try {
Log.d(TAG, "loadInBackground: " + args.getString(ARG_GITHUB_URL));
URL url = new URL(args.getString(ARG_GITHUB_URL));
response = NetworkUtils.getResponseFromHttp(url);
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
};
}
#Override
public void onLoadFinished(Loader<String> loader, String data) {
mLoadingIndicatorProgressBar.setVisibility(View.INVISIBLE);
if (data != null && !data.equals("")) {
mResultTextView.setText(data);
}
}
#Override
public void onLoaderReset(Loader<String> loader) {
// Do nothing...
}
}
How to handle that?
//inside your activity
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
// in manifest
<activity
android:name=".activities.YourActivity"
android:label="#string/title_activity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="stateHidden|adjustResize" />
which not recreates activity layout.
may be helpful
It is happening because your layout is recreated and, as I understood, default ProgressBar is INVISIBLE. You have to save activity's loading state and set visibility for ProgressBar after restoring instance state.
More information about saving/restoring data in activity:
https://stackoverflow.com/a/151940/2504274
I am creating an activity which shows a list of videos(VideoListingActivity) depending on the parameters passed from the parent activity.my I am trying to pass the bundle passed to VideoListingActivity to its child fragment so that it can fetch the related data from database and display it on the activity. I am trying to use Fragment.setArguments() to pass the bundle to fragment but getting the below error .
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rrdtech.vidyavaan.android/com.rrdtech.vidyavaan.android.VideoListingActivity}: java.lang.IllegalStateException: Fragment already active
I think the fragment is attached to activity post to onCreate() so should this error even be raised ?
Below are the codes for my activity and fragment
VideoListingActivity.java
public class VideoListingActivity extends ActionBarActivity implements FilterFragment.OnFilterItemSelectedListener,
android.support.v7.widget.SearchView.OnQueryTextListener
{
public VideoListFragment videoListFragment;
private android.support.v7.widget.SearchView searchView;
private Context context;
private Bundle bundle;
private String listBy;
private String subjectId;
private String levelType;
private FragmentTransaction ft;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_listing);
// videoListFragment=new VideoListFragment();
videoListFragment= (VideoListFragment) getFragmentManager().findFragmentById(R.id.frg_video_listing_video_listing_fragment);
ft =getFragmentManager().beginTransaction();
context=this;
bundle = new Bundle();
bundle = getIntent().getExtras();
videoListFragment.setArguments(bundle);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_video_listing, menu);
MenuItem menuItem=menu.findItem(R.id.item_action_search);
//SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (android.support.v7.widget.SearchView) menu.findItem(R.id.item_action_search).getActionView();
setupSearchView(menuItem);
//searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
return super.onCreateOptionsMenu(menu);
}
public void setupSearchView(MenuItem searchItem)
{
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
if(searchManager != null)
{
SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
searchView.setSearchableInfo(info);
}
searchView.setOnQueryTextListener(this);
}
#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.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onFilterItemSelected(String filterId) {
videoListFragment.filterSelectedAction("filter id is "+filterId);
}
#Override
public boolean onQueryTextSubmit(String query) {
CommonFunctions commonFunctions = new CommonFunctions();
commonFunctions.showProgressDialog(context,"getting data","bringing");
ft.replace(R.id.frg_video_listing_filter_fragment,videoListFragment);
ft.commit();
commonFunctions.dismissProgressDialog();
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
}
VideoListingFragment.java
public class VideoListFragment extends Fragment {
private ListView videoListView;
private Context activityContext;
private VideosListAdapter listAdapter;
private List<Video> videosList;
private Bundle b;
private String listBy;
private String subjectId;
private String levelType;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
activityContext = activity.getApplicationContext();
b=new Bundle();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.video_list_fragment,container,false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
b= getArguments();
listBy = b.getString(VidyavaanGlobal.listBy);
Log.d("list by ",listBy);
}
#Override
public void onStart() {
super.onStart();
}
public void filterSelectedAction(String x)
{
Log.d("passed is ", x);
}
public void fillData()
{
videosList.add(new Video("chapter1","title1", "pragyan public school", "pawan saraskar", "Chemistry", "Advance", "abcd url", "21", "5/6/2015", "thumbnail url"));
videosList.add(new Video("chapter2","title2","pragyan public school","pawan saraskar","physics","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter3","title3","pragyan public school","pawan saraskar","english","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter4","title4","pragyan public school","pawan saraskar","Chemistry","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter5","title5","pragyan public school","pawan saraskar","Chemistry","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter6","title6","pragyan public school","pawan saraskar","Chemistry","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter7", "title7", "pragyan public school", "pawan saraskar", "Chemistry", "Advance", "abcd url", "21", "5/6/2015", "thumbnail url"));
}
public void displayVideoList(boolean searchReqeust )
{
}
public void displayVideoList(String pListBy, String pValue)
{
listAdapter = new VideosListAdapter(activityContext,videosList);
videoListView.setAdapter(listAdapter);
}
public void displayVideoList(String subjectId, String videoType, String VideoLevel)
{
}
}
can one please help. Thanks in advance.
From the Official Android development Reference:
Public void setArguments (Bundle args) Supply the construction
arguments for this fragment. This can only be called before the
fragment has been attached to its activity; that is, you should call
it immediately after constructing the fragment. The arguments supplied
here will be retained across fragment destroy and creation.
Your fragment is already attached to its activity i suggest you to use your own method, you don't need setArguments!
create your own setUIArguments(Bundle args) inside the fragment class and update the fragment UI inside this method
You will call this method in this way:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Detailfragment detailFragment = (Detailfragment)getFragmentManager().findFragmentById(detailFragmentID);
Bundle bundle = new Bundle();
bundle.putSerializable(BUNDLE_KEY, obj);// passing this object
detailFragment.setUIArguments(bundle); /* your new method */
}
in your fragment class
public void setUIArguments(Bundle args) {
getActivity().runOnUiThread(new Runnable() {
public void run() {
/* do your UI stuffs */
}
}
}
call
bundle = new Bundle();
bundle = getIntent().getExtras();
videoListFragment.setArguments(bundle);
before
ft =getFragmentManager().beginTransaction();
line.
try to call ft =getFragmentManager().beginTransaction(); after adding bundle as arguments.
I'm a relatively new Android developer and currently finishing up my first Android app.
This app is a 'shell' app for a web app and it uses fragments, but I am having two issues. I have done extensive research but I could not get any of the ideas I found to work, so I hope I might be able to get some answers here. Thank you in advance!
1) I want the user to be able to use the back button on their device to go back in the web view
2) I am trying to pass the GPS Latitude and Longitude from a method within a class, out the the variables myLongitude and myLatitude
Here is the code from the MainActivity
public class MainActivity extends FragmentActivity implements ActionBar.TabListener
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Without this, location is not fetched
LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
//mlocManager.removeUpdates(mlocListener); // This needs to stop getting the location data and save the battery power.
// Set up the action bar to show tabs.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// For each of the sections in the app, add a tab to the action bar.
actionBar.addTab(actionBar.newTab().setText("Browse").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("My City").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Search").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Favs").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Help").setTabListener(this));
}
// The serialization (saved instance state) Bundle key representing the current tab position.
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
#Override
public void onRestoreInstanceState(Bundle savedInstanceState)
{
// Restore the previously serialized current tab position.
if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM))
{
getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
}
}
#Override
public void onSaveInstanceState(Bundle outState)
{
// Serialize the current tab position.
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex());
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
//Gets the Device ID
public String getDeviceId()
{
final String androidId, deviceId;
androidId = android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
deviceId = androidId.toString();
return deviceId;
}
public class MyLocationListener implements LocationListener
{
Double myLatitude; //This is passing a NULL value down to onTabSelected because it is not getting a value from onLocationChanged
Double myLongitude; //This is passing a NULL value down to onTabSelected because it is not getting a value from onLocationChanged
#Override
public void onLocationChanged(Location loc)
{
myLatitude = loc.getLatitude();
myLongitude = loc.getLongitude();
String Text = "My current location is: " + "Latitude = " + myLatitude + "Longitude = " + myLongitude;
Toast.makeText(getApplicationContext(), Text, Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderDisabled(String provider)
{
Toast.makeText(getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
}
#Override
public void onProviderEnabled(String provider)
{
Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{}
}
// When the given tab is selected, assign specific content to be displayed //
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
Fragment fragment = new SectionFragment();
Bundle args = new Bundle();
final String deviceId = getDeviceId();
MyLocationListener location = new MyLocationListener();
final Double myLatitude = location.myLatitude; //This is returning a NULL value
final Double myLongitude = location.myLongitude; //This is returning a NULL value
//Assigns a specific URL to "ARG_SECTION_URL" for each tab
if(tab.getPosition()==0)
{
args.putString(SectionFragment.ARG_SECTION_URL, "http://www.myurl.com/countries.asp?Country=&State=&City=&Category=&Latitude=&Longitude=&ListingID=&AppId=aDG&DeviceID=" + deviceId + "&OrderBy=Name");
}
else if(tab.getPosition()==1)
{
args.putString(SectionFragment.ARG_SECTION_URL, "http://www.myurl.com/landing.asp?Country=&State=&City=&Category=&Latitude=" + myLatitude + "&Longitude=" + myLongitude + "&ListingID=&AppId=aDG&DeviceID=" + deviceId + "&OrderBy=Name");
}
else if(tab.getPosition()==2)
{
args.putString(SectionFragment.ARG_SECTION_URL, "http://www.myurl.com/searchform.asp?Latitude=&Longitude=&ListingID=&AppId=aDG&DeviceID=" + deviceId);
}
else if(tab.getPosition()==3)
{
args.putString(SectionFragment.ARG_SECTION_URL, "http://www.myurl.com/favorites.asp?Latitude=&Longitude=&ListingID=&AppId=aDG&DeviceID=" + deviceId + "&OrderBy=Name");
}
else if(tab.getPosition()==4)
{
args.putString(SectionFragment.ARG_SECTION_URL, "http://www.myurl.com/help.asp?Latitude=&Longitude=&ListingID=&AppId=aDG&DeviceID=" + deviceId);
}
fragment.setArguments(args);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).commit();
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{}
#Override
public void onBackPressed()
{
}
//A fragment representing a section of the app, but that simply displays content.
public static class SectionFragment extends Fragment
{
//The fragment argument representing the section number for this fragment.
public static final String ARG_SECTION_URL = "section_url";
public SectionFragment()
{}
#SuppressLint("SetJavaScriptEnabled")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
//Create a new WebView and set its URL to the fragment's argument value.
WebView myWebView = new WebView(getActivity());
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl(getArguments().getString(ARG_SECTION_URL));
myWebView.setWebViewClient(new MyWebViewClient());
myWebView.getSettings().setAppCacheEnabled(true);
myWebView.getSettings().setDatabaseEnabled(true);
myWebView.getSettings().setDomStorageEnabled(true);
return myWebView;
}
private class MyWebViewClient extends WebViewClient
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
}
}
}
I find this way to be more simple.
In WebViewActivity.java, I added 1 method:
#Override
public void onBackPressed() {
WebViewFragment fragment = (WebViewFragment)
getSupportFragmentManager().findFragmentById(R.id.fragmentContainer);
if (fragment.canGoBack()) {
fragment.goBack();
} else {
super.onBackPressed();
}
}
In WebViewFragment.java, I added 2 methods:
public boolean canGoBack() {
return mWebView.canGoBack();
}
public void goBack() {
mWebView.goBack();
}
What I did was implement it within the activity and then have a public static so:
In the main activity:
public class MainActivity extends FragmentActivity{
public static WebView myWebView;
...
#Override
public void onBackPressed() {
if (getSupportFragmentManager().findFragmentByTag("yourtag") != null) {
if(myWebView.canGoBack())
myWebView.goBack();
else {
super.onBackPressed();
}
}
else
super.onBackPressed();
}
...
}
and to reference it within the fragment:
MainActivity.myWebView = (WebView) getView().findViewById(R.id.webview);
and be sure when you create the fragment you add a tag
transaction.replace(R.id.yourfragid, newfragment, "yourtag");
Implement View.OnKeyListener in Snippet with WebView ;
public class ItemMenuFragment extends Fragment implementsView.OnKeyListener
Connect the onKeyListener listener to the WebView;
webView.setOnKeyListener(this);
Override the OnKeyListener.onKey method;
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == MotionEvent.ACTION_UP && webView.canGoBack()) {
webView.goBack();
return true;
}
return false;
}
I have a problem regarding with FragmentActivity and mutltiple Fragments inside a ViewPager.
In the FragmentActivity an object is loaded, with a AsyncTask which is used in all the other fragments. I have used the android:configChanges="orientation|keyboardHidden|keyboard" "hack" to make sure the object is only loaded once, even during a screen rotation.
However, now I would to like to display more infromation in landscape modus in one of the Fragments, so now that hack doesn't work.
I've tried implementing a AsyncLoader and the FragmentRetainInstanceSupport from the Android samples. But none of the things work:
1 - I can't get the FragmentRetainInstanceSupport get to work within the ViewPager, when I follow the sample code the onCreate() method isn't called in the worker-fragment
2 - The AsyncLoader crashes during a screen rotation...
Here is my code in which I (tried to) implement the AsyncLoader:
public class TeamActivity extends SherlockFragmentActivity implements LoaderManager.LoaderCallbacks<Response<Team>> {
ViewPager mPager;
PageIndicator mIndicator;
FragmentPagerAdapter mAdapter;
private final int MENU_FOLLOW = Menu.FIRST;
private final int MENU_UNFOLLOW = Menu.FIRST + 1;
Team team = null;
static int team_id;
public Team getTeam(){
return team;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
team_id = this.getIntent().getIntExtra("index", 0);
Log.d("Teamid",""+team_id);
getSupportLoaderManager().initLoader(0, null, this);//.forceLoad();
//getSupportLoaderManager().getLoader(0).startLoading();
//new getTeam().execute();
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(team != null) {
team.getNaam();
SharedPreferences keyValues = this.getSharedPreferences("teams_follow", Context.MODE_PRIVATE);
MenuItem menuItem_volg = menu.findItem(MENU_FOLLOW);
MenuItem menuItem_delete = menu.findItem(MENU_UNFOLLOW);
if(keyValues.contains(String.valueOf(team.getStartnummer()))) {
menuItem_volg.setVisible(false);
menuItem_delete.setVisible(true);
} else {
menuItem_volg.setVisible(true);
menuItem_delete.setVisible(false);
}
}
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0,MENU_UNFOLLOW,Menu.NONE, R.string.ab_verwijderen)
.setIcon(R.drawable.ic_action_delete)
.setVisible(false)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(0,MENU_FOLLOW,Menu.NONE, R.string.ab_volgen)
.setIcon(R.drawable.ic_action_star)
.setVisible(false)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Utils.goHome(getApplicationContext());
break;
case MENU_FOLLOW:
Utils.addFavoTeam(getApplicationContext(), team);
invalidateOptionsMenu();
break;
case MENU_UNFOLLOW:
Utils.removeFavoteam(getApplicationContext(), team.getID());
invalidateOptionsMenu();
break;
}
return super.onOptionsItemSelected(item);
}
class TeamFragmentAdapter extends FragmentPagerAdapter implements TitleProvider {
ArrayList<Fragment> fragments = new ArrayList<Fragment>();
ArrayList<String> titels = new ArrayList<String>();
public TeamFragmentAdapter(FragmentManager fm) {
super(fm);
fragments.add(new TeamInformatieFragment());
titels.add("Informatie");
fragments.add(new TeamLooptijdenFragment());
titels.add("Routetijden");
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public String getTitle(int position) {
return titels.get(position);
}
}
private class getTeam extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
Response<Team> response;
protected void onPreExecute() {
progressDialog = ProgressDialog.show(TeamActivity.this,
"Bezig met laden", "Team wordt opgehaald...", true);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
cancel(true);
Utils.goHome(TeamActivity.this);
}
});
}
#Override
protected Void doInBackground(Void... arg0) {
if(!isCancelled())
response = api.getTeamByID(team_id);
return null;
}
#Override
protected void onPostExecute(Void result) {
if(Utils.checkResponse(TeamActivity.this, response)) {
setContentView(R.layout.simple_tabs);
team = response.getResponse();
mAdapter = new TeamFragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
invalidateOptionsMenu();
progressDialog.dismiss();
}
}
}
public static class AppListLoader extends AsyncTaskLoader<Response<Team>> {
Response<Team> response;
public AppListLoader(Context context) {
super(context);
}
#Override public Response<Team> loadInBackground() {
response = api.getTeamByID(team_id);
return response;
}
#Override public void deliverResult(Response<Team> response) {
if (isReset()) {
return;
}
this.response = response;
super.deliverResult(response);
}
#Override protected void onStartLoading() {
if (response != null) {
deliverResult(response);
}
if (takeContentChanged() || response == null) {
forceLoad();
}
}
#Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
#Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
response = null;
}
}
private ProgressDialog progressDialog;
#Override
public Loader<Response<Team>> onCreateLoader(int arg0, Bundle arg1) {
progressDialog = ProgressDialog.show(TeamActivity.this,
"Bezig met laden", "Team wordt opgehaald...", true);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
finish();
}
});
return new AppListLoader(this);
}
#Override
public void onLoadFinished(Loader<Response<Team>> loader, Response<Team> response) {
//Log.d("Loader", "Klaar");
if(Utils.checkResponse(TeamActivity.this, response)) {
team = response.getResponse();
setContentView(R.layout.simple_tabs);
mAdapter = new TeamFragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
invalidateOptionsMenu();
progressDialog.dismiss();
}
}
#Override
public void onLoaderReset(Loader<Response<Team>> arg0) {
//Utils.goHome(this);
}
}
Fragment (example):
public class TeamInformatieFragment extends SherlockFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Team team = ((TeamActivity)this.getActivity()).getTeam();
//ERROR ON NEXT LINE AFTER SCREEN ROTATION:
getSherlockActivity().getSupportActionBar().setTitle(team.getNaam());
View view = inflater.inflate(R.layout.team_informatie, container, false);
return view;
}
}
The method is called from the fragments (with getActivity().getTeam()) but after a screen rotation getTeam() returns null;
I think the fragments are calling getTeam() too fast, before the variable team has been initialized(?)
Can you please help me?
Thank you!
This is probably not what you want to hear, but I recommend getting rid of
android:configChanges="orientation|keyboardHidden|keyboard"
It's an ugly hack, and a lot of the newer SDK elements like Loaders will break if you don't handle configuration changes correctly. Let Android handle the config changes, and design your code around that.