java.lang.IllegalStateException activity with viewPager and tabs - java

When I go back from the next activity, always savedInstanceState is null and when I rotate screen or turn back , I get this error:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
I have tried to use in MyFragment
View fragment = (View) inflater.inflate(R.layout.recycler_view, null);
Or
View fragment = (View) inflater.inflate(R.layout.recycler_view, container, false);
or
View fragment = (View) inflater.inflate(R.layout.recycler_view, container);
but i get the same error.
Error log:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3562)
at android.view.ViewGroup.addView(ViewGroup.java:3415)
at android.support.v4.view.ViewPager.addView(ViewPager.java:1342)
at android.view.ViewGroup.addView(ViewGroup.java:3360)
at android.view.ViewGroup.addView(ViewGroup.java:3336)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1094)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1259)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1624)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1106)
at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:447)
....
MainActivity
public class MainActivity extends AppCompatActivity {
static public DrawerLayout mDrawerLayout;
private ArrayList<ArrayList<Article>> articlesHomeList;
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log.d("--MainActivity", "onSaveInstanceState");
// Save the user's current game state
savedInstanceState.putSerializable("articlesHomeList", articlesHomeList);
savedInstanceState.putString("test", "teststetststs");
// Always call the superclass so it can save the view hierarchy state
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState) {
Log.d("--MainActivity", "onRestoreInstanceState");
super.onRestoreInstanceState(savedInstanceState, persistentState);
this.articlesHomeList = (ArrayList<ArrayList<Article>>) savedInstanceState.getSerializable("articlesHomeList");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bundle bundle = getIntent().getExtras();
articlesHomeList = (ArrayList<ArrayList<Article>>) bundle.getSerializable("articlesHomeList");
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(R.string.app_name);
setSupportActionBar(toolbar);
// Setting ViewPager for each Tabs
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
// Set Tabs inside Toolbar
TabLayout tabs = (TabLayout) findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
Bundle bundleAll = new Bundle();
bundleAll.putSerializable("articles", (Serializable) this.articlesHomeList.get(2));
myFragment MyFragment = new MyFragment();
myFragment.setArguments(bundleAll);
AdapterTabs adapter = new AdapterTabs(getSupportFragmentManager());
adapter.addFragment(myFragment, "All");
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(0);
}
#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();
Log.e("Item selected", Integer.toString(id));
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} else if (id == android.R.id.home) {
mDrawerLayout.openDrawer(GravityCompat.START);
}
return super.onOptionsItemSelected(item);
}
myFragment:
public class MyFragment extends Fragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragment = (View) inflater.inflate(R.layout.recycler_view, container, false);
recyclerView = (RecyclerView) fragment.findViewById(R.id.my_recycler_view);
articlesList = (List<Article>) this.getArguments().getSerializable("articles");
ContentAdapter adapter = new ContentAdapter(articlesList);
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return recyclerView;
}
...
}
EDIT
I have added to MainActivity:
if (savedInstanceState != null) {
this.articlesHomeList = (ArrayList<ArrayList<Article>>) savedInstanceState.getSerializable("articlesHomeList");
this.renderTabs(viewPager);
} else if (getIntent().getExtras() != null) {
Bundle bundle = getIntent().getExtras();
articlesHomeList = (ArrayList<ArrayList<Article>>) bundle.getSerializable("articlesHomeList");
this.renderTabs(viewPager);
} else {
this.loadArticlesHome(viewPager);
}
But always savedInstanceState is null.

In the onCreateView method of your MyFragment fragment, change
return recyclerView;
to
return fragment;
You should return the fragment's view container, not the RecyclerView's. You see : the onCreateView method is called to have the fragment instantiate its user interface view, not just a single component of it (in your case the RecyclerView).
EDIT:
As #BlackBelt said, the app crashes because the RecyclerView has already a parent, defined in the layout, and it can't have two (the one in the layout and the ViewPager) : which is clearly what the exception says
java.lang.IllegalStateException: The specified child already has a
parent

Related

Having trouble when passing string with bundle from MainActivity to Fragment in android

Im having trouble when passing a test string from MainActivity to TabFragment_malica1. I get "Attempt to invoke virtual method .. on a null object" error. I can see that bundle is a null object with an if statement, but i cannot figure out what did i do wrong. Any help would be appreciated!
MAIN ACTIVITY
public class MainActivity extends AppCompatActivity {
String varTest = new String();
String[] testArray = new String[3];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText(R.string.tab1));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
sendData();
public void sendData() {
varTest = "TEST-TEST-TEST";
//PACKING DATA IN A BUNDLE
Bundle bundle = new Bundle();
bundle.putString("TEST", varTest);
//PASSING DATA OVER THE BUNDLE TO FRAGMENT
TabFragment_malica1 myFragment = new TabFragment_malica1();
myFragment.setArguments(bundle);
//TEST BUNDLE
Log.d("MAIN FRAGMENT DATA:", String.valueOf(bundle));
}
}
FRAGMENT
public class TabFragment_malica1 extends Fragment {
public TabFragment_malica1() {
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = this.getArguments();
if (bundle != null) {
String text = bundle.getString("TEST");
Log.d("TEST LOG", text);
} else {
Log.d("ERROR", "ERROR!");
}
return inflater.inflate(R.layout.tab_fragment_malica1, container, false);
}
}

Switch tabs inside a Fragment from Drawer Menu

I have a TabLayout in a Fragment. I’m trying to switch tabs using DrawerLayout item. Not sure how to access the TabLayout from the parent Activity. Checked everywhere, to no avail.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize Toolbar and set it as the Action Bar
mToolbar = (Toolbar) findViewById(R.id.mToolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
// Inflate the TabFragment as the first one
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.containerView, new TabFragment()).commit();
// Initialize Drawer Menu
mDrawerLayout = (DrawerLayout) findViewById(R.id.mDrawerLayout);
mNavigationView = (NavigationView) findViewById(R.id.mNavigationView);
headerLayout = mNavigationView.getHeaderView(0);
// Set click events for the Drawer Menu items
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// Close the Drawer Menu when an item is clicked
mDrawerLayout.closeDrawers();
switch (menuItem.getItemId()) {
case R.id.menuLessons:
return true;
case R.id.menuCheatSheet:
return true;
case R.id.menuMyProfile:
startActivity(new Intent(MainActivity.this, MyProfileActivity.class));
overridePendingTransition(R.anim.zoom_in, R.anim.fade_out);
return true;
default:
return true;
}
}
});
}
}
TabFragment.java
public class TabFragment extends Fragment {
public TabLayout mTabLayout;
public ViewPager mViewPager;
public static int int_items = 2;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the Tab Layout and setup View Pager
View x = inflater.inflate(R.layout.layout_tabs, null);
mTabLayout = (TabLayout) x.findViewById(R.id.mTabLayout);
mViewPager = (ViewPager) x.findViewById(R.id.mViewPager);
// Setup Adapter for the View Pager
mViewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
return x;
}
private class MyAdapter extends FragmentPagerAdapter {
MyAdapter(FragmentManager fm) {
super(fm);
}
// Return Fragment with respect to position
#Override
public Fragment getItem(int position) {
switch(position) {
case 0 : return new LessonsFragment();
case 1 : return new CheatSheetFragment();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
// Return title of the tab according to the position
#Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0 :
return "Lessons";
case 1 :
return "Cheat Sheet";
}
return null;
}
}
public void setCurrentTab(int tab_index) {
FragmentTabHost mTabHost = (FragmentTabHost)getActivity().findViewById(android.R.id.tabhost);
mTabHost.setCurrentTab(tab_index);
}
}
To get an instance to a Fragment in an activity, use:
Fragment tabFragment = (TabFragment) getSupportFragmentManager().findFragmentById(R.id.containerView);
Once you have this, you can then call your method:
tabFragment.setCurrentTab(/*tab index*/);
That answers the question, however I would consider using a ViewPager or simply sticking with tapping tabs to move to them instead of doing it view the nav drawer.

New fragment on button click from another fragment?

can anyone point me in the right direction and tell me what I'm doing wrong?
I have here a fragment with a button. When the button is pressed, it needs to replace the current fragment and load a new one. I've figured how to go from Fragment to Activity, and Activity to Fragment, just not Fragment to Fragment. I'm aware this question has been asked a few times but I'm just so new I couldn't figure it out myself.
public class FragmentName extends Fragment {
public FragmentName() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_name, container, false);
Button ID = (Button) rootView.findViewById(R.id.buttonID);
ID.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentName NAME = new FragmentName();
fragmentTransaction.replace(R.id.main_container, NAME);
fragmentTransaction.commit();
}
});
return rootView;
}
}
I think you are not initialising the FragmentManager. Without FragmentManager it is not possible to replace,update,create any fragment. Beacuse it is responsible replace or deleting any fragment. Hope this will help.
public class FragmentName extends Fragment {
public FragmentName() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_name, container, false);
Button ID = (Button) rootView.findViewById(R.id.buttonID);
ID.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FragmentName NAME = new FragmentName();
fragmentTransaction.replace(R.id.main_container, NAME);
fragmentTransaction.commit();
}
});
return rootView;
}
}

setText in fragment from another activity not related with fragment

i wanna set textView in fragment from another activity which this activity is not MainActivity has fragment transaction ..
already tried some method from the other related article which related with my problem, but got an error..
here's my method inside fragment to recieve from another activity
Fragment A
public class FragmentA extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ProgressDialog pDialog = new ProgressDialog(getContext());
pDialog.setCancelable(false);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflating view layout
View layout = inflater.inflate(R.layout.fragment_A, container, false);
//Put Data to id fragment
valueName = (TextView) layout.findViewById(R.id.valueNameNav);
valueStatus = (TextView) layout.findViewById(R.id.valueStatusNav);
}
public void setText(String name, String status){
valueName = (TextView) getView().findViewById(R.id.valueNameNav);
valueName.setText(name);
valueStatus = (TextView) getView().findViewById(R.id.valueStatusNav);
valueStatus.setText(status);
}
}
and this is how i call setText method in fragment from activity
String editValueName= editName.getText().toString();
String lastStatus = valueStatus.getText().toString();
FragmentA mFragment = (FragmentA )
getSupportFragmentManager().findFragmentById(R.id.fragment_A);
mFragment.setText(editValueName, lastStatus);
but got an error like this
java.lang.NullPointerException: Attempt to invoke virtual method 'void
com.example.study.fragment.fragmentA.setText(java.lang.String,
java.lang.String)' on a null object reference
100% sure there's a data string on string getText
Create a FrameLayout in your activity with id container with height width to MATCH_PARENT
Then add fragment in your activity like this
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);
You can useing store SharedPreferences for save your string and load it in every where.Of course, if you like to change your code.
No need to findView in setText method you should do in this way and it will work
public class FragmentA extends Fragment {
TextView valueName,valueStatus ;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ProgressDialog pDialog = new ProgressDialog(getContext());
pDialog.setCancelable(false);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflating view layout
View layout = inflater.inflate(R.layout.fragment_A, container, false);
//Put Data to id fragment
valueName = (TextView) layout.findViewById(R.id.valueNameNav);
valueStatus = (TextView) layout.findViewById(R.id.valueStatusNav);
return layout;
}
public void setText(String name, String status){
valueName.setText(name);
valueStatus.setText(status);
}
}
Try to do like this and make sure your fragment is attached with activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grupos);
if(savedInstanceState == null)
{
fragment = new FragmentA();
fragment.setTag(R.id.myfragmentId);
getFragmentManager().beginTransaction()
.add(R.id.container, fragment).commit();
}
else
{
if(fragment == null)
{
fragment = (FragmentA) getFragmentManager().findFragmentByTag(R.id.myfragmentId);
}
}
}

Unable to access a ListFragment

I have a MainActivity like this
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} }
and this
public class MyListFragment extends ListFragment implements OnItemClickListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_fragment, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.Planets, android.R.layout.simple_list_item_1);
setListAdapter(adapter);
getListView().setOnItemClickListener(this);
int count = getListView().getCount();
getListView().setSelection(getListView().getCount() - 1);
test();
}
public void test(){
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.Planets, android.R.layout.simple_list_item_1);
setListAdapter(adapter);
getListView().setOnItemClickListener(this);
int count = getListView().getCount();
getListView().setSelection(getListView().getCount() - 1);
Toast.makeText(getActivity(), "ccc"+count, Toast.LENGTH_SHORT)
.show();
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(getActivity(), "Item: " + position, Toast.LENGTH_SHORT)
.show();
} }
The activity_main.xml has a
fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.mike.mqtt.MyListFragment"
android:id="#+id/fragment_content" />
When the application starts I get the fragment_content filled up with some rows.
How can I access the ListFragment(MyListFragment.java) from inside the MainActivity.java in the onCreate.
When I press a button the get the ListFragment content count, and to set focus at the end of the list.
I have no idea.Thank you.
MyListFragment fragment = (MyListFragment) getFragmentManager().findFragmentById(R.id.fragment_content)
I avoid using fragments in XML as it alows me to replace them on-the-fly. I usually use something like this:
private MyListFragment mListFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// the usual business
FragmentManager fm = getSupportFragmentManager();
if (savedInstanceState == null) {
// the activity opened for the first time, we create and commit fragment
mListFragment = new MyListFragment();
fm.beginTransaction().replace(android.R.id.content, f).commit);
} else {
// activity is recreating so it's safe to find already added fragments
mListFragment = fm.findFragmentById(android.R.id.content);
}
}

Categories

Resources