Replace a fragment above another fragment when dialog is clicked (viewpager) - java

I am trying to open a fragment, when a dialog is clicked inside another fragment. I am using ActionBarSherlock with Tab. My fragment is attached in the view pager. I have almost done the job. But I can't replace a new fragment inside a view pager. I got an error. I read the thread here. The solution isn't clear.
Error:
10-18 21:34:40.379: E/AndroidRuntime(19618): FATAL EXCEPTION: main
10-18 21:34:40.379: E/AndroidRuntime(19618):
java.lang.IllegalArgumentException: No view found for id 0x7f040032
(com.example.actionbartestwithsherlock:id/pager) for fragment
AllContactsFragment{41fd4ba0 #0 id=0x7f040032} 10-18 21:34:40.379:
E/AndroidRuntime(19618): at
android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:903)
I have three fragment associates with pager named FragmentTab1,FragmentTab2 & FragmentTab3.
My MainActivity & FragmentAdapter looks like below:
public class MainActivity extends SherlockFragmentActivity {
ActionBar.Tab Tab1, Tab2, Tab3, Tab4;
private Context context = this;
// view pager
// Declare Variables
ActionBar actionBar;
ViewPager mPager;
Tab tab;
FragmentAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// set application in portrait mode
ActivityHelper.initialize(this);
actionBar = getSupportActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Locate ViewPager in activity_main.xml
mPager = (ViewPager) findViewById(R.id.pager);
// add an adapter to pager
mPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(),
mPager, actionBar));
addActionBarTabs();
}
private void addActionBarTabs() {
String[] tabs = { "Tab 1", "Tab 2", "Tab 3" };
for (String tabTitle : tabs) {
ActionBar.Tab tab = actionBar.newTab().setText(tabTitle)
.setTabListener(tabListener);
actionBar.addTab(tab);
}
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
}
private ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
mPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
};
class FragmentAdapter extends FragmentPagerAdapter implements
ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
final int TOTAL_PAGES = 3;
public FragmentAdapter(FragmentManager fm, ViewPager pager,
ActionBar actionBar) {
super(fm);
this.mViewPager = pager;
this.mViewPager.setOnPageChangeListener(this);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return FragmentTab1.newInstance();
case 1:
return FragmentTab2.newInstance();
case 2:
return FragmentTab3.newInstance();
default:
throw new IllegalArgumentException(
"The item position should be less or equal to:"
+ TOTAL_PAGES);
}
}
#Override
public int getCount() {
return TOTAL_PAGES;
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
}
}
Now, Inside my first tab FragmentTab1, I open a customized dialog when a button clicks. I want to replace new fragment AllContactsFragment in FragmentTab1 when the dialog options are selected.
FragmentTab1 fragment class:
public class FragmentTab1 extends SherlockFragment implements OnClickListener {
Button btnTest;
ViewPager pager;
LinearLayout layoutBlockNumbers;
LinearLayout layoutContact, layoutCallLog, layoutSMSLog, layoutManually;
Context context;
CustomizedDialog dialog;
private static final int CONTACT_PICKER_RESULT = 1001;
private static final String DEBUG_TAG = "Contact List";
private static final double RESULT_OK = -1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragmenttab1, container,
false);
layoutBlockNumbers = (LinearLayout) rootView
.findViewById(R.id.layoutAddBlockNumbers);
layoutBlockNumbers.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v) {
if (v == layoutCallLog) {
dialog.dismiss();
// want to replace new fragment at position 0 in pager
// problem is here ??? how to open new fragmnet
Fragment allContactsFragment = AllContactsFragment.newInstance();
FragmentTransaction transaction = getChildFragmentManager()
.beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.pager, allContactsFragment).commit();
}
if (v == layoutBlockNumbers) {
// open a dialog
showDialog();
} else if (v == layoutContact) {
openContactList();
dialog.dismiss();
} else if (v == layoutSMSLog) {
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
setUserVisibleHint(true);
}
// open a dialog
private void showDialog() {
dialog = new CustomizedDialog(getActivity());
dialog.setContentView(R.layout.dialog_add_number_type);
dialog.setTitle("Add Black List Number");
//initialize all linear layouts in dialog
layoutCallLog = (LinearLayout) dialog.findViewById(R.id.layoutCallLog);
layoutContact = (LinearLayout) dialog.findViewById(R.id.layoutContact);
layoutSMSLog = (LinearLayout) dialog.findViewById(R.id.layoutSMSLog);
layoutManually = (LinearLayout) dialog
.findViewById(R.id.layoutManually);
// add listener to several linear layout
layoutContact.setOnClickListener(this);
layoutCallLog.setOnClickListener(this);
layoutSMSLog.setOnClickListener(this);
layoutManually.setOnClickListener(this);
dialog.show();
}
public static Fragment newInstance() {
Fragment f = new FragmentTab1();
return f;
}
}
activity_main.xml looks like below :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</android.support.v4.view.ViewPager>
</RelativeLayout>
Can anybody can help me to solve this issue? Sorry for the massive code.

I'm not sure you can do things the way you want to. A ViewPager is not set up the same way a normal container/fragment set up would be. In a ViewPager you're not using fragment transactions to add fragments but rather an adapter that loads instances of fragments from a backing list.
Replacing the fragment would then work as follows:
(1) Create an instance of the fragment you want to add
(2) Add that fragment to the list that is backing your PagerAdapter
(3) Display the new fragment
(4) Remove the old one
The problem with implementing this in your current project is the set up of your adapter. Currently you are using a switch statment that can only return a fixed number of fragments. Your adapter should be set up something like this.
class MyPageAdapter extends FragmentPagerAdapter{
private List<Fragment> fragments
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
Then you can just add a method to your adapter class to add or remove new fragments. If you know the index of the fragment you want to replace accomplishing this should be pretty easy. All you have to do is create a new instance of the contacts fragment, add it to your array or list. This Post explains how a ViewPager handles the adding/removing of new content and how to ensure your new fragment is displayed.

After I read this post I solved the answer.
I just add an ID android:id="#+id/fragmentTabLayout1 to top layout of my fragmenttab1.xml . Then call
new fragment as usual:
Fragment allContactsFragment = AllContactsFragment.newInstance();
FragmentTransaction transaction = getChildFragmentManager()
.beginTransaction();
transaction.addToBackStack(null);
// use this id to replace new fragment
transaction.replace(R.id.fragmentTabLayout1, allContactsFragment).commit();

Related

Swiching tabs programally in TabLayout

I'm new to android programming and I can't find a way to switch between tab1 to tab2 in a TabLayout, when the user clicks a button located in the tab1.
It may be something very simple, but I am clueless in my first app.
I have tried the following at first:
TabLayout.Tab tab = tabLayout.getTabAt(1);
tab.select();
And it used to work, but I changed the code and, at some point, it just didn't work anymore.
I also triedtab.getCustomView().setSelected(true);, but I got NullPointerException. So I checked in a if statement if tab was null, and it wasn't.
And then I tried
tabLayout.setScrollPosition(1,0f,true);
ViewPager viewPager = new ViewPager(mainView.getContext());
viewPager.setCurrentItem(1);
But none of the solutions above worked for me.
Here is my code:
View view;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
try {
view = inflater.inflate(R.layout.fragment_main, container, false);
Button GoB = view.findViewById(R.id.GoB);
final EditText USETV = view.findViewById(R.id.USETV);
final EditText commandEV = view.findViewById(R.id.CommandTV);
final SqlHelper db = new SqlHelper(getContext(), "myDatabase", null, 1);
GoB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
String a = "";
if (USETV.getText().toString().length() > 0) {
a += "USE " + USETV.getText().toString() + " ;";
}
a += commandEV.getText().toString();
String[][] c = db.SqlQuery(a);
LayoutInflater factory = getLayoutInflater();
View resultView = factory.inflate(R.layout.fragment_result, null);
TableLayout tableLayout = resultView.findViewById(R.id.ResultContainer);
tableLayout.removeAllViews();
View mainView = factory.inflate(R.layout.main_activity,null);
TabLayout tabLayout = mainView.findViewById(R.id.tabs);
if (c[0].length > 0 && c[1].length > 0) {
TabLayout.Tab tab = tabLayout.getTabAt(1);
//tab.select();
//tab.getCustomView().setSelected(true);
//tabLayout.setScrollPosition(1,0f,true);
//ViewPager viewPager = new ViewPager(mainView.getContext());
//viewPager.setCurrentItem(1);
//
// do some stuff
}
} catch (Exception e) {
showException(e);
}
}
});
} catch (Exception e) {
showException(e);
}
return view;
}
TabLayout and ViewPager belong to your Activity, so in your Fragment you have to call Activity function to switch tab
Here is an example:
public class MyActivity extends Activity {
private TabLayout mTabLayout;
private ViewPager mViewPager;
#Override
public onCreate(...) {
MyFrament myFragment = new MyFragment(this);
// Add fragment to Viewpager ...
// Attach ViewPager to TabLayout ...
}
public void switchTab(int index) {
// Check index ...
mViewPager.setCurrentItem(index);
}
}
then
public class MyFragment extends Fragment {
private Context mContext;
private Button mButton;
public MyFragment(Context context) {
mContext = context;
}
#Override
public View onCreateView(...) {
...
mButton.setOnClickListener(v->{
((MyActivity)mContext).switchTab(1);
});
...
}
}
Hope this help!
Try putting these two lines inside your button's handler :
ActionBar actionBar = (ActionBar)getActivity().getActionBar();
actionBar.setSelectedNavigationItem(1);
Right Click on your package name
new > activity > tabActivity click ok
Chose layout name whatever you want e.g (Example.java).
Select Navigation style is Action Bar Tabs(which is option 2) and click Finish
5.create two new Fragments
6.Go to the java file here Example.java
After open Example.java file paste the blow code in
SectionsPagerAdapter extends FragmentPagerAdapter
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
switch(position){
case 0:
return new Chats();
case 1:
return new Status();
case 2:
return new Call();
}
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
}

Java Android remove name of Application

I have a fragment and an activity. I want to display name of tags(fragments) but I don't want to show name of application in actionBar.
This is my activity: when I remove an ActionBarActivity I can not use a FragmentManager
public class ObjectListActivity extends ActionBarActivity implements android.support.v7.app.ActionBar.TabListener {
private ViewPager viewPager;
private android.support.v7.app.ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_object_list2);
// View pager for showing many fragments over a single activity
viewPager = (ViewPager) findViewById(R.id.pager);
// Getting fragment manager to control fragments
FragmentManager fragmnetManager = getSupportFragmentManager();
// Setting adapter over view pager
viewPager.setAdapter(new MyAdapter(fragmnetManager));
// Implementing view pager pagechangelistener to navigate between tabs
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int pos) {
// Setting navigation of tabs to actionbar
actionBar.setSelectedNavigationItem(pos);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
// Getting actionbar
actionBar = getSupportActionBar();
// Setting navigation mode to actionbar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Now adding a new tab to action bar and setting title, icon and
// implementing listener
android.support.v7.app.ActionBar.Tab tab1 = actionBar.newTab();
tab1.setText("Wszytskie");
// tab1.setIcon(R.drawable.ic_launcher);
tab1.setTabListener(this);
android.support.v7.app.ActionBar.Tab tab2 = actionBar.newTab();
tab2.setText("Grupy");
tab2.setTabListener(this);
// Now finally adding all tabs to actionbar
actionBar.addTab(tab1);
actionBar.addTab(tab2);
}
#Override
public void onTabReselected(android.support.v7.app.ActionBar.Tab arg0,
FragmentTransaction arg1) {
}
#Override
public void onTabSelected(android.support.v7.app.ActionBar.Tab tab,
FragmentTransaction arg1) {
// Setting current position of tab to view pager
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(android.support.v7.app.ActionBar.Tab arg0,
FragmentTransaction arg1) {
}
}
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
// Getting fragments according to selected position
Fragment fragment = null;
if (i == 0) {
fragment = new FragmentAllObjectActivity();
}
if (i == 1) {
fragment = new FragmentGroupObjectsActivity();
}
// and finally returning fragments
return fragment;
}
#Override
public int getCount() {
// Returning no. of counts of fragments
return 2;
}
}
Inside onTabSelected add the line:
#Override
public void onTabSelected(android.support.v7.app.ActionBar.Tab tab,
FragmentTransaction arg1) {
// Setting current position of tab to view pager
viewPager.setCurrentItem(tab.getPosition());
setTitle(getText(tab.getPosition()));
}
You have to implement a getText() method which return the right text based on the current fragment like:
public String getText(android.support.v7.app.ActionBar.Tab tab){
// if tab == tabType 1 return "Title 1"
// else return "Title 2"
}
Use bellow code in your onCreate method
setTitle("");//it will remove your app name

pass data to another fragment by swipe view with tab android studio,not button

Is it possible to pass a data from fragment to fragment by swipe?
There are many articles teaching us how to pass the data from fragment to fragment, but most of the article or questions had implemented OnClickListener in their first fragment, which used to pass value to another fragment.
But my case is pass the data from two fragments without any button click and finally save them in different tables by clicking button in the last fragment. What can I do to achieve this??
The flow is Information >> WorkForce >>WorkDetailsTable and save them to different table by one button click.
I have tried to work it out but I get NULL value in SQLite. I think I have miss out a lot but have no idea. PLEASE help me...I've been stuck at here for more than two days...Thanks
Tab.java
public class Tab extends ActionBarActivity implements ActionBar.TabListener {
ViewPager Tab;
TabPagerAdapter TabAdapter;
ActionBar actionBar;
public static String name = null;
public static String subContractors = null;
// will be used for data communication
public static Force force_bean;;
public static Info info_bean;
public static Force getForce(){
return force_bean;
}
public static void setForce(Force force){
force_bean=force;
}
public static Info getInfo(){
return info_bean;
}
public static void setInfo(Info info){
info_bean=info;
}
final Activity mActivity = (Activity) this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab1);
info_bean = new Info();
force_bean = new Force();
TabAdapter = new TabPagerAdapter(getSupportFragmentManager());
Tab = (ViewPager) findViewById(R.id.pager);
Tab.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar = ((AppCompatActivity) mActivity).getSupportActionBar();
actionBar.setSelectedNavigationItem(position);
}
});
Tab.setAdapter(TabAdapter);
actionBar = ((AppCompatActivity) mActivity).getSupportActionBar();
//Enable Tabs on Action Bar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Add New Tabs
actionBar.addTab(actionBar.newTab().setText("Information").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Work Force").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Work Details").setTabListener(this));
}
#Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
}
TabPagerAdapter.java
public class TabPagerAdapter extends FragmentStatePagerAdapter {
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
return Information.newInstance("name");
case 1:
return WorkForce.newInstance("SubCon");
case 2:
return WorkDetailsTable.newInstance();
}
return null ;
}
#Override
public int getCount() {
return 3; //No of Tabs you can give your number of tabs
}
Informmation.java
public class Information extends Fragment implements View.OnClickListener {
private Spinner spinner, spinner2, spinner3;
private static String a;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View info = inflater.inflate(R.layout.information, container, false);
dialog = new DateDialog();
spinner = (Spinner)info.findViewById(R.id.spinner);
addItemsOnSpinner();
a= spinner.getSelectedItem().toString();
return info;
}
public static Information newInstance(String a)
{
Information fragment=new Information();
Bundle bundle=new Bundle();
bundle.putString("a",a);
fragment.setArguments(bundle);
return fragment;
}
public void addItemsOnSpinner() {
List<String> list = new ArrayList<String>();
list.add("1 ");
list.add("2");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_dropdown_item, list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
WorkForce.java
public class WorkForce extends Fragment {
private static EditText txt1;
private static String subCon;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View work = inflater.inflate(R.layout.workforce, container, false);
txt1 = (EditText) work.findViewById(R.id.editText);
subCon = txt1.getText().toString();
return work;
}
public static WorkForce newInstance(String subCon) {
WorkForce f = new WorkForce();
Bundle bundle = new Bundle();
bundle.putString("subCon", subCon);
f.setArguments(bundle);
return f;
}
}
WorkDetails.java
private com.example.project.project.API.InfoAPI ts;
private com.example.project.project.API.WorkDetailsAPI WD;
private com.example.project.project.API.WorkForceAPI WF;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View workDetails = inflater.inflate(R.layout.tableworkdetails, container, false);
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
spinnerTra = (Spinner) workDetails.findViewById(R.id.spinner6);
addItemsOnSpinner();
Button btn1 = (Button)workDetails.findViewById(R.id.button2);
WD = new com.example.project.project.API.WorkDetailsAPI(getActivity());
ts = new com.example.project.project.API.InfoAPI(getActivity());
WF = new com.example.project.project.API.WorkForceAPI(getActivity());
a1 = spinnerTra.getSelectedItem().toString();
Bundle bundle = new Bundle();
final String name = bundle.getString("a");
final String subContractors = bundle.getString("subCon");
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
add(name, subContractors);
}
});
return workDetails;
}
public void add(String name,String subContractors)
{
Toast.makeText(getActivity(),+name+subContractors, Toast.LENGTH_SHORT).show();
ts.insertTimeSheet(name);
WF.insertWorkForce(subContractors);
}
Note: My case is pass the data from two fragments without any button click and finally save them in different tables by clicking button in the last fragment.
If I understand your problem correctly, you are essentially implementing something a little bit like a "Wizard" where each step passes information to the next step as you swipe between the tabs or select them.
So in reality your problem is how to get the information out of a fragment when it is deselected and into a fragment when selected.
At the simplest level I would suggest your activity holds the "master" copy of all of the information and passes it into/takes it from each fragment in your tab pager adapter.
You would need some kind of "Domain" object to hold all the information you need to collect. Each tab would only update the bits of information it cares about..
public class WorkData {
string information;
string subCon;
... etc..
}
You add an instance of this to hold the master copy to your "tab" activity:
public class Tab extends ActionBarActivity implements ActionBar.TabListener {
...
WorkData workData = new WorkData();
...
I would then suggest a simple interface that each of your "tab" fragments implement; something like:
public interface DataUpdate {
void setData(WorkData data);
WorkData getData();
}
Each of your tab fragments would implement this interface, updating the WorkData as required..
public class WorkForce extends Fragment implements DataUpdate {
...
private WorkData workData; // this fragment's "copy" of the data
...
#Override
public WorkData getData() {
this.workData.subCon = this.subCon; // Assuming subcon has been updated.. else use txt1.getText();
return this.workData;
}
#Override
public void setData(WorkData workData) {
this.workData = workData;
// Update this page's views with the workData...
// This assumes the fragment has already been created and txt1 is set to a view
txt1.setText(workData.subCon);
this.subCon = workData.subCon; // Actually could just use subCon in workData, but be aware that workData actually points to the Activity's copy (kinda makes getdata redundant.. but I like symmetry and couldn't be bothered making lots of copies of the object).
}
Then you just need to add the code to pass the data backwards and forwards.. in your "Tab" activity which looks like...
#Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
int position = tab.getPosition();
DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
// Pass the master workdata to the selected fragment
dataUpdate.setData(this.workData);
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
int position = tab.getPosition();
DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
// Update the master workdata from the unselected fragment
this.workData = dataUpdate.getData();
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
// This might be pointless, but we'll do it anyway..
int position = tab.getPosition();
DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
// Pass the master workdata to the selected fragment
dataUpdate.setData(this.workData);
}
An important thing to notice here is that your TabPagerAdapter will create a new fragment every time you call getItem().. that will mean that we will never get any updates because each time we try to get the fragment it returns a new, empty fragment. We need to change this so that the fragments are still created when first asked for, but only created once so that we don't keep throwing away our work.
public class TabPagerAdapter extends FragmentStatePagerAdapter {
private static final int NUMBER_OF_TABS = 3;
private Fragment[] tabList = new Fragment[NUMBER_OF_TABS];
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
if (tabList[i] != null) {
// Return a tab we created earlier..
return tabList[i];
} else {
switch (i) {
case 0:
tabList[0] = Information.newInstance("name");
return tabList[0];
case 1:
tabList[1] = WorkForce.newInstance("SubCon");
return tabList[1];
case 2:
tabList[2] = WorkDetailsTable.newInstance();
return tabList[2];
}
}
return null ;
}
#Override
public int getCount() {
return NUMBER_OF_TABS;
}
Hope this helps. Good luck :-)
Although C James provides good tips to solve your problems, I would like to introduce another way without using implementing of interfaces. Please check below link out. If you use an event bus library such a http://square.github.io/otto/, you can easily pass data you want to share among fragments and even activities. Additionally, you can reduce a lot of code line since it only requires Sender(PUBLISHING), Receiver(Subscriber) while implementation of interfaces requires additional lines of code.
Here is a tutorial of Otto libarary.
http://www.vogella.com/tutorials/JavaLibrary-EventBusOtto/article.html
Hope it helps :)
I would more go the Observer Pattern way.
Each Fragments changes an POJO with is rendered in your Fragments in some way. You simply have to Observe the pojo in your Fragments. Changing Fragments will notify interested observers without knowing them.
I believe that's a much cleaner way to implement this.
Fragment A -> PojoInstance.setXY("foo");
Fragment A -> informs the Observers which e.b Informs Fragment B:
Fragment B will see the change tru the Observer.
Because ViewPagers or other Components will cache Fragments thats a way to get information in already created Fragments, even when their are not seen.
You could also try to use an EventBus where you pass the POJO around.
To transfer data from one fragment to another fragment when swipe is performed ,firstly you should get the view of the each fragment.here is the sample code that can help you out a bit.
write this code in Activity:
mviewpager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
mviewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
adapter = ((SOFragmentPagerAdapter) mviewpager.getAdapter());
//getting the view of fragments at positions
if(position==0)
{
View v = null;
Fragment1=(Fragment1)adapter.getFragment(position);
v=fragment1.getMyView();//this is how you get the view
ListView lv=(ListView)v.findViewById(R.id.lv_services);
ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(SOListItemSelectedActivity.this,android.R.layout.simple_list_item_1,soRequestFragment.al_list_of_services);
lv.setAdapter(arrayAdapter);
}
if(position==1)
{
}
}
#Override
public void onPageSelected(int position) {
if(position==0)
{
View v = null;
soRequestFragment=(SORequestFragment)adapter.getFragment(position);
v=soRequestFragment.getMyView();
}
if(position==1)
{
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
mviewpager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
and create a FragmentPagerAdapter as:
public class SOFragmentPagerAdapter extends FragmentPagerAdapter {
HashMap<Integer,Fragment> mPageReferenceMap;
int mNumOfTabs;
public SOFragmentPagerAdapter(FragmentManager fm,int mNumOfTabs) {
super(fm);
this.mNumOfTabs=mNumOfTabs;
mPageReferenceMap=new HashMap<Integer,Fragment>();
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
Fragment1 fragment1=new tFragment1();
mPageReferenceMap.put(position,fragment1);
return fragment1;
case 1:
Fragment2 fragment2=new Fragment2();
mPageReferenceMap.put(position,fragment2);
return fragment2;
default:
return null;
}
}
public Fragment getFragment(int key) {
return mPageReferenceMap.get(key);
}
#Override
public int getCount() {
return 2;
}}
In Fragments add the getmyview() which will return the view of that fragment as:
public void getmyview()
{
return myview;//myview is fragment view which you will return in oncreateview method
}
Note: Viewpager execute onpagescroll first and get the position 0,1 and when you scroll ,views at position 1,2 will execute and page selected 0 will execute.
For tabselections: Tabunselected,Tabselected Tab reselected is the sequence of execution.
so write accordingly in the respective positions of fragments.
Hope this helps you.

FragmentStatePagerAdapter, childFragmentManager and orientation change a bad combination?

Here is my the problem, I have an activity, which includes a Fragment that has a ViewPager using (FragmentStatePagerAdapter), all works perfect when the Activity loads for the first time, but when setting setRetainInstance(true) to the parent fragment (the one with the pager), and orientation changes on the activity, it causes
java.lang.IllegalStateException: No activity
When trying to add the saved fragment, here is the code:
Activity:
public class DetailActivity{
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame_layout_with_progress_container);
...
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
FragmentManager fm = getSupportFragmentManager();
if (savedInstanceState != null) {
Fragment f = fm.findFragmentById(R.id.container);
if(f instanceof DetailPagerFragment){
detailPagerFragment = (DetailPagerFragment) f;
}
}
}
#Override
protected void onPostResume() {
super.onPostResume();
//If fragment is null, create a new instance
if(detailPagerFragment==null){
detailPagerFragment =
DetailContainerFragment.newInstance(details, initialPosition);
}
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, detailPagerFragment);
ft.commit();
}
Note: that i have to save the fragment instance on onCreate because when the code reaches onStart the reference for this fragment was null (this issue is not important for the time it has something to do with the NavigationDrawer), so i need to manually save the instance of the fragment.
Activity layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/container"/>
</RelativeLayout>
ViewPager Fragmentm this class extends for DetailPagerFragment which is a custom pager fragment it only wraps common code for pagers (for example view inflation, uses inflateView method), this is why the pager is added on a fragment instead of directly to the activity:
public class DetailContainerFragment extends DetailPagerFragment {
List<Detail> details;
public static DetailContainerFragment newInstance(List<Detail> details,int selectedPosition) {
DetailContainerFragment df = new DetailContainerFragment();
df.setSelectedPosition(selectedPosition);
df.setDetails(details);
return df;
}
public void setDetails(List<Detail> details) {
this.details = details;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
/**
* Inflates the view to be used by this fragment
*
* #param inflater
* Inflater to use
* #return Inflated view
*/
#Override
public View inflateView(LayoutInflater inflater) {
return inflater.inflate(R.layout.detail_pager_fragment, null);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
DetailStatePagerAdapter detailStatePagerAdapter = new DetailStatePagerAdapter(getChildFragmentManager());
setPagerAdapter(detailStatePagerAdapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
private class DetailStatePagerAdapter extends FragmentStatePagerAdapter {
public DetailStatePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return DetailFragment.newInstance(details.get(position));
}
#Override
public CharSequence getPageTitle(int position) {
return details.get(position).getTitle();
}
#Override
public int getCount() {
return details.size();
}
}
}
I had a similar problem with child fragments in a ViewPager.
The parent fragment created new instances of the child fragments to be used with the ViewPager while the adapter kept instances of the old child fragments used before the configuration change.
I ended up cleaning the ChildFragmentManager before initializing the adapter with it:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mPager = (ViewPager) view.findViewById(R.id.pager);
cleanChildFragments(getChildFragmentManager());
mPagerAdapter = new MyPagerAdapter(getChildFragmentManager(), getTabFragments());
mPager.setAdapter(mPagerAdapter);
}
/**
* This is necessary to have a clean ChildFragmentManager, old fragments might be called otherwise
* #param childFragmentManager
*/
private void cleanChildFragments(FragmentManager childFragmentManager) {
List<Fragment> childFragments = childFragmentManager.getFragments();
if (childFragments != null && !childFragments.isEmpty()) {
FragmentTransaction ft = childFragmentManager.beginTransaction();
for (Fragment fragment : childFragments) {
ft.remove(fragment);
}
ft.commit();
}
}
Maybe this helps someone...

FragmentActivity to Fragment

I haven't found any question like this on here so I wanted to ask. Please keep in mind that I'm new to Fragments & FragmentActivity (not Android) and I don't really know how to work with them quite yet but I'm learning. My question is I want to know how to change from a FragmentActivity to a Fragment so I can incorporate it into my app seamlessly without any errors. The code I want to rid errors of is below
public class Work extends Fragment implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Tattoos", "Piercings", "Social Networks" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.our_work);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
I've tried 3 different ways of doing this by rearranging the code but nothing works. Please help me with this!
EDIT I've tried it this way now
public class Work extends Fragment implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
private String[] tabs = { "Tattoos", "Piercings", "Social Networks" };
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.our_work, container, false);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
return rootView;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
first of all;
a Fragment must be inside a FragmentActivity, that's the first rule,
a FragmentActivity is quite similar to a standart Activity that you already know, besides having some Fragment oriented methods
second thing about Fragments, is that there is one important method you MUST call, wich is onCreateView, where you inflate your layout, think of it as the setContentLayout
here is an example:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_layout, container, false);
return mView;
}
and continu your work based on that mView, so to find a View by id, call mView.findViewById(..);
for the FragmentActivity part:
the xml part "must" have a FrameLayout in order to inflate a fragment in it
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
as for the inflation part
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, new YOUR_FRAGMENT, "TAG").commit();
begin with these, as there is tons of other stuf you must know about fragments and fragment activities, start of by reading something about it (like life cycle) at the android developer site

Categories