I created a simple project that Button in Activity click to Show Toast from Fragment.Works fine when just click Button, but after orientation changed and clicking Button occurs error.
public class MainActivity extends Activity {
PlaceholderFragment pf;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pf = new PlaceholderFragment();
Button b = (Button)findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
pf.showToast();
}
});
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, pf)
.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
Log.i("TAG", "onCreateView");
return rootView;
}
public void showToast(){
Toast.makeText(getActivity(), "Show Toast from PlaceholderFragment", Toast.LENGTH_SHORT).show();
}
#Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
Log.i("TAG", "onAttach");
}
#Override
public void onDetach() {
// TODO Auto-generated method stub
super.onDetach();
Log.i("TAG", "onDetach");
}
}
}
I found out Fragment was calling onAttach and onDetach after orientating. How can i fix this problem?
When the device Orientation changes, the activity in which the fragment sits is by default destroyed and created again. You can avoid these changes by adjusting the android:configChanges in the manifest file. This code should work:
android:configChanges="keyboardHidden|orientation"
Related
I am using options menu in message fragment where I can add friends from menu. I can navigate to this fragment from activity or fragment. When I launch this message fragment, menu is working fine. When I do navigate through other screen and come to message fragment menu disappears. After using/navigating in the application for 4-5 minutes, menu starts behaving randomly.
Strange behavior is, when I do launch message fragment from activity, menu always works well. This behaves randomly when I launch it from fragment.
Here is my code
public class MessagesFragment extends BaseFragment{
private static final String TAG = MessagesFragment.class.getSimpleName();
Context mContext;
View mView;
private ListView listBuddy;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mContext = activity;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setHasOptionsMenu(true);
((InnerActivity)getActivity()).setActionbarTitle(getResources().getString(R.string.my_buddies));
View v = inflater.inflate(R.layout.fragment_messages, container, false);
listBuddy = (ListView) v.findViewById(R.id.listViewFindBuddy);
this.mView = v;
return v;
}
#Override
public void onDetach() {
// TODO Auto-generated method stub
super.onDetach();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
#Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
}
#Override
public void onStop() {
// TODO Auto-generated method stub
super.onStop();
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
// TODO Auto-generated method stub
super.setUserVisibleHint(isVisibleToUser);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.messages, menu);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_add:
break;
}
return super.onOptionsItemSelected(item);
}
Activity
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
return super.onPrepareOptionsMenu(menu);
}
add the following code in your activity :
#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;
}
I have a Fragment that interfaces OnWeekViewClickListener as such:
public interface OnWeekViewClickListener {
// TODO: Update argument type and name
public void onWeekViewClick();
}
I assign the listener during the onAttach method as such:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.activity = activity;
try {
mListener = (OnWeekViewClickListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
yet my Activity that implements OnWeekViewClickListener never receives a call back? Nor any errors?
Here is that activity:
public class RoomDetailsActivity extends FragmentActivity implements RoomAmenityHorizontalViewer.OnFragmentInteractionListener, DayScheduleViewer.OnWeekViewClickListener {
private RoomAmenityHorizontalViewer amenityFrag = RoomAmenityHorizontalViewer.newInstance();
private DayScheduleViewer dayFrag = DayScheduleViewer.newInstance();
private FrameLayout dayViewFrame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(getWindow().FEATURE_NO_TITLE);
setContentView(R.layout.detail_view_info);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.room_amenity_spinner_view, amenityFrag, "amenityFrag");
transaction.replace(R.id.room_dayview_layout, dayFrag, "dayFrag");
transaction.commit();
ImageButton backButton = (ImageButton) findViewById(R.id.roomDetailsBackBtn);
backButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent myBackIntent = new Intent(getBaseContext(), ProximityActivity.class);
startActivity(myBackIntent);
}
});
RoundedImageView pinOverlay = (RoundedImageView) findViewById(R.id.imageView4);
ImageView roomImage = (ImageView) findViewById(R.id.roomImageView);
}
#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_room_details, 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);
}
#Override
public void onWeekViewClick() {
Log.v("Fragment Interaction", "Fragment item touched!");
}
#Override
public void onFragmentInteraction(Uri uri) {
}
}
Here the fragment is calling the listener:
myWeekView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.onWeekViewClick();
}
});
Im trying to implement Interstitial Ads in my app. Im using a handler with postDelayed to delay the showing of the interstitial ad by 10 seconds.
My small app uses fragments. I have fragment 1 which contains a button to go to fragment 2 via fragment replacement transaction.
A problem im having is multiple instances of the same task being made which results into more than 1 interstitial ad showing (which is not good). This happens if you go into fragment 2, press back and then go into fragment 2 again.
What I want is a way to only allow a single handler (1 message) for this runnable. To prevent multiple ads from appearing
My main activity
public class MainActivity extends ActionBarActivity {
private ViewGroup container;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null)
{
container = (ViewGroup)findViewById(R.id.container);
if(container != null)
{
Fragment1 fragment1 = new Fragment1();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(container.getId(), fragment1, Fragment1.class.getName());
fragmentTransaction.commit();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onResume()
{
// TODO Auto-generated method stub
super.onResume();
int isAvaiable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(isAvaiable == ConnectionResult.SUCCESS)
{
Log.d("TEST", "GPS IS OK");
}
else if(isAvaiable == ConnectionResult.SERVICE_MISSING ||
isAvaiable == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED ||
isAvaiable == ConnectionResult.SERVICE_DISABLED)
{
GooglePlayServicesUtil.getErrorDialog(isAvaiable, this, 10).show();
}
}
}
Fragment 1
public class Fragment1 extends Fragment implements OnClickListener {
private Button bFragmentB;
private ViewGroup container;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_1, container, false);
this.container = container;
bFragmentB = (Button)view.findViewById(R.id.bFragmentB);
bFragmentB.setOnClickListener(this);
return view;
}
#Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
switch(arg0.getId())
{
case R.id.bFragmentB:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(container.getId(),new Fragment2(),Fragment2.class.getName());
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
}
}
}
Fragment 2 (which contains the interstitial ad)
public class Fragment2 extends Fragment
{
private Handler handler = new Handler();
private InterstitialAd interstitialAd;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_2, container, false);
return view;
}
#Override
public void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
interstitialAd = new InterstitialAd(getActivity());
interstitialAd.setAdUnitId(getResources().getString(R.string.banner_ad_unit_id));
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
interstitialAd.loadAd(adRequest);
interstitialAd.setAdListener(new AdListener()
{
#Override
public void onAdLoaded()
{
handler.postDelayed(showInterstitialAd, 10000);
}
});
}
private Runnable showInterstitialAd = new Runnable()
{
#Override
public void run()
{
interstitialAd.show();
}
};
}
Here is a summary of the things I have tried but did not work
On fragment B onDestroy I have this code
#Override
public void onDestroy()
{
super.onDestroy();
handler.removeCallbacks(showInterstitialAd);
}
Still resulted in more than 1 instance of the task (2 ads appearing). Also is not good if the screen rotates anyway because the task would be destroyed from my understanding.
Another attempt at things
interstitialAd.setAdListener(new AdListener()
{
#Override
public void onAdLoaded()
{
if(!handler.hasMessages(1))
{
handler.sendEmptyMessage(1);
handler.postDelayed(showInterstitialAd, 10000);
}
//else do nothing
}
});
This one was pretty stupid considering a new hander object is made at the start so it would not have a message to begin with :D. The idea was to have message in the queue of 1 and if it sees 1 existing already then do not start another handler.
Looks like your old fragment2 is not getting full destryoed/GC'ed yet.
Since we are trying to get hold of the existing callback, which we created in old fragment, we need to save a reference to it, so we can delete it from handler message queue. You can do this by saving it in Application level global.
public class Global extends Application {
public Runnable oldshowInterstitialAd = null;
}
update your manifest Application with
<application android:name=".Global"
add the handler.removeCallbacks(oldshowInterstitialAd); just before posting a new one.
public void onAdLoaded()
{
handler.removeCallbacks(((Global)getApplicationContext()).oldshowInterstitialAd);
handler.postDelayed(showInterstitialAd, 10000);
((Global)getApplicationContext()).oldshowInterstitialAd = showInterstitialAd;
}
saving a reference to old fragment's member may hinder its GC'ing, but we loose the reference anyways as we update oldshowInterstitialAd with newer one.
So i've just started doing some android programing, and I'm already stuck! My problem is; I want want my fragment, from MainActivity, to NOT be a part of my new Activity. I want the activity to be all blank, the fragment from MainActivity should be gone, buuut it's not.
The content from the "fragmentz" xml document, which is "linked" in the Fragment Class. Should NOT appear in the second Activity... Where in the SecondActivity have I associated it with the Fragment Class? This is getting frustrating :D
So here is my MainActivity code:
public class MainActivity extends ActionBarActivity {
FragmentManager manager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
manager= getSupportFragmentManager();
ArticleFragment frag = new ArticleFragment();
FragmentTransaction transaction = manager.beginTransaction();
transaction = manager.beginTransaction();
transaction.add(R.id.fragmentet,frag,"tagg");
transaction.commit();
// here the Fragment should be added to my MainActiviy
}
public void WalkForward(View view)
{
ArticleFragment frag = (ArticleFragment) manager.findFragmentByTag("tagg");
FragmentTransaction transaction = manager.beginTransaction();
transaction.remove(frag);
transaction.commit();
// Here, the fragment should disappear before the new activity start
Intent intenten = new Intent(this, SecondActivity.class);
startActivity(intenten);
// Start new activity
finish();
// I've tried this finish method, and also onDestroy and so on... But that work either. I thought the Fragments should
// disappear with its activity?
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}
}
My Fragment Class:
public class ArticleFragment extends Fragment {
public void onAttach(Activity activity)
{
Log.d("Fraggment", "onAttach");
super.onAttach(activity);
// #17 Android FragmentTransaction Part 2: Android Application Development Development [HD 1080p]
}
public void onCreate(Bundle saveInstanceState)
{
Log.d("Fraggment", "onCreate");
super.onCreate(saveInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragmentz, container, false);
}
public void onActivityCreate(Bundle saveInstanceState)
{
Log.d("Fraggment", "onActivityCreated");
super.onActivityCreated(saveInstanceState);
}
public void onPause()
{
super.onPause();
Log.d("Fraggment", "onPause");
}
public void onStop()
{
super.onStop();
Log.d("Fraggment", "onStop");
}
public void onDestroyView()
{
super.onDestroyView();
Log.d("Fraggment", "onDestroyView");
}
public void onDestroy()
{
super.onDestroy();
Log.d("Fraggment", "onDestroy");
}
public void onDetach()
{
super.onDetach();
Log.d("Fraggment", "onDetach");
}
And my Second Activity Class:
public class SecondActivity extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.second, 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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_second,
container, false);
return rootView;
}
}
}
I hope you understand what I mean :P Is there anything I can do? Thanks in advance!
Remove this
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
from your Second Activity. And why are you extending MainActivity? Some Reason?
This question already has answers here:
NullPointerException accessing views in onCreate()
(13 answers)
Closed 8 years ago.
I have a very simple android app being built. I have 2 buttons and 1 textview. I build them graphically in fragment_main.xml. Below is my full codes.
public class MainActivity extends ActionBarActivity {
TextView tvOut;
Button btnOk;
Button btnCancel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
View.OnClickListener oclBtnOk = new View.OnClickListener() {
public void onClick(View v) {
// change text of the TextView (tvOut)
tvOut.setText("Button OK clicked");
}
};
btnOk.setOnClickListener(oclBtnOk);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
If I comment this part of the codes it works well.
View.OnClickListener oclBtnOk = new View.OnClickListener() {
public void onClick(View v) {
// change text of the TextView (tvOut)
tvOut.setText("Button OK clicked");
}
};
btnOk.setOnClickListener(oclBtnOk);
Even though I use setContentView(R.layout.main_activity); all my button and text view appears and quite puzzle why even with main_activity my buttons and text view appears well.
You never assign values to your views. Use findViewById to get references to the views with the id's you gave them in your XML layout.
setContentView(R.layout.fragment_main);
// get the views
btnOk = (BUtton) findViewById(R.id.your_button_id);
tvOut = (TextView) findViewById(R.id.another_id);
btnOk.setOnClickListener(...);