I have a tabbed app with four Fragments. To handle them i extend FragmentPagerAdapter and use a FragmentManager, mFragmentManager.
In one of these Fragments i need to press a button and display another Fragment(but back should of course go back to the old one).
Now i tried using an interface where this method is called when the user presses that button:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
......
switch(position){
case 0:
if(mFragmentAtHome ==null)
{
mFragmentAtHome = HomeScreenFragment.newInstance(new HomeScreenFragmentListener()
{
public void onSwitchToCreateCity() {
mFragmentOnHome = All_media.newInstance(aml);
mFragmentManager.beginTransaction().add(mFragmentOnHome,"allMfrag").commit();
notifyDataSetChanged();
//Lets see what the manager looks like
System.out.println("mFragmentManager:");
System.out.println(mFragmentManager.getFragments().toString());
}
});
}
return mFragmentAtHome;
case1:...
But somehow my fragment is not displayed. Still logcat tells me it is on the mFragmentManager:
mFragmentManager:
[HomeScreenFragment{41798e80 #0 id=0x7f050028 android:switcher:2131034152:0},
MyTripsFragment{4170d5d0 #1 id=0x7f050028 android:switcher:2131034152:1},
All_media{418f5f50 #2 allMfrag}]
But it doesn't have an id, or a android:switcher something.
What can i do?
Thanks!
Related
Apparently I have a scenario where my launcher activity is splash screen which contains a handler class to show animation on start.
handler.postDelayed(new Runnable() {
#Override
public void run() {
//animation coder inside
}, 5);
After it is launched the app then navigates to next activity i.e. Home Activity. This activity is basically a fragment loader where I have a custom top bar, frame layout (to load fragment in it) and BottomAppBar. Now on main method I'm intialising all the ids and calling two methods i.e. loadFrag() which loads default fragment to display when home activity is first loaded and clicklisteners() which contains click listener implementation of image views and bottom navigation view included in top and bottom bar.
public void loadFrag() {
HomeFrag = new HomeFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, HomeFrag,
HomeFrag.getClass().getSimpleName()).addToBackStack("fragment").commit();
}
public void clickListeners() {
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#SuppressLint("NonConstantResourceId")
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
/* when user opens home fragment, title and back button will be set to gone
in order to display his location on home */
case R.id.homePage:
Fragment fragment = new HomeFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, fragment,
fragment.getClass().getSimpleName()).commit();
iv_location.setVisibility(View.VISIBLE);
tv_location.setVisibility(View.VISIBLE);
iv_edit.setVisibility(View.VISIBLE);
tv_title.setVisibility(View.GONE);
iv_back.setVisibility(View.GONE);
currentFragment = fragment;
break;
/* when user opens wallet fragment, location and edit location icon will be set to gone
in order to display tab title and back icon inside wallet fragment */
case R.id.wallet:
Fragment fragment1 = new WalletFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, fragment1,
fragment1.getClass().getSimpleName()).commit();
iv_location.setVisibility(View.GONE);
tv_location.setVisibility(View.GONE);
iv_edit.setVisibility(View.GONE);
tv_title.setVisibility(View.VISIBLE);
iv_back.setVisibility(View.VISIBLE);
tv_title.setText("Wallet");
currentFragment = fragment1;
break;
/* when user opens myorders fragment, location and edit location icon will be set to gone
in order to display tab title and back icon inside myorders fragment */
case R.id.myorders:
Fragment fragment3 = new MilkCheeseAndYogurtFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, fragment3,
fragment3.getClass().getSimpleName()).commit();
iv_location.setVisibility(View.GONE);
tv_location.setVisibility(View.GONE);
iv_edit.setVisibility(View.GONE);
tv_title.setVisibility(View.VISIBLE);
iv_back.setVisibility(View.VISIBLE);
tv_title.setText("My Orders");
currentFragment = fragment3;
break;
/* when user opens search fragment, location and edit location icon will be set to gone
in order to display tab title and back icon inside search fragment */
case R.id.search:
Fragment fragment4 = new MilkAndMilkPowderFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, fragment4,
fragment4.getClass().getSimpleName()).commit();
iv_location.setVisibility(View.GONE);
tv_location.setVisibility(View.GONE);
iv_edit.setVisibility(View.GONE);
tv_title.setVisibility(View.VISIBLE);
iv_back.setVisibility(View.VISIBLE);
tv_title.setText("Search");
currentFragment = fragment4;
break;
}
return true;
}
});
Now this all is happening on a single thread which is displaying home fragment after a delay of 2-6 seconds approximately on cold start. I have read about AsyncTask and Threads too but I'm unable to find any proper tutorial or code to take hint on how to implement it. If there's any approach better than that please let me know. Ask more if my question is still not clear.
I have a fragment that displays data from APIs, but i dont want to be calling apis everytime the fragment is called.. so am making api call from a different class and and calling a method in the fragment to update UI (textViews)
but am getting null exception for the textViews but data is 100% there
and if i try to hardcode textView.setText("Hello") it works..
one of the task of fragment is change ui !!! you must change ui in activity or fragment
you must use interface . your server class :
public class server {
.
.
.
public void callServer(IServerResponse iResponse){
.
.
.
iResponse.onResponse(//your data such as List or string or json and etc);
}
public interface IServerResponse{
// use parameter type as you want like List or string ,etc..
void onResponse(String data);
}
}
your fragment or activity implement your interface :
public class SomeFragment extends Fragment implements Server.IServerResponse{
....
#Override
public View onCreateView(...){
...
Server server=new Server();
server.callServer(this);
}
#Override
public void IServerResponse(String data){
textview.SetText(data);
}
}
You should create a FrameLayout in your activity
And use this code:
FragmentA newFragment = new FragmentA ();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.container, newFragment).commit();
and than set your text
String editValueName= editName.getText().toString();
String lastStatus = valueStatus.getText().toString();
newFragment .setText(editValueName, lastStatus);
Try for quick fix if it is working for the output of your desire
Make Textview static in class(youractivity) where textview is originated like
public static TextView textview;
And in fragment
if(youractivity.textView!=null){ youractivity.textView.setText("your desire text"); }
Im new to android dev and Im currently struggling with this annoying problem for days.
Tried google and many articles. None helped. Also tried IRC for some on line help but couldnt get a straight answer. Maybe you can direct me in the right direction...
My app is basically a ViewPager that holds a single Fragment class. Inside the Fragment class, there is a switch case block that determines based on position, which image to load from the resources folder. The thing is, I have a TextView View in my parent Activity that needs to get updated according to the current picture. Like an image title.
I used:
TextView tv = (TextView) getActivity().findViewById(R.id.titleTV);
in onCreateView() to get access to that TextView from within the Fragment. And added a:
tv.setText("Picture 1");
for instance, to the switch case block. This way, when a picture is shown, the text view gets updated.
The problem is, the method that retrieves a new Fragment with each slide, getItem(int position) in the parent Activity, gets called twice to load more than one Fragment to memory. This causes the current position to be one int ahead. Meaning, the switch case stands on case 0 for instance and it shows a specific picture, but the text gets updated from case 1.
I cant get it to work properly because of that.
What am I doing wrong??
Thank you
If you are able to determine text based on current fragment position only you can use ViewPager.OnPageChangeListener. In you Activity implement that interface and use it by calling mViewPager.setOnPageChangeListener(SomeOnPageChangeListener). Determine what text put into TextView with OnPageChangeListener.onPageSelected() method.
Unfortunately there is a bug in SDK and onPageSelected() is not called for page at position 0 when it is shown for the first time. You can find workaround under above link, use ViewPager.setCurrentPage(1) or just set text for that position manually in onCreate() method.
Example code:
//activity onCreate()
protected void onCreate(Bundle savedInstanceState) {
...
mTextView = (TextView) findViewById(R.id.text_view);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
String someText = determineText(position)
mTextView.setText(someText);
});
//because onPageSelected will not be called for page 0 first time
String someText = determineText(0)
mTextView.setText(someText);
}
private String determineText(int position){ //static?
//switch?
}
Ok I'll give a piece of code, you can use that, not just for a String but for any data at all that you want to send to the Activity from the Fragment, or even from other type of classes between each other.
That's the type of code is also used on .'setOnSomethingHappenListener(listener);'
public interface TitleChangeListener{
public void onTitleChanged(String title);
}
then on your activity you will
public class MyActivity extends Activity implements TitleChangeListener{
#Override
onTitleChanged(String title){
// set here your value
}
}
then on your fragment
public void MyFragment extends Fragment{
private TitleChangeListener listener;
#Override
public void onAttach(Activity activity){
if(activity instanceof TitleChangeListener)
listener = (TitleChangeListener)activity;
else
// throw some error ???
}
#Override
public void onResume(){
listener.onTitleChanged("my title");
}
}
and remember I typed all of that by heart, there is bound to have some small mistakes.
But just follow the idea and you'll be fine.
I'm having some trouble, and I have done research on the problem but it did not help me.
I have a Main.java class, which is template made pager view of fragments.
I did not modify it in any way, except for getItem() method which now returns my own fragments.
My fragment A is collecting accelerometer data, saving last 120 records in an ArrayList.
It also has graph plots, with Series objects, which I would like to access from fragment B.
This is what I want to do:
In fragment B user presses a button "record data"
This results in fragment A boolean field "recordingOn" changing to true
Now in fragmentA onSensorChange method, after checking for "recordingOn", if it's true it will pass data to an ArrayList that is a field in fragment B
How do I access these fields?
from fragment call
Fragment frag = getActivity().getFragmentManager()..findFragmentByTag("fragment to find tag");
Greensy answer is a valid option (I upvoted him) but you can also refrain from doing so much DataPassing between fragments and let the Activity be a manager for all that.
For that you can create public methods and interfaces in the fragments and let/force the activity implement the interfaces.
Simple example:
public class Act extends Activity implements OnClickListener{
#Override
OnClick(View v){
if(v.getId()==R.id.btn_recordData){
fragA.startRecording();
}
}
}
then FragA you must create that method:
public class FragA extends Fragment{
private boolean isRecording
public void startRecording(){ isRecording = true; // also init the sensor stuff }
public void stopRecording() { isRecording = false; // also stop the sensor stuff }
}
then on FragB you can:
public class FragB extends Fragment{
onCreateView(...){
// initialise all the views and find the button, let's call it Button btn;
btn.setOnClickListener((OnClickListener)getActivity());
}
}
does that make sense?
A way to do that is to use your own Application class and store your ArrayList in there
You can then access it in any point of your application, if you got a Context :
ArrayList<AccelerometerData> myAccelerometerData = ((MyApplication) mContext.getApplicationContext()).getAccelerometerData();
Be carefull about this solution since your ArrayList will be alive during all the application run
I have an Android application with a MainActivity and I do this to create navigational tabs in onCreate:
ActionBar myActionBar = getActionBar();
myActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab = myActionBar.newTab().setText("FirstTab").setIcon(R.drawable.first_tab)
.setTabListener(new TabListener<FirstTabFragment>(this, "FirstTab",
FirstTabFragment.class));
... more tabs ...
The TabListener, I use this from developer.android.com:
http://developer.android.com/reference/android/app/ActionBar.html#newTab():
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
...
public TabListener(Activity activity, String tag, Class<T> clz) { ... }
}
So if a user clicks on the first tab, my fragment FirstTabFragment is called and executes onCreateView.
My problem is, if a user now clicks a button I do the following and I do not know how to switch to the next fragment:
private OnClickListener firstTabListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (v == button1) {
Intent intent = new Intent(???, MyDetailsFragment.class);
startActivity(intent);
} else if (...) {
...
}
}
};
The MyDetailsFragmentshould show details to the selected item (button click), so I want to drill down to the details fragment and want to give some extra data to the new fragment, so the detail fragment knows which details of which selected item it should display.
The selected tab should not change and the back button should go back to the FirstTabFragment page.
I think I should start a new fragment, but it is not possible, the name of the method startActivity tells me that I start a new activity and not a fragment. So, I have to use the MainActivity and put into there the new fragment?
(I do not use the android-support-v4.jar library, because I only target Android 4 devices)
How can I solve this problem? Any ideas?
From the fragment, call a method on the hosting activity, telling it about the button click event. The activity can then do whatever is appropriate.
Personally, I think that totally replacing the contents of a tab is inappropriate in the vast majority of cases, but you are certainly welcome to do it.