On Android how to call from TextView inside a fragment? - android-fragments

I am trying to call when someone tap or click on a number which in a TextView.
I have added permission in Android AndroidMainfest.xml
<uses-permission android:name="android.permission.CALL_PHONE" />
Also I have set the TextView android:clickable="true"
I am very new in Android development so please Help me.
I am sorry for my bad English.
Here is My code AboutDeveloper.java
package com.rupomkhondaker.sonalibank;
import android.app.Fragment;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class AboutDeveloper extends Fragment {
public AboutDeveloper(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final TextView tv_phone = (TextView)getActivity().findViewById(R.id.devMobile);
tv_phone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String phone_no= tv_phone.getText().toString().replaceAll(":", "");
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+phone_no));
startActivity(callIntent);
}
});
View rootView = inflater.inflate(R.layout.fragment_developer, container, false);
return rootView;
}
}
ERROR LOG
09-20 20:28:05.852 622-622/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.rupomkhondaker.sonalibank.AboutDeveloper.onCreateView(AboutDeveloper.java:22)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:829)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035)
at android.app.BackStackRecord.run(BackStackRecord.java:635)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)

Replace your code by this code and tell me what is the output.
public class AboutDeveloper extends Fragment {
public AboutDeveloper(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_developer, container, false);
final TextView tv_phone = (TextView)v.findViewById(R.id.devMobile);
tv_phone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
try
{
String uri = "tel:"+tv_phone.getText().toString();
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(uri));
startActivity(callIntent);
}
catch(Exception e) {
Toast.makeText(getActivity(),"Your call has failed...",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
});
return v;
}
Since you were getting
java.lang.NullPointerException
at com.rupomkhondaker.sonalibank.AboutDeveloper.onCreateView(AboutDeveloper.java:22)
it meant that it was not able to find the view element.

Related

NPE on clickListener in recyclerView in fragment when rotating Android app

I am having an issue with a NPE on a clickListener on a RecyclerView which is in a fragment. Initially it works fine with it displaying a toast message, but when I rotate the device and touch any icon I get:
java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.android.newswiz.OnItemClickListener.onItemClick(java.lang.String)' on a null object reference
at com.example.android.newswiz.Fragments.PublishersSlidePageFragment$PublishersAdapter$PublishersAdapterViewHolder$1.onClick(PublishersSlidePageFragment.java:86)
Here is my Fragment class. I have commented the part where there is the NPE in the logs:
package com.example.android.newswiz.Fragments;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.android.newswiz.OnItemClickListener;
import com.example.android.newswiz.R;
public class PublishersSlidePageFragment extends Fragment {
public OnItemClickListener listener;
public PublishersSlidePageFragment(){}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle
savedInstanceState) {
ViewGroup rootView = (ViewGroup)
inflater.inflate(R.layout.fragment_publishers_slide_page,
container, false);
RecyclerView mRecyclerView =
rootView.findViewById(R.id.recyclerView_publishers);
int numberOfColumns =
Integer.parseInt(getContext().getResources().getString(R.string.no_of_cols));
mRecyclerView.setLayoutManager(new GridLayoutManager(getContext(),
numberOfColumns));
mRecyclerView.setHasFixedSize(true);
PublishersAdapter mAdapter = new PublishersAdapter();
mRecyclerView.setAdapter(mAdapter);
return rootView;
}
public void setListener(OnItemClickListener onItemClickListener) {
this.listener = onItemClickListener;
}
public class PublishersAdapter extends RecyclerView.Adapter<PublishersAdapter.PublishersAdapterViewHolder>{
#NonNull
#Override
public PublishersAdapter.PublishersAdapterViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.publisher_item, parent, false);
return new PublishersAdapterViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PublishersAdapter.PublishersAdapterViewHolder holder, int position) {
holder.mPublisherImageView.setImageResource(mThumbIds[position]);
holder.mPublisherTextView.setText(mPublishers[position]);
holder.bind(mPublishers[position], listener);
}
#Override
public int getItemCount() {
return mThumbIds.length;
}
public class PublishersAdapterViewHolder extends RecyclerView.ViewHolder {
private final ImageView mPublisherImageView;
private final TextView mPublisherTextView;
public PublishersAdapterViewHolder(View itemView) {
super(itemView);
mPublisherImageView = itemView.findViewById(R.id.publisher_icon);
mPublisherTextView = itemView.findViewById(R.id.publisher_desc);
}
public void bind(final String mPublisher, final OnItemClickListener clickListener) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
clickListener.onItemClick(mPublisher); //NPE on this line
}
});
}
}
}
// references to the images
private Integer[] mThumbIds = {
R.drawable.abc_news, R.drawable.abc_news_au,
R.drawable.aftenposten, R.drawable.aljazeera_english,
R.drawable.bbc, R.drawable.cbs_news,
R.drawable.cnn_news, R.drawable.entertainment_weekly,
R.drawable.espn, R.drawable.financial_post,
R.drawable.financial_times, R.drawable.fox_news,
R.drawable.fox_sports, R.drawable.ign,
R.drawable.independent, R.drawable.lequipe,
R.drawable.metro, R.drawable.msnbc,
R.drawable.mtvnews, R.drawable.nat_geo,
R.drawable.nbc_news, R.drawable.new_scientist,
R.drawable.new_york_magazine, R.drawable.talk_sport,
R.drawable.techradar, R.drawable.the_guardian,
R.drawable.the_nyt, R.drawable.wsj
};
private String[] mPublishers = {"ABC News", "ABC News (AU)", "Aftenposten", "AlJazeera (ENG)"
, "BBC", "CBS News", "CNN News", "Entertainment Weekly", "ESPN", "Financial Post",
"Financial Times", "Fox News", "Fox Sports", "IGN", "Independent", "L'Equipe",
"Metro", "MSNBC", "MTV News", "Nat. Geo.", "NBC News", "New Scientist",
"NY Magazine", "Talk Sport", "TechRadar", "The Guardian", "NYT",
"Wall Street Journal"};
}
The Fragment class and listener are initialized in the Main Activity:
public class MainActivity extends AppCompatActivity {
private ViewPager mPager;
private SectionsPageAdapter mSectionsPageAdapter;
private Context context;
private TabLayout tabLayout;
private OnItemClickListener publisherClickListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
// Login authentication code ....
//Set up the ViewPager and PagerAdapter
mSectionsPageAdapter = new
SectionsPageAdapter(getSupportFragmentManager());
mPager = findViewById(R.id.sources_container);
setupViewPager(mPager);
tabLayout = findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mPager);
}
//FIXME NPE on listener object if you rotate screen and touch icon
private void setupViewPager(ViewPager mPager) {
SectionsPageAdapter adapter = new SectionsPageAdapter(getSupportFragmentManager());
PublishersSlidePageFragment publishersSlidePageFragment = new PublishersSlidePageFragment();
publisherClickListener = new OnItemClickListener() {
#Override
public void onItemClick(String item) {
Toast.makeText(context, "You have selected " + item, Toast.LENGTH_SHORT).show();
}
};
publishersSlidePageFragment.setListener(publisherClickListener);
adapter.addFragment(publishersSlidePageFragment, "Publishers");
adapter.addFragment(new CategoriesSlidePageFragment(), "Categories");
adapter.addFragment(new CountriesSlidePageFragment(), "Countries");
mPager.setAdapter(adapter);
}
I find it very weird that it is fine to recreate the fragments when the screen is rotated but is unable to make a new clickListener to the fragment. I have searched StackOverflow and found Save interface (Listener) in onSaveInstanceState to be of use but I don't think in my situation it is good practice to save the listener. I want to make a new listener and just set it on the Recycler View within the fragment. I might be missing something trivial but can anyone advise?
I don't have enough rep to comment, so I'll provide what I believe could be the answer...
First, I noticed that there is no reference to the View "itemView" passed into the method "bind(final String mPublisher, final OnItemClickListener clickListener)" and I don't see it globally available. Not sure why it would run once and NPE after screen rotation though.
So, this points me to not saving the fragments instance. Something is being destroyed when you rotate your device, and if the log is correct, it's saying that is the variable mPublisher is being passed in as null.
mPublishers exists the first time the fragment is created, but looks like it's being destroyed / not recreated on an orientation change.
First thing I would try is setRetainInstance(true) to save the fragments instance across config changes. I have been setting it in onCreate(), but I see no reason you can't set it in onCreateView().
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
if (DEBUG) Log.i(TAG, "onCreate(Bundle)");
super.onCreate(savedInstanceState);
// retain this fragment across configuration changes
setRetainInstance(true);
}
If that doesn't do it automatically for you, save the publisher list when the fragment is being recreated. This is done in onSaveInstanceState() of your fragment.
#Override
public void onSaveInstanceState(#NonNull Bundle bundle) {
if (DEBUG) Log.i(TAG, "onSaveInstanceState(Bundle)");
// make sure to call the super method so that the states of our views are saved
super.onSaveInstanceState(bundle);
// save our own state variables
bundle.putStringArray("publishers", mPublishers);
}
Then you can restore them in your onCreateView() method.
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_publishers_slide_page, container, false);
RecyclerView mRecyclerView = rootView.findViewById(R.id.recyclerView_publishers);
int numberOfColumns = Integer.parseInt(getContext().getResources().getString(R.string.no_of_cols));
mRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), numberOfColumns));
mRecyclerView.setHasFixedSize(true);
PublishersAdapter mAdapter = new PublishersAdapter();
mRecyclerView.setAdapter(mAdapter);
// if we have a savedInstanceState, restore the Fragment
if (savedInstanceState != null) {
mPublishers = savedInstanceState.getStringArray("publishers");
}
return rootView;
}
You may have to do this for other variables as well, such as your mThumbIds array.
The solution was actually a simple fix - I actually needed to define an OnItemClickListener interface in the Fragment class. Then override the onAttach method to set the listener to the context. Previously I just made a separate interface.
So in the Fragment class:
public class PublishersSlidePageFragment extends Fragment {
private OnItemClickListener listener;
public PublishersSlidePageFragment(){}
public interface OnItemClickListener{
void onItemClick(String item);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (OnItemClickListener) context;
}
// ... rest of code
Then in the MainActivity, declare that you will implement the PublishersSlidePageFragment.OnItemClickListener:
public class MainActivity extends AppCompatActivity implements PublishersSlidePageFragment.OnItemClickListener {
Then that class needs to implement the listener method:
#Override
public void onItemClick(String item) {
Toast.makeText(context, "You have clicked " + item, Toast.LENGTH_SHORT).show();
}

How to change TextView in fragment in on create or when a button is called

Almost 10 hours am I searching for an answer. Why my app crashes when i launch it.
What I realy want is a function that when I click OK on Edittext, text will be written on Text view. But first just hat to set text in on create in class that extence fragment.
package youtube.demo.youtubedemo.Fragments.Calculator_list;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import youtube.demo.youtubedemo.R;
public class Calculator_list extends Fragment {
View view;
FragmentManager fragmentManager;
public Calculator_list() {
}
TextView Damage1pise;
EditText Damage1beri;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_calculator_list, container, false);
Damage1beri = (EditText) view.findViewById(R.id.Game1_read_dmg_list_Player1);
Damage1pise = (TextView)view.findViewById(R.id.Game1_writen_dmg_list_Player1);
Damage1pise.setText("123");
return view;
}
public TextView Returnelement ()
{
return Damage1pise;
}
#Override
public void onCreate(Bundle savedInstanceState) {
Damage1pise = (TextView)getView().findViewById(R.id.Game1_writen_dmg_list_Player1);
Damage1pise.setText("1234");
super.onCreate(savedInstanceState);
}
}
What I realy want is a funcction that when I click OK on Edittext, text will be written on Text view
public void OnButton1click(View v)
{
Damage1.settext(v.text)
// This is hard coded, First I want to set text on create then go on whit the code
}
Here are the errors.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: youtube.demo.youtubedemo, PID: 2736
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at youtube.demo.youtubedemo.Fragments.Calculator_list.Calculator_list.onCreate(Calculator_list.java:47)
at android.app.Fragment.performCreate(Fragment.java:2335)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:949)
at android.app.BackStackRecord.setLastIn(BackStackRecord.java:857)
at android.app.BackStackRecord.calculateFragments(BackStackRecord.java:897)
at android.app.BackStackRecord.run(BackStackRecord.java:727)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1578)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:483)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
On this line of your showed code, both methods, certify yourself you have a blank space between (TextView) and the end of the sentence, like below:
Damage1pise = (TextView) getView().findViewById(R.id.Game1_writen_dmg_list_Player1);
Also, certify yourself you have a textview on your invoked layout file xml with name Game1_writen_dmg_list_Player1, because the error is been raised by a null reference, i.e.: you're invoking a not found element (maybe written with two ts?).

How do I make an activity wait until Facebook login is complete?

I am trying to make an application for the Android platform. So far I have two activities. Both have fragments. The first activity at the moment is using the Facebook api so that users can sign in. I want my first activity to switch to the second activity once the login is complete. I tried using an onClickListener with an intent, but the second activity would start before the login was completed. I have sense reverted my code to the point where there is no onClicklistener or intent. Any help would be appreciated. I did try reading the documentation for intents and activities, but I couldn't figure out how to do what I wanted. I will post my code bellow.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#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_main, menu);
return true;
}
#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);
}
}
next
package com.tfs.taylor.retreat;
import android.content.Intent;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.facebook.AccessToken;
import com.facebook.AccessTokenTracker;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.FacebookSdk;
import com.facebook.Profile;
import com.facebook.ProfileTracker;
import com.facebook.login.LoginResult;
import com.facebook.login.widget.LoginButton;
/**
* A placeholder fragment containing a simple view.
*/
public class MainFragment extends Fragment {
private TextView mTextDetails;
private AccessTokenTracker mTokenTracker;
private ProfileTracker mProfileTracker;
private CallbackManager mCallBackManager;
private FacebookCallback<LoginResult> mCallBack= new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
AccessToken accessToken = loginResult.getAccessToken();
Profile profile = Profile.getCurrentProfile();
displayWelcomeMessage(profile);
}
#Override
public void onCancel() {
}
#Override
public void onError(FacebookException e) {
}
};
public MainFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(getActivity().getApplicationContext());
mCallBackManager=CallbackManager.Factory.create();
mTokenTracker=new AccessTokenTracker() {
#Override
protected void onCurrentAccessTokenChanged(AccessToken oldToken, AccessToken newToken) {
}
};
mProfileTracker=new ProfileTracker() {
#Override
protected void onCurrentProfileChanged(Profile oldprofile, Profile newprofile) {
}
};
mTokenTracker.startTracking();
mProfileTracker.startTracking();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
private void displayWelcomeMessage(Profile profile) {
if (profile != null) {
mTextDetails.setText("Welcome " + profile.getName());
}
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LoginButton loginButton = (LoginButton) view.findViewById(R.id.login_button);
loginButton.setReadPermissions("public_profile");
loginButton.setFragment(this);
loginButton.registerCallback(mCallBackManager, mCallBack);
mTextDetails=(TextView) view.findViewById(R.id.text_details);
}
#Override
public void onResume() {
super.onResume();
Profile profile = Profile.getCurrentProfile();
displayWelcomeMessage(profile);
}
#Override
public void onStop() {
super.onStop();
mTokenTracker.stopTracking();
mProfileTracker.stopTracking();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mCallBackManager.onActivityResult(requestCode,resultCode,data);
}
}
You have to call new activity in your onSuccess method. By this your activity is called only after user logged in Successfully.
private FacebookCallback<LoginResult> mCallBack= new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
AccessToken accessToken = loginResult.getAccessToken();
Profile profile = Profile.getCurrentProfile();
displayWelcomeMessage(profile);
//call new activity here.
}

java.lang.RuntimeException: Unable to start activity ComponentInfo java.lang.IllegalStateException:Fragment not attached to Activity

I'm working with a fragment but its always throwing the error that it cannot start the activity because the fragmentis not attached to the activity,
kindly assist me figure out where I'm messing
Below is my code for the Fragment and Activity:
Fragment
package com.sarham.kabs.fruity;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ListFragment;
import android.support.v7.app.ActionBarDrawerToggle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import adapters.CategoriesListAdapter;
/**
* Created by Kabunyi Wanja on 22/03/2015.
*/
public class CategoriesFragment extends ListFragment {
private ListView categoriesListView;
private String[] categoriesArray = getResources().getStringArray(R.array.drawer_list);
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.categories_fragment, container, false);
categoriesListView = (ListView)v.findViewById(android.R.id.list);
//setCategoriesListAdapter();
//Log.d("ADAPTER: ", "Adapter has been set for listview");
return v;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setCategoriesListAdapter();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
//set adapter to categoriesListView
public void setCategoriesListAdapter(){
categoriesListView.setAdapter(new CategoriesListAdapter(getActivity(), categoriesArray));
}
}
Activity
package com.sarham.kabs.fruity;
import android.content.res.Configuration;
import android.os.PersistableBundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.app.ActionBarDrawerToggle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity implements AdapterView.OnItemClickListener{
private DrawerLayout drawerLayout;
private ListView listView;
private String[] planets;
private ActionBarDrawerToggle drawerListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawerLayout = (DrawerLayout)findViewById(R.id.drawerLayout);
listView = (ListView)findViewById(R.id.drawerListView);
planets = getResources().getStringArray(R.array.planets);
listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, planets));
listView.setOnItemClickListener(this);
drawerListener = new ActionBarDrawerToggle(this, drawerLayout,R.string.drawer_open, R.string.drawer_close){
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
Toast.makeText(MainActivity.this,"Drawer Open", Toast.LENGTH_LONG).show();
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
Toast.makeText(MainActivity.this, "Drawer Closed", Toast.LENGTH_LONG).show();
}
};
drawerLayout.setDrawerListener(drawerListener);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
CategoriesFragment categories = new CategoriesFragment();
addFragment(R.id.drawerLayout, categories, "CATEGORIES");
}
#Override
public void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onPostCreate(savedInstanceState, persistentState);
drawerListener.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerListener.onConfigurationChanged(newConfig);
}
#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_main, menu);
return true;
}
#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.
if(drawerListener.onOptionsItemSelected(item)){
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this, planets[position]+" Was selected", Toast.LENGTH_SHORT).show();
selectItem(position);
switch (position){
case 0:
CategoriesFragment categories = new CategoriesFragment();
addFragment(R.id.drawerLayout, categories, "CATEGORIES");
break;
case 1:
Toast.makeText(this, "Settings was selected", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(this, "Exit was selected", Toast.LENGTH_SHORT).show();
finish();
break;
default:
}
}
public void selectItem(int position){
listView.setItemChecked(position, true);
setTitle(planets[position]);
}
//set ActionBar title
public void setTitle(String title){
getSupportActionBar().setTitle(title);
}
//call this method to add a fragment
public void addFragment(int containerViewId, Fragment fragment, String tag){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(containerViewId, fragment, tag);
transaction.commit();
}
}
Below is the LogCat ouput:
Caused by: java.lang.IllegalStateException: Fragment CategoriesFragment{41545e80} not attached to Activity
at android.support.v4.app.Fragment.getResources(Fragment.java:619)
at com.sarham.kabs.fruity.CategoriesFragment.<init>(CategoriesFragment.java:21)
at com.sarham.kabs.fruity.MainActivity.onCreate(MainActivity.java:55)
at android.app.Activity.performCreate(Activity.java:5020)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211)
            at android.app.ActivityThread.access$600(ActivityThread.java:149)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1300)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:153)
            at android.app.ActivityThread.main(ActivityThread.java:5086)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
            at dalvik.system.NativeStart.main(Native Method)
On carefull analysis of the Fragment lifecycle, Its not possible to carry out operations like fetching of string resources using the getResources().getStringArray(...) as I was doing, this has to be done within the method onActivityCreated(...)

Which lifecycle callback is called when a fragment pager adapter's fragment comes to screen?

I want to detect when a particular fragment of three fragments I have set up with a ViewPager comes on to screen. I have 3 fragments in the viewpager and have set up the viewpager with
mViewPager.setOffscreenPageLimit(2);
so all three fragments are constructed at once (since it stores 2 on each side). I checked that Fragment.onResume() is called just once and not when each fragment comes to the foreground. Is there another callback to ensure I can catch this event and send some analytics signal for it?
Thanks
You can use the ViewPager.setOnPageChangeListener() to set a ViewPager.OnPageChangeListener().
Use the listener for the selected page based on its position in the PagerAdapter.
Here's my sample app:
package net.ynotapps.testviewpagerfragment;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.ButterKnife;
import butterknife.InjectView;
public class MainActivity extends ActionBarActivity {
#InjectView(R.id.pager)
ViewPager pager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
CustomPagerAdapter adapter = new CustomPagerAdapter(getSupportFragmentManager());
pager.setAdapter(adapter);
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
// Put Code here //
// Example code //
if (position == 2) {
Toast.makeText(MainActivity.this, "Found Position 2 fragment", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
public static class CustomPagerAdapter extends FragmentPagerAdapter {
public CustomPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
CustomFragment fragment = new CustomFragment();
Bundle bundle = new Bundle();
bundle.putString("display_text", String.format("Fragment %d is here.", position));
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return 5;
}
}
public static class CustomFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
TextView tv = new TextView(getActivity());
tv.setText(getArguments().getString("display_text"));
return tv;
}
}
}
ViewPager source code:
// Dispatch the change to any listeners
if (mAdapterChangeListeners != null && !mAdapterChangeListeners.isEmpty()) {
for (int i = 0, count = mAdapterChangeListeners.size(); i < count; i++) {
mAdapterChangeListeners.get(i).onAdapterChanged(this, oldAdapter, adapter);
}
}
So, you can use the ViewPager.addOnAdapterChangeListener to listen the callback.

Resources