How to maintain fragment's state when it is shown within FragmentTabHost?
Thanks to this tutorial, I'm able to implement FragmentTabHost in my application.
My intention is to create an app whose main activity contains some tabs (which sticks on the top throughout the app). Clicking each tab opens a new fragment below the tabs.
Issue is when I click on a tab do something, then go to anther tab which opens a new fragment, then comes back to first tab - my changes here are not maintained.
Flow:
I really need to implement this logic. If my approach is wrong, please suggest alternative.
Thanks
Code:
Main Activity
public class FagTabHostMain extends FragmentActivity {
FragmentTabHost mTabHost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fag_tab_host_main);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("audio").setIndicator("Audio"),
AudioContainerFragmentClass.class, null);
mTabHost.addTab(mTabHost.newTabSpec("video").setIndicator("Video"),
VideoContainerFragmentClass.class, null);
}
#Override
public void onBackPressed() {
boolean isPopFragment = false;
String currentTabTag = mTabHost.getCurrentTabTag();
if (currentTabTag.equals("audio")) {
isPopFragment = ((AudioContainerFragmentClass) getSupportFragmentManager()
.findFragmentByTag("audio")).popFragment();
} else if (currentTabTag.equals("video")) {
isPopFragment = ((VideoContainerFragmentClass) getSupportFragmentManager()
.findFragmentByTag("video")).popFragment();
}
// Finish when no more fragments to show in back stack
finish();
}
}
Main activity layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v4.app.FragmentTabHost
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Not Using this one right now -->
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dip"
android:layout_height="0dip"
android:layout_weight="0" />
</android.support.v4.app.FragmentTabHost>
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
</LinearLayout>
AudioContainerFragmentClass
public class AudioContainerFragmentClass extends Fragment implements
OnClickListener {
final String TAG = "AudioContainerFragmentClass";
private Boolean mIsViewInitiated = false;
private boolean addToBackStack = true;
private Button bNextFragment;
private LinearLayout linearLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
try {
Log.e("AudioContainerFragmentClass", "onCreateView called");
linearLayout = (LinearLayout) inflater.inflate(
R.layout.audio_fragment_container, container, false);
} catch (Exception e) {
printException(e.toString());
}
return linearLayout;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
try {
super.onActivityCreated(savedInstanceState);
Log.e("AudioContainerFragmentClass", "onActivityCreated called");
if (!mIsViewInitiated) {
mIsViewInitiated = true;
initView();
}
} catch (Exception e) {
printException(e.toString());
}
}
private void initView() {
try {
Log.e("AudioContainerFragmentClass", "initView called");
bNextFragment = (Button) linearLayout
.findViewById(R.id.bNextFragment);
bNextFragment.setOnClickListener(this);
replaceFragment(new AudioFragment(), false);
} catch (Exception e) {
printException(e.toString());
}
}
private void replaceFragment(AudioFragment audioFragment, boolean b) {
try {
FragmentTransaction ft = getChildFragmentManager()
.beginTransaction();
if (addToBackStack) {
ft.addToBackStack(null);
}
ft.replace(R.id.audio_sub_fragment, audioFragment);
ft.commit();
getChildFragmentManager().executePendingTransactions();
} catch (Exception e) {
printException(e.toString());
}
}
// Called from FagTabHostMain Activity
public boolean popFragment() {
boolean isPop = false;
try {
Log.e("AudioContainerFragmentClass", "popFragment called");
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
} catch (Exception e) {
printException(e.toString());
}
return isPop;
}
#Override
public void onClick(View arg0) {
TextView tv = (TextView)getActivity().findViewById(R.id.tvaudioTitle);
tv.setText("Text changed");
}
private void printException(String string) {
Log.e("__ERRORR__", string);
}
}
AudioFragment
public class AudioFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.audio_sub_fragment, container,
false);
return view;
}
}
Had the same thing in my app.
You will need to copy the FragmentTabHost to your project, point your code to use the new custom FragmentTabHost and then change the code of doTabChanged to following implementation:
private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) {
TabInfo newTab = null;
for (int i=0; i<mTabs.size(); i++) {
TabInfo tab = mTabs.get(i);
if (tab.tag.equals(tabId)) {
newTab = tab;
}
}
if (newTab == null) {
throw new IllegalStateException("No tab known for tag " + tabId);
}
if (mLastTab != newTab) {
if (ft == null) {
ft = mFragmentManager.beginTransaction();
}
if (mLastTab != null) {
if (mLastTab.fragment != null) {
ft.hide(mLastTab.fragment);
}
}
if (newTab != null) {
if (newTab.fragment == null) {
newTab.fragment = Fragment.instantiate(mContext,
newTab.clss.getName(), newTab.args);
ft.add(mContainerId, newTab.fragment, newTab.tag);
findViewById(mContainerId).setContentDescription("DEBUG. add fragment to this container");
} else {
if (newTab.fragment.isHidden()){
ft.show(newTab.fragment);
}
else{
ft.attach(newTab.fragment);
}
}
}
mPreviousTab = mLastTab;
mLastTab = newTab;
}
return ft;
}
The change that was made is that instead of deattach/attach the fragment, we are doing hide/show
I believe your fragment is being re-instantiated each time you switch tab, which means that your field variables are reset.
You probably could use the saveInstance bundle to manage the state of your fragment but I find it more useful and simpler to use SharedPreferences. This also has the benefit of keeping the saved state even if your application is restarted.
To read and write variables to SharedPreferences I use this small helper class:
public class PreferencesData {
public static void saveString(Context context, String key, String value) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(context);
sharedPrefs.edit().putString(key, value).commit();
}
public static void saveInt(Context context, String key, int value) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(context);
sharedPrefs.edit().putInt(key, value).commit();
}
public static void saveBoolean(Context context, String key, boolean value) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(context);
sharedPrefs.edit().putBoolean(key, value).commit();
}
public static int getInt(Context context, String key, int defaultValue) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(context);
return sharedPrefs.getInt(key, defaultValue);
}
public static String getString(Context context, String key, String defaultValue) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(context);
return sharedPrefs.getString(key, defaultValue);
}
public static boolean getBoolean(Context context, String key, boolean defaultValue) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(context);
return sharedPrefs.getBoolean(key, defaultValue);
}
}
Now, as an example, to save your mIsViewInitiated variable, then in onPause:
#Override
protected void onPause() {
PreferencesData.saveBoolean(this, "isViewInitiated", mIsViewInitiated);
super.onPause();
}
And to retrieve it again:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
try {
super.onActivityCreated(savedInstanceState);
Log.e("AudioContainerFragmentClass", "onActivityCreated called");
// will now be true if onPause have been called
mIsViewInitiated = PreferencesData.getBoolean(this, "isViewInitiated", false);
if (!mIsViewInitiated) {
mIsViewInitiated = true;
initView();
}
} catch (Exception e) {
printException(e.toString());
}
}
Since this example variable tells whether some UI has been loaded, then you might want to set it to false when the activity is destroyed.
#Override
protected void onDestroy() {
PreferencesData.saveBoolean(this, "isViewInitiated", false);
super.onDestroy();
}
This answer is just a single option and shows my personal preference, whereas other options might suit your situation better. I would suggest taking a look at http://developer.android.com/guide/topics/data/data-storage.html
Modify your Activity to override onSaveInstanceState and your onCreate method to restore from a "savedInstanceState".
public static final String TAB_STATE = "TAB_STATE";
#Override
protected void onSaveInstanceState(Bundle outState) {
outstate.putParcelable(TAB_STATE, mTabHost.onSaveInstanceState());
super.onSaveInstanceState(outState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fag_tab_host_main);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
if(savedInstanceState==null || savedInstanceState.getParcelable(TAB_STATE)==null){
mTabHost.addTab(mTabHost.newTabSpec("audio").setIndicator("Audio"),
AudioContainerFragmentClass.class, null);
mTabHost.addTab(mTabHost.newTabSpec("video").setIndicator("Video"),
VideoContainerFragmentClass.class, null);
} else{
mTabHost.onRestoreInstanceState(savedInstanceState.getParcelable(TAB_STATE));
}
}
As stated above you can save and then restore your data via the Bundle, Shared Preferences, or a SQLite db. You may also want to call setRetainInstance(true) on your Fragment. This will stop your fragments from being re-created repeatedly.
Related
I am using an interface, as is standard (best?) practice to communicate between a series of fragments. The business logic requires the app to collect some information in fragment n+1 and if the "next" button is tapped then the user goes to fragment n+2. If the "back" button is tapped then the user goes to fragment n. I am also using a nice sliding animation to display the transition from one fragment to the other depending on the direction. I cannot figure out why this is not working and I am getting the null pointer error on this line:
createPlanListener.onCreatePlan(bundle);
Here is the initial fragment Mealplan.class where I trigger the transition. I have left all of the boiler plate code generated by Android Studio as is:
public class MealplanFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private FloatingActionButton createMealplan;
// bunch of variables
private Bundle bundle;
private OnCreatePlanListener createPlanListener;
public MealplanFragment() {
// Required empty public constructor
}
public static MealplanFragment newInstance(String param1, String param2) {
MealplanFragment fragment = new MealplanFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Other code that has nothing to do with the bundle or the listener
// Floating action bar
createMealplan.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
bundle.putBoolean("direction", true);
createPlanListener.onCreatePlan(bundle);
}
});
return mealplanView;
}
public void onButtonPressed(Bundle bundle) {
if (createPlanListener != null) {
createPlanListener.onCreatePlan(bundle);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mealplanContext = context;
if (context instanceof OnCreatePlanListener) {
createPlanListener = (OnCreatePlanListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
createPlanListener = null;
}
public interface OnCreatePlanListener {
void onCreatePlan(Bundle bundle);
}
#Override
public void onResume() {
super.onResume();
}
And here is MainActivity.class
public class MainActivity extends AppCompatActivity implements
MealplanFragment.OnCreatePlanListener {
// Non related variables
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// MealplanFragment is the default fragment at onCreate
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.frame_container, new MealplanFragment(), null).commit();
}
}
#Override
public void onCreatePlan(Bundle bundle) {
if (bundle != null) {
Boolean direction = bundle.getBoolean("direction");
ReceptionFragment fragment = new ReceptionFragment();
openFragment(bundle, fragment, direction);
}
}
private void openFragment(Bundle bundle, Fragment fragment, Boolean direction) {
fragment.setArguments(bundle);
//Starting fragment with animation
if (direction) {
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_right).replace(R.id.frame_container, fragment, null);
fragmentTransaction.commit();
} else {
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_left).replace(R.id.frame_container, fragment, null);
fragmentTransaction.commit();
}
}
}
createMealplan.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
bundle.putBoolean("direction", true);
createPlanListener.onCreatePlan(bundle);
}
});
This is your click listener. bundle is defined as class variable but never initialized and hence the null pointer exception. I would suggest that you use a local variable -> create a new instance of bundle, add data and then invoke callback. Also, createPlanListener is nullable, so you should add a check for that as well.
I have an Activity with a ViewPager and TabLayout. I enabled "destroy activities" from Settings in my phone to simulate low memory.
I use getSupportFragmentManager because it's an Activity.
The first time I open the activity, I see my fragments. When I minimize my app and reopen it, I see the tabs but not the content. Inside fragments I call setRetainInstance(true).
Of course if I call super.onCreate(null); instead of super.onCreate(savedInstanceState); it's working fine because the activity is being recreated at all.
If I use FragmentStatePagerAdapter the content is ok but the menu displays duplicated items.
So please, don't suggest FragmentStatePagerAdapter (want all fragments visible), getChildFragmentManager (ViewPager is in an Activity), setRetainInstance (already using it).
public class SystemActivity extends LoadingActivity {
#BindView(R.id.pager)
ViewPager viewPager;
#BindView(R.id.tab_layout)
TabLayout tabLayout;
#BindView(R.id.toolbar)
Toolbar toolbar;
int[] ICONS = {
R.drawable.ic_tab_general,
R.drawable.ic_tab_details
};
int[] TEXTS = {
R.string.general,
R.string.details,
};
private CustomPagerAdapter customPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fetch();
}
protected void fetch() {
super.fetch();
final Long systemId = getIntent().getLongExtra(Constants.Intent.SYSTEM_ID, 0);
this.realm = Realm.getDefaultInstance();
this.call = ApiClientHelper.getInstance(this).getSystem(systemId);
call.enqueue(new ApiUICallback<System>(this) {
#Override
public void onError(int code, String message) {
System system = realm.where(System.class).equalTo("id", systemId).findFirst();
if (system == null) {
fail();
} else {
init(system);
}
}
#Override
public void onSuccess(System system) {
realm.beginTransaction();
realm.copyToRealmOrUpdate(system);
realm.commitTransaction();
init(system);
}
});
}
private void init(System system) {
setContentView(R.layout.activity_system);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
customPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager(), system);
viewPager.setOffscreenPageLimit(TEXTS.length);
viewPager.setAdapter(customPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
CharSequence title = customPagerAdapter.getPageTitle(0);
getSupportActionBar().setTitle(title);
for (int i = 0; i < ICONS.length; i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
tab.setCustomView(R.layout.tab_view);
((ImageView) tab.getCustomView().findViewById(R.id.icon)).setImageResource(ICONS[i]);
}
tabLayout.setOnTabSelectedListener(
new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
CharSequence title = customPagerAdapter.getPageTitle(tab.getPosition());
getSupportActionBar().setTitle(title);
hiddenKeyboard();
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
hiddenKeyboard();
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
hiddenKeyboard();
}
}
);
}
private void hiddenKeyboard() {
View focus = getCurrentFocus();
if (focus != null) {
focus.clearFocus();
InputMethodManager keyboard = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
keyboard.hideSoftInputFromWindow(focus.getWindowToken(), 0);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
class CustomPagerAdapter extends FragmentPagerAdapter {
private System system;
public CustomPagerAdapter(FragmentManager fm, System system) {
super(fm);
this.system = system;
}
#Override
public Fragment getItem(int position) {
Fragment fragment;
switch (position) {
case 0:
fragment = new SystemGeneralFragment();
break;
case 1:
fragment = new SystemDetailsFragment();
break;
default:
return null;
}
Bundle bundle = new Bundle();
bundle.putLong(Constants.Intent.SYSTEM_ID, this.system.getId());
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return TEXTS.length;
}
#Override
public CharSequence getPageTitle(int position) {
return getResources().getString(TEXTS[position]);
}
}
}
And one of my fragments:
public class SystemGeneralFragment extends MyFragment {
#BindView(R.id.progress)
View progress;
#BindView(R.id.progress_background)
View progressBackground;
#BindView(R.id.progress_percentage)
TextView percentage;
protected Call call;
protected Realm realm;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
realm = Realm.getDefaultInstance();
}
#Override
public void onDestroyView() {
if (this.call != null) {
this.call.cancel();
}
super.onDestroyView();
}
#Override
public void onDestroy() {
realm.close();
super.onDestroy();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_system_general, container, false);
ButterKnife.bind(this, view);
System system = realm.where(System.class).equalTo("id", getArguments().getLong(Constants.Intent.SYSTEM_ID)).findFirst();
System.Status status = system.getStatus();
percentage.setText(String.format("%d%%", status.getProgress()));
setProgress(progress, status.getColor(getContext()));
setProgress(progressBackground, ContextCompat.getColor(getContext(), R.color.light_gray));
return view;
}
private void setProgress(View view, int color) {
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius(16);
shape.setColor(color);
if (Build.VERSION.SDK_INT >= 16) {
view.setBackground(shape);
} else {
view.setBackgroundDrawable(shape);
}
}
}
so I'm trying to refactor my app that uses the Facebook API to use fragments instead of activities. Before, after logging in with Facebook, I would get taken to a new activity - now, I'm trying to use fragments instead. However, ever since I started using fragments, it's been failing during requests, giving me an error "Session provided to a Request in un-opened state"
I added all the UIHelper lifecycle methods to my fragment, but I'm still getting the error. I basically copied the exact code that the example fragment uses, and I'm still getting this issue. Can anybody help me out? Here's my fragment, and the activity that sets it up (most of it is stock code taken directly from Facebook's example)
Fragment:
public class ConvoFragment extends Fragment {
String name;
ListView convos;
SwipeRefreshLayout rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
rootView = (SwipeRefreshLayout)inflater.inflate(R.layout.convos_fragment,
container, false);
convos = (ListView) rootView.findViewById(R.id.conversation_list);
name = getActivity().getSharedPreferences("global", 0).getString("myName", "");
Session session = Session.getActiveSession();
RequestAsyncTask req = new Request(session, "/me/inbox/", null, HttpMethod.GET, new Request.Callback()
{
public void onCompleted(Response response)
{
final Response resp = response;
try
{
if (response != null)
{
GraphObject asdf2 = response.getGraphObject();
Log.i("graphobject", response.toString());
//This logs the Session Provided to Request in unopened state error. Everything below will fail
JSONObject obj = asdf2.getInnerJSONObject();
JSONArray threads= obj.getJSONArray("data");
final ConvoAdapter adapter = new ConvoAdapter(getActivity(), convertArray(threads), name);
convos.setAdapter(adapter);
setupRefreshListener();
setupItemListener(adapter);
}
}
catch (JSONException e)
{
e.printStackTrace();
}
}
}).executeAsync();
return rootView;
}
So it fails right as it makes the request, because the request essentially returns null. Here's my activity that sets up the fragments:
public class LoginActivity extends AppCompatActivity {
private static final String USER_SKIPPED_LOGIN_KEY = "user_skipped_login";
private static final int SPLASH = 0;
public static final int FILE = 1;
public static final int CONVOS = 2;
public static final int SETTINGS = 3;
public static final int ABOUT = 4;
private static final int FRAGMENT_COUNT = ABOUT +1;
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
private Fragment[] fragments = new Fragment[FRAGMENT_COUNT];
private boolean isResumed = false;
private boolean userSkippedLogin = false;
private UiLifecycleHelper uiHelper;
private Session.StatusCallback callback = new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
userSkippedLogin = savedInstanceState.getBoolean(USER_SKIPPED_LOGIN_KEY);
}
uiHelper = new UiLifecycleHelper(this, callback);
uiHelper.onCreate(savedInstanceState);
setContentView(R.layout.login_activity);
getSupportActionBar().setLogo(R.drawable.chatstatssmall);
FragmentManager fm = getSupportFragmentManager();
MainFragment splashFragment = (MainFragment) fm.findFragmentById(R.id.splashFragment);
fragments[SPLASH] = splashFragment;
fragments[FILE] = fm.findFragmentById(R.id.fileFragment);
fragments[CONVOS] = fm.findFragmentById(R.id.convoFragment);
fragments[SETTINGS] = fm.findFragmentById(R.id.userSettingsFragment);
fragments[ABOUT] = fm.findFragmentById(R.id.aboutFragment);
FragmentTransaction transaction = fm.beginTransaction();
for(int i = 0; i < fragments.length; i++) {
transaction.hide(fragments[i]);
}
transaction.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
android.support.v7.app.ActionBar act = getSupportActionBar();
act.setTitle("Welcome to ChatStats!");
act.setHomeAsUpIndicator(R.drawable.chatstatssmall);
act.setHomeButtonEnabled(true);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_settings:
showFragment(SETTINGS, false);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public final static String extra_msg = "chatstats.passArray";
#Override
public void onResume() {
super.onResume();
uiHelper.onResume();
isResumed = true;
// Call the 'activateApp' method to log an app event for use in analytics and advertising reporting. Do so in
// the onResume methods of the primary Activities that an app may be launched into.
AppEventsLogger.activateApp(this);
}
#Override
public void onPause() {
super.onPause();
uiHelper.onPause();
isResumed = false;
// Call the 'deactivateApp' method to log an app event for use in analytics and advertising
// reporting. Do so in the onPause methods of the primary Activities that an app may be launched into.
AppEventsLogger.deactivateApp(this);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data);
}
#Override
public void onDestroy() {
super.onDestroy();
uiHelper.onDestroy();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
uiHelper.onSaveInstanceState(outState);
outState.putBoolean(USER_SKIPPED_LOGIN_KEY, userSkippedLogin);
}
#Override
protected void onResumeFragments() {
super.onResumeFragments();
Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
// if the session is already open, try to show the selection fragment
userSkippedLogin = false;
showFragment(FILE, false);
} else if (userSkippedLogin) {
showFragment(FILE, false);
} else {
// otherwise present the splash screen and ask the user to login, unless the user explicitly skipped.
showFragment(SPLASH, false);
}
}
public void startMainActivity(){
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (isResumed) {
FragmentManager manager = getSupportFragmentManager();
int backStackSize = manager.getBackStackEntryCount();
for (int i = 0; i < backStackSize; i++) {
manager.popBackStack();
}
// check for the OPENED state instead of session.isOpened() since for the
// OPENED_TOKEN_UPDATED state, the selection fragment should already be showing.
if (state.equals(SessionState.OPENED)) {
showFragment(FILE, false);
} else if (state.isClosed()) {
showFragment(SPLASH, false);
}
}
}
public void showFragment(int fragmentIndex, boolean addToBackStack) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
for (int i = 0; i < fragments.length; i++) {
if (i == fragmentIndex) {
transaction.show(fragments[i]);
} else {
transaction.hide(fragments[i]);
}
}
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.commit();
}
}
This uiHelper stuff is really confusing me. I'd appreciate if anybody could let me know what I might be doing wrong. I thought I followed the Facebook documentation (available here https://developers.facebook.com/docs/reference/android/3.23.1/class/UiLifecycleHelper/ ) exactly, but I'm still getting this error.
i am creating a application in which i am using preference Fragment with navigation Drawer my problem is i am created navigation Drawer and in which i am added some menu item in which i want to load the preference Fragment as a first element when the app loads.it is does as i don to display. when i am changing the options I-e.when i am changing the drawer menu options like second element the in the drawer menu fist view is not replacing with the second,it is overlapping an the first
my navigation drawer xml is as follow
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.koteswara.wise.NavigationDrawerMainActivity" >
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="#+id/drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_gravity="start" >
<ListView
android:id="#+id/drawer_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
tools:context="com.koteswara.wise.NavigationDrawerFragment" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
my preference fragment is like this
public class AutoAnswerPreferenceActivity extends PreferenceFragment implements OnSharedPreferenceChangeListener {
private AutoAnswerNotifier mNotifier;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference);
mNotifier = new AutoAnswerNotifier(getActivity());
mNotifier.updateNotification();
SharedPreferences sharedPreferences = getPreferenceManager().getSharedPreferences();
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onDestroy() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("enabled")) {
mNotifier.updateNotification();
}
}
}
my fragment class which is adding to load the PreferenceFragment is
public class AutoAnswarFragment extends Fragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getActivity().getFragmentManager().beginTransaction().replace(R.id.container, new AutoAnswerPreferenceActivity()) .commit();
}
the navigation Drawer class in which show fragment method is
protected void showFragment(int position) {
// TODO Auto-generated method stub
Fragment fragment = null;
switch (position) {
case 0:
fragment = new AutoAnswarFragment();
break;
case 1:
fragment = new Tab2();
break;
case 2:
// fragment = new BhajanaFragment();
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, fragment).commit();
// update selected item and title, then close the drawer
// mDrawerList.setItemChecked(position, true);
// mDrawerList.setSelection(position);
mTitle = mDrawer_title[position];
// mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
// Log.e("MainActivity", "Error in creating fragment");
}
}
}
if i will call the fragment other than the preference Fragment like below it will works please help me
public class Tab1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1,container,false);
return v;
}
}
i am struggling to clear the solution for it please any body solve it and please tell me the solution .i will be the thank full please help me
Be sure the root layout of all your fragments are having
android:background="#color/your_favorite_color"
In that way they will be hiding other fragments below.
on so many days of research and searching on the web i have found a solution its working fine for me for the above problem there is a link on the web as http://www.michenux.net/android-preferencefragmentcompat-906.html in this i found a sample apk and a source code regarding the apk . as this apk has a functionality as it solves my problem . i cleared the errors of the source code which will comes when you import and after that i added the library to my project. I used the PreferenceCompatFragment rather than PreferenceFragmentCompat, it solved my problem if anybody needs help it may help them also so that i am posting my solution to the above problem. and i thank who are all helped me who and all given some valuable suggestion for the above problem.
The below class below i have used instead of PreferenceFragmentCompat of v7 support library
public abstract class PreferenceCompatFragment extends Fragment {
private static final int FIRST_REQUEST_CODE = 100;
private static final int MSG_BIND_PREFERENCES = 1;
private static final String PREFERENCES_TAG = "android:preferences";
private boolean mHavePrefs;
private boolean mInitDone;
private ListView mList;
private PreferenceManager mPreferenceManager;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BIND_PREFERENCES:
bindPreferences();
break;
}
}
};
final private Runnable mRequestFocus = new Runnable() {
public void run() {
mList.focusableViewAvailable(mList);
}
};
private void bindPreferences() {
PreferenceScreen localPreferenceScreen = getPreferenceScreen();
if (localPreferenceScreen != null) {
ListView localListView = getListView();
localPreferenceScreen.bind(localListView);
}
}
private void ensureList() {
if (mList == null) {
View view = getView();
if (view == null) {
throw new IllegalStateException("Content view not yet created");
}
View listView = view.findViewById(android.R.id.list);
if (!(listView instanceof ListView)) {
throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class");
}
mList = (ListView)listView;
if (mList == null) {
throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'");
}
mHandler.post(mRequestFocus);
}
}
private void postBindPreferences() {
if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) {
mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
}
}
private void requirePreferenceManager() {
if (this.mPreferenceManager == null) {
throw new RuntimeException("This should be called after super.onCreate.");
}
}
public void addPreferencesFromIntent(Intent intent) {
requirePreferenceManager();
PreferenceScreen screen = inflateFromIntent(intent, getPreferenceScreen());
setPreferenceScreen(screen);
}
public void addPreferencesFromResource(int resId) {
requirePreferenceManager();
PreferenceScreen screen = inflateFromResource(getActivity(), resId, getPreferenceScreen());
setPreferenceScreen(screen);
}
public Preference findPreference(CharSequence key) {
if (mPreferenceManager == null) {
return null;
}
return mPreferenceManager.findPreference(key);
}
public ListView getListView() {
ensureList();
return mList;
}
public PreferenceManager getPreferenceManager() {
return mPreferenceManager;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getListView().setScrollBarStyle(0);
if (mHavePrefs) {
bindPreferences();
}
mInitDone = true;
if (savedInstanceState != null) {
Bundle localBundle = savedInstanceState.getBundle(PREFERENCES_TAG);
if (localBundle != null) {
PreferenceScreen screen = getPreferenceScreen();
if (screen != null) {
screen.restoreHierarchyState(localBundle);
}
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
dispatchActivityResult(requestCode, resultCode, data);
}
#Override
public void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
mPreferenceManager = createPreferenceManager();
}
#Override
public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle) {
return paramLayoutInflater.inflate(R.layout.preference_list_content, paramViewGroup, false);
}
#Override
public void onDestroy() {
super.onDestroy();
dispatchActivityDestroy();
}
#Override
public void onDestroyView() {
mList = null;
mHandler.removeCallbacks(mRequestFocus);
mHandler.removeMessages(MSG_BIND_PREFERENCES);
super.onDestroyView();
}
#Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
PreferenceScreen screen = getPreferenceScreen();
if (screen != null) {
Bundle localBundle = new Bundle();
screen.saveHierarchyState(localBundle);
bundle.putBundle(PREFERENCES_TAG, localBundle);
}
}
#Override
public void onStop() {
super.onStop();
dispatchActivityStop();
}
/** Access methods with visibility private **/
private PreferenceManager createPreferenceManager() {
try {
Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
c.setAccessible(true);
return c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private PreferenceScreen getPreferenceScreen() {
try {
Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
m.setAccessible(true);
return (PreferenceScreen) m.invoke(mPreferenceManager);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void setPreferenceScreen(PreferenceScreen preferenceScreen) {
try {
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
m.setAccessible(true);
boolean result = (Boolean) m.invoke(mPreferenceManager, preferenceScreen);
if (result && preferenceScreen != null) {
mHavePrefs = true;
if (mInitDone) {
postBindPreferences();
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
m.setAccessible(true);
m.invoke(mPreferenceManager, requestCode, resultCode, data);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void dispatchActivityDestroy() {
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
m.setAccessible(true);
m.invoke(mPreferenceManager);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void dispatchActivityStop() {
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
m.setAccessible(true);
m.invoke(mPreferenceManager);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void setFragment(PreferenceFragment preferenceFragment) {
try {
Method m = PreferenceManager.class.getDeclaredMethod("setFragment", PreferenceFragment.class);
m.setAccessible(true);
m.invoke(mPreferenceManager, preferenceFragment);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public PreferenceScreen inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences) {
PreferenceScreen preferenceScreen ;
try {
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
m.setAccessible(true);
preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, context, resId, rootPreferences);
} catch (Exception e) {
throw new RuntimeException(e);
}
return preferenceScreen;
}
public PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) {
PreferenceScreen preferenceScreen ;
try {
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class);
m.setAccessible(true);
preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, queryIntent, rootPreferences);
} catch (Exception e) {
throw new RuntimeException(e);
}
return preferenceScreen;
}
}
I have a tabbed application built with fragments and ActionBarSherlock. I have 7 tabs. Here's what's happening.
When I select any tab, the onCreate method for the associated fragment is called as expected. The problem is that the onCreate method is called for the next adjacent tab as well. For instance:
App starts in tab1 and onCreate is called as expected
tab2 onCreate is called as well (should not happen)
-------
Click on tab2 and onCreate is called as expected (even though it's already been called)
tab3 onCreate is called as well (should not happen)
-------
Click on tab6 and onCreate is called as expected
tab7 onCreate is called as well (should not happen)
-------
And really weird, click on tab7 (the last tab)
tab6 (2nd to last tab) onCreate is called as well (should not happen)
I've read a couple of possible problems and checked to make sure it's not happening here:
Not using unique tag for each tab (they are unique)
Emulator has bug that calls onCreate twice (I get the same behavior on my ICS device)
So it's not the two previous possibilities and I'll completely out of ideas. The program runs fine but loading two fragments (which are webviews) takes too much time and isn't the behavior I expected.
Here's my code for the main activity onCreate which creates the tab host:
EDITED:
public class SynergyWorldwideActivity extends SherlockFragmentActivity
{
//TabHost mTabHost;
ViewPager mViewPager;
TabsAdapter mTabsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set up the view pager
setContentView(R.layout.fragment_tabs_pager);
mViewPager = (ViewPager)findViewById(R.id.pager);
// Set up action bar
final ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayShowTitleEnabled(true);
//bar.setDisplayShowHomeEnabled(false);
// Creat tabs with bundled URLs
Bundle tab1Args=new Bundle(), tab2Args=new Bundle(), tab3Args=new Bundle(),
tab4Args=new Bundle(), tab5Args=new Bundle(), tab6Args=new Bundle(), tab7Args=new Bundle();
tab1Args.putString("tabURL", getString(R.string.webtab1_URL));
tab2Args.putString("tabURL", getString(R.string.webtab2_URL));
tab3Args.putString("tabURL", getString(R.string.webtab3_URL));
tab4Args.putString("tabURL", getString(R.string.webtab4_URL));
tab5Args.putString("tabURL", getString(R.string.webtab5_URL));
tab6Args.putString("tabURL", getString(R.string.webtab6_URL));
tab7Args.putString("tabURL", getString(R.string.webtab7_URL));
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab1_name)),
WebTabFragment.MyWebviewFragment.class, tab1Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab2_name)),
WebTabFragment.MyWebviewFragment.class, tab2Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab3_name)),
WebTabFragment.MyWebviewFragment.class, tab3Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab4_name)),
WebTabFragment.MyWebviewFragment.class, tab4Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab5_name)),
WebTabFragment.MyWebviewFragment.class, tab5Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab6_name)),
WebTabFragment.MyWebviewFragment.class, tab6Args);
mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.webtab7_name)),
WebTabFragment.MyWebviewFragment.class, tab7Args);
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
}
/**
* This is a helper class that implements the management of tabs and all
* details of connecting a ViewPager with associated TabHost. It relies on a
* trick. Normally a tab host has a simple API for supplying a View or
* Intent that each tab will show. This is not sufficient for switching
* between pages. So instead we make the content part of the tab host
* 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
* view to show as the tab content. It listens to changes in tabs, and takes
* care of switch to the correct paged in the ViewPager whenever the selected
* tab changes.
*/
public static class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener{
private final Context mContext;
//private final TabHost mTabHost;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(FragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = ((SherlockFragmentActivity) activity).getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
#Override
public int getCount()
{
int iCount = mTabs.size();
return iCount;
}
#Override
public Fragment getItem(int position)
{
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
}
#Override
public void onPageSelected(int position)
{
mActionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrollStateChanged(int state)
{
}
#Override
public void onTabSelected(Tab tab)
{
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
#Override
public void onTabUnselected(Tab tab)
{
}
#Override
public void onTabReselected(Tab tab)
{
}
}
}
Here's the code for the tab fragments:
EDITED:
public class WebTabFragment extends SherlockFragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState == null)
{
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentById(android.R.id.content) == null) {
MyWebviewFragment myWebView = new MyWebviewFragment();
fm.beginTransaction().add(android.R.id.content, myWebView).commit();
}
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//outState.putString("tabNumber", mTabNumber);
}
public static class MyWebviewFragment extends SherlockFragment {
final static private String tag = MyWebviewFragment.class.getSimpleName();
String mTabURL;
private WebView mWebView = null;
static final int REFRESH_ID = Menu.FIRST;
private ProgressDialog spinnerDlg;
#Override
public void onSaveInstanceState(Bundle outState)
{
if(mWebView.saveState(outState) == null)
Log.i(tag,"Saving state FAILED!");
else
Log.i(tag, "Saving state succeeded.");
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
#Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(Menu.NONE, REFRESH_ID, 0, getString(R.string.refresh_string))
.setIcon(R.drawable.ic_action_refresh)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
#Override public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case REFRESH_ID:
if(mWebView != null)
mWebView.reload();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* When creating, retrieve this instance's number from its arguments.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Tell the framework to try to keep this fragment around
// during a configuration change.
setRetainInstance(true);
mTabURL = getArguments() != null ? getArguments().getString("tabURL") : "http://www.google.com";
}
/**
* The Fragment's UI is just a simple text view showing its
* instance number.
*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Create view object to return
View v = inflater.inflate(R.layout.webview_layout, container, false);
// Set up webview object
if (mWebView != null) {
mWebView.destroy();
}
mWebView = (WebView)v.findViewById(R.id.webview_fragment);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setOnKeyListener(new OnKeyListener(){
#Override
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return false;
}
});
// Check to see if it has been saved and restore it if true
if(savedInstanceState != null)
{
if (savedInstanceState.isEmpty())
Log.i(tag, "Can't restore state because bundle is empty.");
else
{
if (mWebView.restoreState(savedInstanceState) == null)
Log.i(tag, "Restoring state FAILED!");
else
Log.i(tag, "Restoring state succeeded.");
}
}
else
{
// Load web page
mWebView.setWebViewClient(new MyWebViewClient());
mWebView.getSettings().setPluginsEnabled(true);
mWebView.getSettings().setBuiltInZoomControls(false);
mWebView.getSettings().setSupportZoom(false);
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.getSettings().setAllowFileAccess(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.loadUrl(mTabURL);
}
return v;
}
#Override
public void onDestroy()
{
super.onDestroy();
}
#Override
public void onDestroyView()
{
super.onDestroyView();
}
#Override
public void onPause()
{
super.onPause();
}
#Override
public void onResume()
{
super.onResume();
}
#Override
public void onConfigurationChanged(Configuration newConfig)
{
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
}
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// YouTube video link
if (url.startsWith("http://youtu.be"))
{
String urlSubString = url.substring("http://youtu.be/".length());
String newURL = String.format("http://www.youtube.com/v/%s", urlSubString);
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(newURL)));
return (true);
}
return (false);
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if(spinnerDlg == null)
{
spinnerDlg = new ProgressDialog(getActivity());
spinnerDlg.setMessage("Loading....");
spinnerDlg.show();
}
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if(spinnerDlg != null)
{
spinnerDlg.dismiss();
}
spinnerDlg = null;
}
}
}
}
Tabs count will start form 0 so in viewPager you have to set the screen limit like below
Example if you have 3 tabs just give
viewPager.setOffscreenPageLimit(2);
Thats one of the properties of tabs. It loads the second one so you aren't swiping to a null tab.. You're welcome to override the tab class and handle that yourself if you want :D.
If you are using fragments, consider using ViewPager. Its much easier to implement and faster in response.
example here,
http://android-developers.blogspot.com/2011/08/horizontal-view-swiping-with-viewpager.html
You say
onCreate is called as well (should not happen)
But that's exactly what should happen if you use ViewPager. How else would you see the fragment if you swipe it half way between the first and second tab?
If you tap on tab 2, it will be recreated maybe, because it is destroyed. Try to override getItemPosition like this:
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}